]> git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.suite.ui/src/org/argeo/suite/ui/ArgeoSuiteApp.java
Ignore target directories.
[gpl/argeo-suite.git] / org.argeo.suite.ui / src / org / argeo / suite / ui / ArgeoSuiteApp.java
1 package org.argeo.suite.ui;
2
3 import static org.argeo.cms.ui.CmsView.CMS_VIEW_UID_PROPERTY;
4
5 import java.util.Collections;
6 import java.util.HashMap;
7 import java.util.HashSet;
8 import java.util.Map;
9 import java.util.Set;
10 import java.util.SortedMap;
11 import java.util.TreeMap;
12
13 import javax.jcr.Node;
14 import javax.jcr.RepositoryException;
15 import javax.jcr.Session;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19 import org.argeo.cms.ui.AbstractCmsApp;
20 import org.argeo.cms.ui.CmsTheme;
21 import org.argeo.cms.ui.CmsUiProvider;
22 import org.argeo.cms.ui.CmsView;
23 import org.argeo.cms.ui.dialogs.CmsFeedback;
24 import org.argeo.cms.ui.util.CmsEvent;
25 import org.argeo.cms.ui.util.CmsUiUtils;
26 import org.argeo.entity.EntityNames;
27 import org.argeo.entity.EntityTypes;
28 import org.argeo.jcr.Jcr;
29 import org.argeo.jcr.JcrUtils;
30 import org.argeo.suite.RankingKey;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.widgets.Composite;
33 import org.eclipse.swt.widgets.Control;
34 import org.osgi.service.event.Event;
35 import org.osgi.service.event.EventHandler;
36
37 /** The Argeo Suite App. */
38 public class ArgeoSuiteApp extends AbstractCmsApp implements EventHandler {
39 private final static Log log = LogFactory.getLog(ArgeoSuiteApp.class);
40
41 public final static String PID_PREFIX = "argeo.suite.ui.";
42 public final static String HEADER_PID = PID_PREFIX + "header";
43 public final static String LEAD_PANE_PID = PID_PREFIX + "leadPane";
44 public final static String LOGIN_SCREEN_PID = PID_PREFIX + "loginScreen";
45 public final static String DASHBOARD_PID = PID_PREFIX + "dashboard";
46 public final static String RECENT_ITEMS_PID = PID_PREFIX + "recentItems";
47
48 private final static String DEFAULT_UI_NAME = "app";
49 private final static String DEFAULT_THEME_ID = "org.argeo.suite.theme.default";
50
51 private SortedMap<RankingKey, CmsUiProvider> uiProviders = Collections.synchronizedSortedMap(new TreeMap<>());
52
53 // TODO make more optimal or via CmsSession/CmsView
54 private Map<String, ArgeoSuiteUi> managedUis = new HashMap<>();
55
56 // private CmsUiProvider headerPart = null;
57
58 public void init(Map<String, String> properties) {
59 if (log.isDebugEnabled())
60 log.info("Argeo Suite App started");
61 }
62
63 public void destroy(Map<String, String> properties) {
64 for (ArgeoSuiteUi ui : managedUis.values())
65 if (!ui.isDisposed())
66 ui.dispose();
67 if (log.isDebugEnabled())
68 log.info("Argeo Suite App stopped");
69
70 }
71
72 @Override
73 public Set<String> getUiNames() {
74 HashSet<String> uiNames = new HashSet<>();
75 uiNames.add(DEFAULT_UI_NAME);
76 return uiNames;
77 }
78
79 @Override
80 public Composite initUi(Composite parent) {
81 String uiName = parent.getData(UI_NAME_PROPERTY) != null ? parent.getData(UI_NAME_PROPERTY).toString() : null;
82 CmsView cmsView = CmsView.getCmsView(parent);
83 if (cmsView == null)
84 throw new IllegalStateException("No CMS view is registered.");
85 CmsTheme theme = getTheme(uiName);
86 if (theme != null)
87 CmsTheme.registerCmsTheme(parent.getShell(), theme);
88 ArgeoSuiteUi argeoSuiteUi = new ArgeoSuiteUi(parent, SWT.NONE);
89 String uid = cmsView.getUid();
90 managedUis.put(uid, argeoSuiteUi);
91 argeoSuiteUi.addDisposeListener((e) -> {
92 managedUis.remove(uid);
93 if (log.isDebugEnabled())
94 log.debug("Suite UI " + uid + " has been disposed.");
95 });
96 refreshUi(argeoSuiteUi, null);
97 return argeoSuiteUi;
98 }
99
100 @Override
101 public String getThemeId(String uiName) {
102 // TODO make it configurable
103 return DEFAULT_THEME_ID;
104 }
105
106 @Override
107 public void refreshUi(Composite parent, String state) {
108 try {
109 Node context = null;
110 ArgeoSuiteUi ui = (ArgeoSuiteUi) parent;
111 refreshPart(findUiProvider(HEADER_PID, context), ui.getHeader(), context);
112 CmsView cmsView = CmsView.getCmsView(parent);
113 if (cmsView.isAnonymous()) {
114 ui.refreshBelowHeader(false);
115 refreshPart(findUiProvider(LOGIN_SCREEN_PID, context), ui.getBelowHeader(), context);
116 } else {
117 try {
118 if (ui.getSession() == null)
119 ui.setSession(getRepository().login());
120 context = ui.getSession().getRootNode();
121
122 } catch (RepositoryException e) {
123 e.printStackTrace();
124 }
125 ui.refreshBelowHeader(true);
126
127 ui.addLayer(ArgeoSuiteUi.DASHBOARD_LAYER);
128 ui.addLayer("documents");
129 ui.addLayer("locations");
130 ui.addLayer("people");
131 ui.switchToLayer(ArgeoSuiteUi.DASHBOARD_LAYER);
132
133 refreshPart(findUiProvider(DASHBOARD_PID, context), ui.getTabbedArea().getCurrent(), context);
134 refreshPart(findUiProvider(LEAD_PANE_PID, context), ui.getLeadPane(), context);
135 refreshPart(findUiProvider(RECENT_ITEMS_PID, context), ui.getEntryArea(), context);
136 }
137 ui.layout(true, true);
138 } catch (Exception e) {
139 CmsFeedback.show("Unexpected exception", e);
140 }
141 }
142
143 private void refreshPart(CmsUiProvider uiProvider, Composite part, Node context) {
144 CmsUiUtils.clear(part);
145 uiProvider.createUiPart(part, context);
146 }
147
148 private CmsUiProvider findUiProvider(String pid, Node context) {
149 CmsUiProvider found = null;
150 if (pid != null) {
151 SortedMap<RankingKey, CmsUiProvider> subMap = uiProviders.subMap(RankingKey.minPid(pid),
152 RankingKey.maxPid(pid));
153 providers: for (RankingKey key : subMap.keySet()) {
154 if (key.getPid() == null || !key.getPid().equals(pid))
155 break providers;
156 found = subMap.get(key);
157 }
158 if (found != null)
159 return found;
160 }
161
162 if (found == null && context != null) {
163 SortedMap<RankingKey, CmsUiProvider> subMap = null;
164 String dataType = null;
165 if (Jcr.isNodeType(context, EntityTypes.ENTITY_ENTITY)) {
166 dataType = Jcr.get(context, EntityNames.ENTITY_TYPE);
167 subMap = uiProviders.subMap(RankingKey.minDataType(dataType), RankingKey.maxDataType(dataType));
168 }
169 providers: for (RankingKey key : subMap.keySet()) {
170 if (key.getDataType() == null || !key.getDataType().equals(dataType))
171 break providers;
172 found = subMap.get(key);
173 }
174 if (found == null)
175 found = uiProviders.get(new RankingKey(null, null, null, dataType, null));
176 if (found != null)
177 return found;
178 }
179
180 // nothing
181 if (log.isWarnEnabled())
182 log.warn("No UI provider found for" + (pid != null ? " pid " + pid : "")
183 + (context != null ? " " + context : ""));
184 return new CmsUiProvider() {
185
186 @Override
187 public Control createUi(Composite parent, Node context) throws RepositoryException {
188 return parent;
189 }
190 };
191 }
192
193 @Override
194 public void setState(Composite parent, String state) {
195 CmsView cmsView = CmsView.getCmsView(parent);
196 // for the time being we systematically open a session, in order to make sure
197 // that home is initialised
198 Session session = null;
199 try {
200 if (state != null && state.startsWith("/")) {
201 String path = state.substring(1);
202 String workspace;
203 if (path.equals("")) {
204 workspace = null;
205 path = "/";
206 } else {
207 int index = path.indexOf('/');
208 if (index == 0) {
209 log.error("Cannot interpret // " + state);
210 cmsView.navigateTo("~");
211 return;
212 } else if (index > 0) {
213 workspace = path.substring(0, index);
214 path = path.substring(index);
215 } else {// index<0, assuming root node
216 workspace = path;
217 path = "/";
218 }
219 }
220 session = getRepository().login(workspace);
221
222 Node node = session.getNode(path);
223
224 refreshEntityUi(null, node);
225 }
226 } catch (RepositoryException e) {
227 log.error("Cannot load state " + state, e);
228 cmsView.navigateTo("~");
229 } finally {
230 JcrUtils.logoutQuietly(session);
231 }
232 }
233
234 private void refreshEntityUi(Composite parent, Node context) {
235 }
236
237 /*
238 * Dependency injection.
239 */
240
241 public void addUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
242 RankingKey partKey = new RankingKey(properties);
243 // String servicePid = properties.get(Constants.SERVICE_PID);
244 // if (servicePid == null) {
245 // log.error("No service pid found for " + uiProvider.getClass() + ", " + properties);
246 // } else {
247 if (partKey.getPid() != null || partKey.getDataType() != null) {
248 uiProviders.put(partKey, uiProvider);
249 if (log.isDebugEnabled())
250 log.debug("Added UI provider " + partKey + " (" + uiProvider.getClass().getName() + ") to CMS app.");
251 }
252 // }
253
254 }
255
256 public void removeUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
257 RankingKey partKey = new RankingKey(properties);
258 // String servicePid = properties.get(Constants.SERVICE_PID);
259 uiProviders.remove(partKey);
260
261 }
262
263 @Override
264 public void handleEvent(Event event) {
265
266 // Specific UI related events
267 ArgeoSuiteUi ui = getRelatedUi(event);
268 if (isTopic(event, SuiteEvent.refreshPart)) {
269 Node node = Jcr.getNodeById(ui.getSession(), get(event, SuiteEvent.NODE_ID));
270 ui.getTabbedArea().view(findUiProvider(DASHBOARD_PID, node), node);
271 // ui.layout(true, true);
272 } else if (isTopic(event, SuiteEvent.openNewPart)) {
273 Node node = Jcr.getNodeById(ui.getSession(), get(event, SuiteEvent.NODE_ID));
274 ui.getTabbedArea().open(findUiProvider(DASHBOARD_PID, node), node);
275 // ui.layout(true, true);
276 } else if (isTopic(event, SuiteEvent.switchLayer)) {
277 String layer = get(event, SuiteEvent.LAYER);
278 ui.switchToLayer(layer);
279 }
280
281 }
282
283 private ArgeoSuiteUi getRelatedUi(Event event) {
284 return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY));
285 }
286
287 private static boolean isTopic(Event event, CmsEvent cmsEvent) {
288 return event.getTopic().equals(cmsEvent.topic());
289 }
290
291 private static String get(Event event, String key) {
292 Object value = event.getProperty(key);
293 if (value == null)
294 throw new IllegalArgumentException("Property " + key + " must be set");
295 return value.toString();
296
297 }
298 }