]> git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.swt/src/org/argeo/app/swt/ux/SwtArgeoApp.java
Update Argeo Build
[gpl/argeo-suite.git] / swt / org.argeo.app.swt / src / org / argeo / app / swt / ux / SwtArgeoApp.java
1 package org.argeo.app.swt.ux;
2
3 import static org.argeo.api.cms.ux.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.List;
9 import java.util.Locale;
10 import java.util.Map;
11 import java.util.Objects;
12 import java.util.Set;
13 import java.util.TreeMap;
14 import java.util.TreeSet;
15
16 import javax.xml.namespace.QName;
17
18 import org.argeo.api.acr.Content;
19 import org.argeo.api.acr.ContentRepository;
20 import org.argeo.api.acr.spi.ProvidedSession;
21 import org.argeo.api.cms.CmsConstants;
22 import org.argeo.api.cms.CmsEvent;
23 import org.argeo.api.cms.CmsEventSubscriber;
24 import org.argeo.api.cms.CmsLog;
25 import org.argeo.api.cms.CmsSession;
26 import org.argeo.api.cms.ux.CmsTheme;
27 import org.argeo.api.cms.ux.CmsUi;
28 import org.argeo.api.cms.ux.CmsView;
29 import org.argeo.app.api.AppUserState;
30 import org.argeo.app.api.EntityConstants;
31 import org.argeo.app.api.EntityName;
32 import org.argeo.app.api.EntityType;
33 import org.argeo.app.api.RankedObject;
34 import org.argeo.app.ux.AbstractArgeoApp;
35 import org.argeo.app.ux.AppUi;
36 import org.argeo.app.ux.SuiteUxEvent;
37 import org.argeo.cms.LocaleUtils;
38 import org.argeo.cms.Localized;
39 import org.argeo.cms.swt.CmsSwtUtils;
40 import org.argeo.cms.swt.acr.SwtUiProvider;
41 import org.argeo.cms.swt.dialogs.CmsFeedback;
42 import org.argeo.cms.util.LangUtils;
43 import org.argeo.cms.ux.CmsUxUtils;
44 import org.argeo.eclipse.ui.specific.UiContext;
45 import org.eclipse.swt.SWT;
46 import org.eclipse.swt.events.DisposeEvent;
47 import org.eclipse.swt.events.DisposeListener;
48 import org.eclipse.swt.widgets.Composite;
49 import org.osgi.framework.Constants;
50
51 /** The Argeo Suite App. */
52 public class SwtArgeoApp extends AbstractArgeoApp implements CmsEventSubscriber {
53 private final static CmsLog log = CmsLog.getLog(SwtArgeoApp.class);
54
55 public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath";
56 public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName";
57 public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId";
58 public final static String DEFAULT_LAYER_PROPERTY = "defaultLayer";
59 public final static String SHARED_PID_PREFIX_PROPERTY = "sharedPidPrefix";
60
61 private final static String LOGIN = "login";
62 private final static String HOME_STATE = "~";
63
64 private String publicBasePath = null;
65
66 private String appPid;
67 private String pidPrefix;
68 private String sharedPidPrefix;
69
70 // private String headerPid;
71 // private String footerPid;
72 // private String leadPanePid;
73 // private String adminLeadPanePid;
74 // private String loginScreenPid;
75
76 private String defaultUiName = "app";
77 private String adminUiName = "admin";
78
79 // FIXME such default names make refactoring more dangerous
80 @Deprecated
81 private String defaultLayerPid = "argeo.suite.ui.dashboardLayer";
82 @Deprecated
83 private String defaultThemeId = "org.argeo.app.theme.default";
84
85 // TODO use QName as key for byType
86 private Map<String, RankedObject<SwtUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
87 private Map<String, RankedObject<SwtUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
88 private Map<String, RankedObject<SwtAppLayer>> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>());
89 private Map<String, RankedObject<SwtAppLayer>> layersByType = Collections.synchronizedSortedMap(new TreeMap<>());
90
91 // private CmsUserManager cmsUserManager;
92
93 // TODO make more optimal or via CmsSession/CmsView
94 private Map<String, SwtAppUi> managedUis = Collections.synchronizedMap(new HashMap<>());
95
96 // ACR
97 private ContentRepository contentRepository;
98 private AppUserState appUserState;
99 // JCR
100 // private Repository repository;
101
102 public void start(Map<String, Object> properties) {
103 for (SuiteUxEvent event : SuiteUxEvent.values()) {
104 getCmsContext().getCmsEventBus().addEventSubscriber(event.topic(), this);
105 }
106
107 if (log.isDebugEnabled())
108 log.info("Argeo Suite App started");
109
110 if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY))
111 defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY);
112 if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY))
113 defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY);
114 if (properties.containsKey(DEFAULT_LAYER_PROPERTY))
115 defaultLayerPid = LangUtils.get(properties, DEFAULT_LAYER_PROPERTY);
116 sharedPidPrefix = LangUtils.get(properties, SHARED_PID_PREFIX_PROPERTY);
117 publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY);
118
119 if (properties.containsKey(Constants.SERVICE_PID)) {
120 appPid = properties.get(Constants.SERVICE_PID).toString();
121 int lastDotIndex = appPid.lastIndexOf('.');
122 if (lastDotIndex >= 0) {
123 pidPrefix = appPid.substring(0, lastDotIndex);
124 }
125 } else {
126 // TODO doe it make sense to accept that?
127 appPid = "<unknown>";
128 }
129
130 Objects.requireNonNull(contentRepository, "Content repository must be provided");
131 Objects.requireNonNull(appUserState, "App user state must be provided");
132 // if (pidPrefix == null)
133 // throw new IllegalArgumentException("PID prefix must be set.");
134
135 // headerPid = pidPrefix + "header";
136 // footerPid = pidPrefix + "footer";
137 // leadPanePid = pidPrefix + "leadPane";
138 // adminLeadPanePid = pidPrefix + "adminLeadPane";
139 // loginScreenPid = pidPrefix + "loginScreen";
140 }
141
142 public void stop(Map<String, Object> properties) {
143 for (SwtAppUi ui : managedUis.values())
144 if (!ui.isDisposed() && !ui.getDisplay().isDisposed()) {
145 ui.getDisplay().syncExec(() -> ui.dispose());
146 }
147 managedUis.clear();
148 if (log.isDebugEnabled())
149 log.info("Argeo Suite App stopped");
150
151 }
152
153 @Override
154 public Set<String> getUiNames() {
155 HashSet<String> uiNames = new HashSet<>();
156 uiNames.add(defaultUiName);
157 uiNames.add(adminUiName);
158 return uiNames;
159 }
160
161 @Override
162 public CmsUi initUi(Object parent) {
163 Composite uiParent = (Composite) parent;
164 String uiName = uiParent.getData(UI_NAME_PROPERTY) != null ? uiParent.getData(UI_NAME_PROPERTY).toString()
165 : null;
166 CmsView cmsView = CmsSwtUtils.getCmsView(uiParent);
167 if (cmsView == null)
168 throw new IllegalStateException("No CMS view is registered.");
169 CmsTheme theme = getTheme(uiName);
170 if (theme != null)
171 CmsSwtUtils.registerCmsTheme(uiParent.getShell(), theme);
172 SwtAppUi argeoSuiteUi = new SwtAppUi(uiParent, SWT.INHERIT_DEFAULT);
173 String uid = cmsView.getUid();
174 managedUis.put(uid, argeoSuiteUi);
175 argeoSuiteUi.addDisposeListener(new CleanUpUi(uid));
176 // argeoSuiteUi.addDisposeListener((e) -> {
177 // managedUis.remove(uid);
178 // if (log.isDebugEnabled())
179 // log.debug("Suite UI " + uid + " has been disposed.");
180 // });
181 // Display.getCurrent().disposeExec(() -> {
182 // if (managedUis.containsKey(uid)) {
183 // managedUis.remove(uid);
184 // if (log.isDebugEnabled())
185 // log.debug("Suite UI " + uid + " has been disposed from Display#disposeExec().");
186 // }
187 // });
188 return argeoSuiteUi;
189 }
190
191 @Override
192 public String getThemeId(String uiName) {
193 String themeId = System.getProperty("org.argeo.app.theme.default");
194 if (themeId != null)
195 return themeId;
196 return defaultThemeId;
197 }
198
199 @Override
200 public void refreshUi(CmsUi cmsUi, String state) {
201 try {
202 Content context = null;
203 SwtAppUi ui = (SwtAppUi) cmsUi;
204
205 String uiName = Objects.toString(ui.getParent().getData(UI_NAME_PROPERTY), null);
206 if (uiName == null)
207 throw new IllegalStateException("UI name should not be null");
208 CmsView cmsView = CmsSwtUtils.getCmsView(ui);
209
210 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, cmsView);
211
212 SwtUiProvider headerUiProvider = findStructuralUiProvider(SwtAppUi.Structural.header.name());
213 SwtUiProvider footerUiProvider = findStructuralUiProvider(SwtAppUi.Structural.footer.name());
214 SwtUiProvider leadPaneUiProvider;
215 if (adminUiName.equals(uiName)) {
216 leadPaneUiProvider = findStructuralUiProvider(SwtAppUi.Structural.adminLeadPane.name());
217 } else {
218 leadPaneUiProvider = findStructuralUiProvider(SwtAppUi.Structural.leadPane.name());
219 }
220
221 Localized appTitle = null;
222 if (headerUiProvider instanceof DefaultHeader) {
223 appTitle = ((DefaultHeader) headerUiProvider).getTitle();
224 }
225 ui.setTitle(appTitle);
226
227 if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login
228 ui.logout();
229 ui.setLoginScreen(true);
230 if (headerUiProvider != null)
231 refreshPart(headerUiProvider, ui.getHeader(), context);
232 ui.refreshBelowHeader(false);
233 SwtUiProvider loginScreenUiProvider = findStructuralUiProvider(SwtAppUi.Structural.loginScreen.name());
234 refreshPart(loginScreenUiProvider, ui.getBelowHeader(), context);
235 if (footerUiProvider != null)
236 refreshPart(footerUiProvider, ui.getFooter(), context);
237 ui.layout(true, true);
238 setState(ui, LOGIN);
239 } else {
240 if (LOGIN.equals(state))
241 state = null;
242 if (ui.isLoginScreen()) {
243 ui.setLoginScreen(false);
244 }
245 CmsSession cmsSession = cmsView.getCmsSession();
246 if (ui.getUserDir() == null) {
247 // FIXME NPE on CMSSession when logging in from anonymous
248 if (cmsSession == null || cmsView.isAnonymous()) {
249 assert publicBasePath != null;
250 Content userDir = contentSession
251 .get(Content.ROOT_PATH + CmsConstants.SYS_WORKSPACE + publicBasePath);
252 ui.setUserDir(userDir);
253 } else {
254 Content userDir = appUserState.getOrCreateSessionDir(cmsSession);
255 ui.setUserDir(userDir);
256 // Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
257 // Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
258 // return node;
259 // });
260 // Content userDir = contentSession
261 // .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
262 // ui.setUserDir(userDir);
263 }
264 }
265 initLocale(cmsSession);
266 context = stateToNode(ui, state);
267 if (context == null)
268 context = ui.getUserDir();
269
270 if (headerUiProvider != null)
271 refreshPart(headerUiProvider, ui.getHeader(), context);
272 ui.refreshBelowHeader(true);
273 for (String key : layersByPid.keySet()) {
274 SwtAppLayer layer = layersByPid.get(key).get();
275 ui.addLayer(key, layer);
276 }
277
278 if (leadPaneUiProvider != null)
279 refreshPart(leadPaneUiProvider, ui.getLeadPane(), context);
280 if (footerUiProvider != null)
281 refreshPart(footerUiProvider, ui.getFooter(), context);
282 ui.layout(true, true);
283 setState(ui, state != null ? state : defaultLayerPid);
284 }
285 } catch (Exception e) {
286 CmsFeedback.error("Unexpected exception", e);
287 }
288 }
289
290 private void initLocale(CmsSession cmsSession) {
291 if (cmsSession == null)
292 return;
293 Locale locale = cmsSession.getLocale();
294 UiContext.setLocale(locale);
295 LocaleUtils.setThreadLocale(locale);
296
297 }
298
299 private void refreshPart(SwtUiProvider uiProvider, Composite part, Content context) {
300 CmsSwtUtils.clear(part);
301 uiProvider.createUiPart(part, context);
302 }
303
304 private SwtUiProvider findStructuralUiProvider(String suffix) {
305 SwtUiProvider res = null;
306 if (pidPrefix != null)
307 res = findUiProvider(pidPrefix + "." + suffix);
308 if (res != null)
309 return res;
310 if (sharedPidPrefix != null)
311 res = findUiProvider(sharedPidPrefix + "." + suffix);
312 return res;
313 }
314
315 private SwtUiProvider findUiProvider(String pid) {
316 if (!uiProvidersByPid.containsKey(pid))
317 return null;
318 return uiProvidersByPid.get(pid).get();
319 }
320
321 private SwtAppLayer findLayer(String pid) {
322 if (!layersByPid.containsKey(pid))
323 return null;
324 return layersByPid.get(pid).get();
325 }
326
327 private <T> T findByType(Map<String, RankedObject<T>> byType, Content content) {
328 if (content == null)
329 throw new IllegalArgumentException("A node should be provided");
330
331 // boolean checkJcr = false;
332 // if (checkJcr && content instanceof JcrContent) {
333 // Node context = ((JcrContent) content).getJcrNode();
334 // try {
335 // // mixins
336 // Set<String> types = new TreeSet<>();
337 // for (NodeType mixinType : context.getMixinNodeTypes()) {
338 // String mixinTypeName = mixinType.getName();
339 // if (byType.containsKey(mixinTypeName)) {
340 // types.add(mixinTypeName);
341 // }
342 // for (NodeType superType : mixinType.getDeclaredSupertypes()) {
343 // if (byType.containsKey(superType.getName())) {
344 // types.add(superType.getName());
345 // }
346 // }
347 // }
348 // // primary node type
349 // NodeType primaryType = context.getPrimaryNodeType();
350 // String primaryTypeName = primaryType.getName();
351 // if (byType.containsKey(primaryTypeName)) {
352 // types.add(primaryTypeName);
353 // }
354 // for (NodeType superType : primaryType.getDeclaredSupertypes()) {
355 // if (byType.containsKey(superType.getName())) {
356 // types.add(superType.getName());
357 // }
358 // }
359 // // entity type
360 // if (context.isNodeType(EntityType.entity.get())) {
361 // if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
362 // String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
363 // if (byType.containsKey(entityTypeName)) {
364 // types.add(entityTypeName);
365 // }
366 // }
367 // }
368 //
369 // if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
370 // types.add("nt:folder");
371 // }
372 //
373 // if (types.size() == 0)
374 // throw new IllegalArgumentException(
375 // "No type found for " + context + " (" + listTypes(context) + ")");
376 // String type = types.iterator().next();
377 // if (!byType.containsKey(type))
378 // throw new IllegalArgumentException("No component found for " + context + " with type " + type);
379 // return byType.get(type).get();
380 // } catch (RepositoryException e) {
381 // throw new IllegalStateException(e);
382 // }
383 //
384 // } else {
385 Set<String> types = new TreeSet<>();
386 if (content.hasContentClass(EntityType.entity.qName())) {
387 String type = content.attr(EntityName.type.qName());
388 if (type != null && byType.containsKey(type))
389 types.add(type);
390 }
391
392 List<QName> objectClasses = content.getContentClasses();
393 for (QName cc : objectClasses) {
394 String type = cc.getPrefix() + ":" + cc.getLocalPart();
395 if (byType.containsKey(type))
396 types.add(type);
397 }
398 if (types.size() == 0) {
399 throw new IllegalArgumentException("No type found for " + content + " (" + objectClasses + ")");
400 }
401 String type = types.iterator().next();
402 if (!byType.containsKey(type))
403 throw new IllegalArgumentException("No component found for " + content + " with type " + type);
404 return byType.get(type).get();
405 // }
406 }
407
408 // private static String listTypes(Node context) {
409 // try {
410 // StringBuilder sb = new StringBuilder();
411 // sb.append(context.getPrimaryNodeType().getName());
412 // for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
413 // sb.append(' ');
414 // sb.append(superType.getName());
415 // }
416 //
417 // for (NodeType nodeType : context.getMixinNodeTypes()) {
418 // sb.append(' ');
419 // sb.append(nodeType.getName());
420 // if (nodeType.getName().equals(EntityType.local.get()))
421 // sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString());
422 // for (NodeType superType : nodeType.getDeclaredSupertypes()) {
423 // sb.append(' ');
424 // sb.append(superType.getName());
425 // }
426 // }
427 // return sb.toString();
428 // } catch (RepositoryException e) {
429 // throw new JcrException(e);
430 // }
431 // }
432
433 @Override
434 public void setState(CmsUi cmsUi, String state) {
435 AppUi ui = (AppUi) cmsUi;
436 if (state == null)
437 return;
438 if (!state.startsWith("/")) {
439 // if (cmsUi instanceof SwtAppUi) {
440 // SwtAppUi ui = (SwtAppUi) cmsUi;
441 if (LOGIN.equals(state)) {
442 String appTitle = "";
443 if (ui.getTitle() != null)
444 appTitle = ui.getTitle().lead();
445 ui.getCmsView().stateChanged(state, appTitle);
446 return;
447 }
448 Map<String, Object> properties = new HashMap<>();
449 String layerId = HOME_STATE.equals(state) ? defaultLayerPid : state;
450 properties.put(SuiteUxEvent.LAYER, layerId);
451 properties.put(SuiteUxEvent.CONTENT_PATH, HOME_STATE);
452 ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), properties);
453 // }
454 return;
455 }
456 // SwtAppUi suiteUi = (SwtAppUi) cmsUi;
457 if (ui.isLoginScreen()) {
458 return;
459 }
460
461 Content node = stateToNode(ui, state);
462 if (node == null) {
463 ui.getCmsView().navigateTo(HOME_STATE);
464 } else {
465 ui.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.eventProperties(node));
466 ui.getCmsView().sendEvent(SuiteUxEvent.refreshPart.topic(), SuiteUxEvent.eventProperties(node));
467 }
468 }
469
470 // TODO move it to an internal package?
471 private static String nodeToState(Content node) {
472 return node.getPath();
473 }
474
475 private Content stateToNode(CmsUi suiteUi, String state) {
476 if (suiteUi == null)
477 return null;
478 if (state == null || !state.startsWith("/"))
479 return null;
480
481 String path = state;
482
483 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
484 suiteUi.getCmsView());
485 return contentSession.get(path);
486 }
487
488 /*
489 * Events management
490 */
491
492 @Override
493 public void onEvent(String topic, Map<String, Object> event) {
494
495 // Specific UI related events
496 SwtAppUi ui = getRelatedUi(event);
497 if (ui == null)
498 return;
499 ui.getCmsView().runAs(() -> {
500 try {
501 String appTitle = "";
502 if (ui.getTitle() != null)
503 appTitle = ui.getTitle().lead();
504
505 if (isTopic(topic, SuiteUxEvent.refreshPart)) {
506 Content node = getContentFromEvent(ui, event);
507 if (node == null)
508 return;
509 SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
510 SwtAppLayer layer = findByType(layersByType, node);
511 ui.switchToLayer(layer, node);
512 layer.view(uiProvider, ui.getCurrentWorkArea(), node);
513 ui.getCmsView().stateChanged(nodeToState(node), stateTitle(appTitle, CmsUxUtils.getTitle(node)));
514 } else if (isTopic(topic, SuiteUxEvent.openNewPart)) {
515 Content node = getContentFromEvent(ui, event);
516 if (node == null)
517 return;
518 SwtUiProvider uiProvider = findByType(uiProvidersByType, node);
519 SwtAppLayer layer = findByType(layersByType, node);
520 ui.switchToLayer(layer, node);
521 layer.open(uiProvider, ui.getCurrentWorkArea(), node);
522 ui.getCmsView().stateChanged(nodeToState(node), stateTitle(appTitle, CmsUxUtils.getTitle(node)));
523 } else if (isTopic(topic, SuiteUxEvent.switchLayer)) {
524 String layerId = get(event, SuiteUxEvent.LAYER);
525 if (layerId != null) {
526 SwtAppLayer suiteLayer = findLayer(layerId);
527 if (suiteLayer == null)
528 throw new IllegalArgumentException("No layer '" + layerId + "' available.");
529 Localized layerTitle = suiteLayer.getTitle();
530 // FIXME make sure we don't rebuild the work area twice
531 Composite workArea = ui.switchToLayer(layerId, ui.getUserDir());
532 String title = null;
533 if (layerTitle != null)
534 title = layerTitle.lead();
535 Content nodeFromState = getContentFromEvent(ui, event);
536 if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDir().getPath())) {
537 // default layer view is forced
538 String state = defaultLayerPid.equals(layerId) ? "~" : layerId;
539 ui.getCmsView().stateChanged(state, stateTitle(appTitle, title));
540 suiteLayer.view(null, workArea, nodeFromState);
541 } else {
542 Content layerCurrentContext = suiteLayer.getCurrentContext(workArea);
543 if (layerCurrentContext != null && !layerCurrentContext.equals(ui.getUserDir())) {
544 // layer was already showing a context so we set the state to it
545 ui.getCmsView().stateChanged(nodeToState(layerCurrentContext),
546 stateTitle(appTitle, CmsUxUtils.getTitle(layerCurrentContext)));
547 } else {
548 // no context was shown
549 ui.getCmsView().stateChanged(layerId, stateTitle(appTitle, title));
550 }
551 }
552 } else {
553 Content node = getContentFromEvent(ui, event);
554 if (node != null) {
555 SwtAppLayer layer = findByType(layersByType, node);
556 ui.switchToLayer(layer, node);
557 }
558 }
559 }
560 } catch (Exception e) {
561 CmsFeedback.error("Cannot handle event " + topic + " " + event, e);
562 // log.error("Cannot handle event " + event, e);
563 }
564 });
565 }
566
567 private String stateTitle(String appTitle, String additionalTitle) {
568 return additionalTitle == null ? appTitle : appTitle + " - " + additionalTitle;
569 }
570
571 private boolean isTopic(String topic, CmsEvent cmsEvent) {
572 Objects.requireNonNull(topic);
573 return topic.equals(cmsEvent.topic());
574 }
575
576 protected Content getContentFromEvent(SwtAppUi ui, Map<String, Object> event) {
577 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
578 ui.getCmsView());
579
580 String path = get(event, SuiteUxEvent.CONTENT_PATH);
581
582 if (path != null && (path.equals(HOME_STATE) || path.equals("")))
583 return ui.getUserDir();
584 Content node;
585 if (path == null) {
586 return null;
587 // // look for a user
588 // String username = get(event, SuiteUxEvent.USERNAME);
589 // if (username == null)
590 // return null;
591 // User user = cmsUserManager.getUser(username);
592 // if (user == null)
593 // return null;
594 // node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
595 } else {
596 node = contentSession.get(path);
597 }
598 return node;
599 }
600
601 private SwtAppUi getRelatedUi(Map<String, Object> eventProperties) {
602 return managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY));
603 }
604
605 public static String get(Map<String, Object> eventProperties, String key) {
606 Object value = eventProperties.get(key);
607 if (value == null)
608 return null;
609 return value.toString();
610
611 }
612
613 /*
614 * Dependency injection.
615 */
616
617 public void addUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
618 if (properties.containsKey(Constants.SERVICE_PID)) {
619 String pid = (String) properties.get(Constants.SERVICE_PID);
620 RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties);
621 }
622 if (properties.containsKey(EntityConstants.TYPE)) {
623 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
624 for (String type : types) {
625 RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties);
626 }
627 }
628 }
629
630 public void removeUiProvider(SwtUiProvider uiProvider, Map<String, Object> properties) {
631 if (properties.containsKey(Constants.SERVICE_PID)) {
632 String pid = (String) properties.get(Constants.SERVICE_PID);
633 if (uiProvidersByPid.containsKey(pid)) {
634 if (uiProvidersByPid.get(pid).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
635 uiProvidersByPid.remove(pid);
636 }
637 }
638 }
639 if (properties.containsKey(EntityConstants.TYPE)) {
640 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
641 for (String type : types) {
642 if (uiProvidersByType.containsKey(type)) {
643 if (uiProvidersByType.get(type).equals(new RankedObject<SwtUiProvider>(uiProvider, properties))) {
644 uiProvidersByType.remove(type);
645 }
646 }
647 }
648 }
649 }
650
651 public void addLayer(SwtAppLayer layer, Map<String, Object> properties) {
652 if (properties.containsKey(Constants.SERVICE_PID)) {
653 String pid = (String) properties.get(Constants.SERVICE_PID);
654 RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
655 }
656 if (properties.containsKey(EntityConstants.TYPE)) {
657 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
658 for (String type : types)
659 RankedObject.putIfHigherRank(layersByType, type, layer, properties);
660 }
661 }
662
663 public void removeLayer(SwtAppLayer layer, Map<String, Object> properties) {
664 if (properties.containsKey(Constants.SERVICE_PID)) {
665 String pid = (String) properties.get(Constants.SERVICE_PID);
666 if (layersByPid.containsKey(pid)) {
667 if (layersByPid.get(pid).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
668 layersByPid.remove(pid);
669 }
670 }
671 }
672 if (properties.containsKey(EntityConstants.TYPE)) {
673 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
674 for (String type : types) {
675 if (layersByType.containsKey(type)) {
676 if (layersByType.get(type).equals(new RankedObject<SwtAppLayer>(layer, properties))) {
677 layersByType.remove(type);
678 }
679 }
680 }
681 }
682 }
683
684 // public void setCmsUserManager(CmsUserManager cmsUserManager) {
685 // this.cmsUserManager = cmsUserManager;
686 // }
687
688 // protected ContentRepository getContentRepository() {
689 // return contentRepository;
690 // }
691
692 public void setContentRepository(ContentRepository contentRepository) {
693 this.contentRepository = contentRepository;
694 }
695
696 public void setAppUserState(AppUserState appUserState) {
697 this.appUserState = appUserState;
698 }
699
700 /**
701 * Dedicated class to clean up the UI in order to avoid illegal access issues
702 * with lambdas.
703 */
704 private class CleanUpUi implements DisposeListener {
705 private static final long serialVersionUID = 1905900302262082463L;
706 final String uid;
707
708 public CleanUpUi(String uid) {
709 super();
710 this.uid = uid;
711 }
712
713 @Override
714 public void widgetDisposed(DisposeEvent e) {
715 managedUis.remove(uid);
716 if (log.isDebugEnabled())
717 log.debug("App " + appPid + " - Suite UI " + uid + " has been disposed (" + managedUis.size()
718 + " UIs still being managed).");
719 }
720
721 }
722
723 }