1 package org
.argeo
.app
.swt
.ux
;
3 import static org
.argeo
.api
.cms
.ux
.CmsView
.CMS_VIEW_UID_PROPERTY
;
5 import java
.lang
.ref
.WeakReference
;
6 import java
.util
.Collections
;
7 import java
.util
.HashMap
;
8 import java
.util
.HashSet
;
9 import java
.util
.Iterator
;
10 import java
.util
.List
;
11 import java
.util
.Locale
;
13 import java
.util
.Objects
;
15 import java
.util
.Timer
;
16 import java
.util
.TimerTask
;
17 import java
.util
.TreeMap
;
18 import java
.util
.TreeSet
;
20 import javax
.xml
.namespace
.QName
;
22 import org
.argeo
.api
.acr
.Content
;
23 import org
.argeo
.api
.acr
.ContentRepository
;
24 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
25 import org
.argeo
.api
.cms
.CmsConstants
;
26 import org
.argeo
.api
.cms
.CmsEvent
;
27 import org
.argeo
.api
.cms
.CmsEventSubscriber
;
28 import org
.argeo
.api
.cms
.CmsLog
;
29 import org
.argeo
.api
.cms
.CmsSession
;
30 import org
.argeo
.api
.cms
.ux
.CmsTheme
;
31 import org
.argeo
.api
.cms
.ux
.CmsUi
;
32 import org
.argeo
.api
.cms
.ux
.CmsView
;
33 import org
.argeo
.app
.api
.AppUserState
;
34 import org
.argeo
.app
.api
.EntityConstants
;
35 import org
.argeo
.app
.api
.EntityName
;
36 import org
.argeo
.app
.api
.EntityType
;
37 import org
.argeo
.app
.api
.RankedObject
;
38 import org
.argeo
.app
.ux
.AbstractArgeoApp
;
39 import org
.argeo
.app
.ux
.AppUi
;
40 import org
.argeo
.app
.ux
.SuiteUxEvent
;
41 import org
.argeo
.cms
.LocaleUtils
;
42 import org
.argeo
.cms
.Localized
;
43 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
44 import org
.argeo
.cms
.swt
.acr
.SwtUiProvider
;
45 import org
.argeo
.cms
.swt
.dialogs
.CmsFeedback
;
46 import org
.argeo
.cms
.util
.LangUtils
;
47 import org
.argeo
.cms
.ux
.CmsUxUtils
;
48 import org
.argeo
.eclipse
.ui
.specific
.UiContext
;
49 import org
.eclipse
.swt
.SWT
;
50 import org
.eclipse
.swt
.events
.DisposeEvent
;
51 import org
.eclipse
.swt
.events
.DisposeListener
;
52 import org
.eclipse
.swt
.widgets
.Composite
;
53 import org
.osgi
.framework
.Constants
;
55 /** The Argeo Suite App. */
56 public class SwtArgeoApp
extends AbstractArgeoApp
implements CmsEventSubscriber
{
57 private final static CmsLog log
= CmsLog
.getLog(SwtArgeoApp
.class);
59 public final static String PUBLIC_BASE_PATH_PROPERTY
= "publicBasePath";
60 public final static String DEFAULT_UI_NAME_PROPERTY
= "defaultUiName";
61 public final static String DEFAULT_THEME_ID_PROPERTY
= "defaultThemeId";
62 public final static String DEFAULT_LAYER_PROPERTY
= "defaultLayer";
63 public final static String SHARED_PID_PREFIX_PROPERTY
= "sharedPidPrefix";
65 private final static String LOGIN
= "login";
66 private final static String HOME_STATE
= "~";
68 private String publicBasePath
= null;
70 private String appPid
;
71 private String pidPrefix
;
72 private String sharedPidPrefix
;
74 // private String headerPid;
75 // private String footerPid;
76 // private String leadPanePid;
77 // private String adminLeadPanePid;
78 // private String loginScreenPid;
80 private String defaultUiName
= "app";
81 private String adminUiName
= "admin";
83 // FIXME such default names make refactoring more dangerous
85 private String defaultLayerPid
= "argeo.suite.ui.dashboardLayer";
87 private String defaultThemeId
= "org.argeo.app.theme.default";
89 // TODO use QName as key for byType
90 private Map
<String
, RankedObject
<SwtUiProvider
>> uiProvidersByPid
= Collections
.synchronizedMap(new HashMap
<>());
91 private Map
<String
, RankedObject
<SwtUiProvider
>> uiProvidersByType
= Collections
.synchronizedMap(new HashMap
<>());
92 private Map
<String
, RankedObject
<SwtAppLayer
>> layersByPid
= Collections
.synchronizedSortedMap(new TreeMap
<>());
93 private Map
<String
, RankedObject
<SwtAppLayer
>> layersByType
= Collections
.synchronizedSortedMap(new TreeMap
<>());
95 // private CmsUserManager cmsUserManager;
97 // TODO make more optimal or via CmsSession/CmsView
98 private static Timer janitorTimer
= new Timer(true);
99 private Map
<String
, WeakReference
<SwtAppUi
>> managedUis
= new HashMap
<>();
102 private ContentRepository contentRepository
;
103 private AppUserState appUserState
;
105 // private Repository repository;
107 public void start(Map
<String
, Object
> properties
) {
108 for (SuiteUxEvent event
: SuiteUxEvent
.values()) {
109 getCmsContext().getCmsEventBus().addEventSubscriber(event
.topic(), this);
112 if (properties
.containsKey(DEFAULT_UI_NAME_PROPERTY
))
113 defaultUiName
= LangUtils
.get(properties
, DEFAULT_UI_NAME_PROPERTY
);
114 if (properties
.containsKey(DEFAULT_THEME_ID_PROPERTY
))
115 defaultThemeId
= LangUtils
.get(properties
, DEFAULT_THEME_ID_PROPERTY
);
116 if (properties
.containsKey(DEFAULT_LAYER_PROPERTY
))
117 defaultLayerPid
= LangUtils
.get(properties
, DEFAULT_LAYER_PROPERTY
);
118 sharedPidPrefix
= LangUtils
.get(properties
, SHARED_PID_PREFIX_PROPERTY
);
119 publicBasePath
= LangUtils
.get(properties
, PUBLIC_BASE_PATH_PROPERTY
);
121 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
122 appPid
= properties
.get(Constants
.SERVICE_PID
).toString();
123 int lastDotIndex
= appPid
.lastIndexOf('.');
124 if (lastDotIndex
>= 0) {
125 pidPrefix
= appPid
.substring(0, lastDotIndex
);
128 // TODO does it make sense to accept that?
129 appPid
= "<unknown>";
131 Objects
.requireNonNull(contentRepository
, "Content repository must be provided");
132 Objects
.requireNonNull(appUserState
, "App user state must be provided");
134 long janitorPeriod
= 60 * 60 * 1000;// 1h
135 janitorTimer
.schedule(new TimerTask() {
140 Iterator
<Map
.Entry
<String
, WeakReference
<SwtAppUi
>>> uiRefs
= managedUis
.entrySet().iterator();
141 refs
: while (uiRefs
.hasNext()) {
142 Map
.Entry
<String
, WeakReference
<SwtAppUi
>> entry
= uiRefs
.next();
143 String uiUuid
= entry
.getKey();
144 WeakReference
<SwtAppUi
> uiRef
= entry
.getValue();
145 SwtAppUi ui
= uiRef
.get();
147 if (log
.isTraceEnabled())
148 log
.warn("Unreferenced UI " + uiUuid
+ " in " + appPid
+ ", removing it");
152 if (!ui
.isDisposed() && !ui
.getDisplay().isDisposed()) {
153 if (ui
.isTimedOut()) {
154 if (log
.isTraceEnabled())
155 log
.trace("Killing timed-out UI " + uiUuid
+ " in " + appPid
);
156 UiContext
.killDisplay(ui
.getDisplay());
159 if (log
.isTraceEnabled())
160 log
.warn("Disposed UI " + uiUuid
+ " still in " + appPid
+ ", removing it");
164 if (log
.isTraceEnabled())
165 log
.trace(managedUis
.size() + " UIs being managed by app " + appPid
);
166 } catch (Exception e
) {
170 }, janitorPeriod
, janitorPeriod
);
172 if (log
.isDebugEnabled())
173 log
.info("Argeo Suite App " + appPid
+ " started");
176 public void stop(Map
<String
, Object
> properties
) {
177 refs
: for (WeakReference
<SwtAppUi
> uiRef
: managedUis
.values()) {
178 SwtAppUi ui
= uiRef
.get();
181 if (!ui
.isDisposed() && !ui
.getDisplay().isDisposed()) {
182 ui
.getDisplay().syncExec(() -> ui
.dispose());
186 if (log
.isDebugEnabled())
187 log
.info("Argeo Suite App stopped");
192 public Set
<String
> getUiNames() {
193 HashSet
<String
> uiNames
= new HashSet
<>();
194 uiNames
.add(defaultUiName
);
195 uiNames
.add(adminUiName
);
200 public CmsUi
initUi(Object parent
) {
201 Composite uiParent
= (Composite
) parent
;
202 String uiName
= uiParent
.getData(UI_NAME_PROPERTY
) != null ? uiParent
.getData(UI_NAME_PROPERTY
).toString()
204 CmsView cmsView
= CmsSwtUtils
.getCmsView(uiParent
);
206 throw new IllegalStateException("No CMS view is registered.");
207 CmsTheme theme
= getTheme(uiName
);
209 CmsSwtUtils
.registerCmsTheme(uiParent
.getShell(), theme
);
210 SwtAppUi argeoSuiteUi
= new SwtAppUi(uiParent
, SWT
.INHERIT_DEFAULT
);
211 // TODO make timeout configurable
212 argeoSuiteUi
.setUiTimeout(6 * 60 * 60 * 1000);// 6 hours
213 String uid
= cmsView
.getUid();
214 argeoSuiteUi
.addDisposeListener(new CleanUpUi(uid
));
215 managedUis
.put(uid
, new WeakReference
<>(argeoSuiteUi
));
220 public String
getThemeId(String uiName
) {
221 String themeId
= System
.getProperty("org.argeo.app.theme.default");
224 return defaultThemeId
;
228 public void refreshUi(CmsUi cmsUi
, String state
) {
230 Content context
= null;
231 SwtAppUi ui
= (SwtAppUi
) cmsUi
;
232 ui
.updateLastAccess();
234 String uiName
= Objects
.toString(ui
.getParent().getData(UI_NAME_PROPERTY
), null);
236 throw new IllegalStateException("UI name should not be null");
237 CmsView cmsView
= CmsSwtUtils
.getCmsView(ui
);
239 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
, cmsView
);
241 SwtUiProvider headerUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.header
.name());
242 SwtUiProvider footerUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.footer
.name());
243 SwtUiProvider leadPaneUiProvider
;
244 if (adminUiName
.equals(uiName
)) {
245 leadPaneUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.adminLeadPane
.name());
247 leadPaneUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.leadPane
.name());
250 Localized appTitle
= null;
251 if (headerUiProvider
instanceof DefaultHeader
) {
252 appTitle
= ((DefaultHeader
) headerUiProvider
).getTitle();
254 ui
.setTitle(appTitle
);
256 if (cmsView
.isAnonymous() && publicBasePath
== null) {// internal app, must login
258 ui
.setLoginScreen(true);
259 if (headerUiProvider
!= null)
260 refreshPart(headerUiProvider
, ui
.getHeader(), context
);
261 ui
.refreshBelowHeader(false);
262 SwtUiProvider loginScreenUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.loginScreen
.name());
263 refreshPart(loginScreenUiProvider
, ui
.getBelowHeader(), context
);
264 if (footerUiProvider
!= null)
265 refreshPart(footerUiProvider
, ui
.getFooter(), context
);
266 ui
.layout(true, true);
269 if (LOGIN
.equals(state
))
271 if (ui
.isLoginScreen()) {
272 ui
.setLoginScreen(false);
274 CmsSession cmsSession
= cmsView
.getCmsSession();
275 if (ui
.getUserDir() == null) {
276 // FIXME NPE on CMSSession when logging in from anonymous
277 if (cmsSession
== null || cmsView
.isAnonymous()) {
278 assert publicBasePath
!= null;
279 Content userDir
= contentSession
280 .get(Content
.ROOT_PATH
+ CmsConstants
.SYS_WORKSPACE
+ publicBasePath
);
281 ui
.setUserDir(userDir
);
283 Content userDir
= appUserState
.getOrCreateSessionDir(cmsSession
);
284 ui
.setUserDir(userDir
);
285 // Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
286 // Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
289 // Content userDir = contentSession
290 // .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
291 // ui.setUserDir(userDir);
294 initLocale(cmsSession
);
295 context
= stateToNode(ui
, state
);
297 context
= ui
.getUserDir();
299 if (headerUiProvider
!= null)
300 refreshPart(headerUiProvider
, ui
.getHeader(), context
);
301 ui
.refreshBelowHeader(true);
302 for (String key
: layersByPid
.keySet()) {
303 SwtAppLayer layer
= layersByPid
.get(key
).get();
304 ui
.addLayer(key
, layer
);
307 if (leadPaneUiProvider
!= null)
308 refreshPart(leadPaneUiProvider
, ui
.getLeadPane(), context
);
309 if (footerUiProvider
!= null)
310 refreshPart(footerUiProvider
, ui
.getFooter(), context
);
311 ui
.layout(true, true);
312 setState(ui
, state
!= null ? state
: defaultLayerPid
);
314 } catch (Exception e
) {
315 CmsFeedback
.error("Unexpected exception", e
);
319 private void initLocale(CmsSession cmsSession
) {
320 if (cmsSession
== null)
322 Locale locale
= cmsSession
.getLocale();
323 UiContext
.setLocale(locale
);
324 LocaleUtils
.setThreadLocale(locale
);
328 private void refreshPart(SwtUiProvider uiProvider
, Composite part
, Content context
) {
329 CmsSwtUtils
.clear(part
);
330 uiProvider
.createUiPart(part
, context
);
333 private SwtUiProvider
findStructuralUiProvider(String suffix
) {
334 SwtUiProvider res
= null;
335 if (pidPrefix
!= null)
336 res
= findUiProvider(pidPrefix
+ "." + suffix
);
339 if (sharedPidPrefix
!= null)
340 res
= findUiProvider(sharedPidPrefix
+ "." + suffix
);
344 private SwtUiProvider
findUiProvider(String pid
) {
345 if (!uiProvidersByPid
.containsKey(pid
))
347 return uiProvidersByPid
.get(pid
).get();
350 private SwtAppLayer
findLayer(String pid
) {
351 if (!layersByPid
.containsKey(pid
))
353 return layersByPid
.get(pid
).get();
356 private <T
> T
findByType(Map
<String
, RankedObject
<T
>> byType
, Content content
) {
358 throw new IllegalArgumentException("A node should be provided");
360 // boolean checkJcr = false;
361 // if (checkJcr && content instanceof JcrContent) {
362 // Node context = ((JcrContent) content).getJcrNode();
365 // Set<String> types = new TreeSet<>();
366 // for (NodeType mixinType : context.getMixinNodeTypes()) {
367 // String mixinTypeName = mixinType.getName();
368 // if (byType.containsKey(mixinTypeName)) {
369 // types.add(mixinTypeName);
371 // for (NodeType superType : mixinType.getDeclaredSupertypes()) {
372 // if (byType.containsKey(superType.getName())) {
373 // types.add(superType.getName());
377 // // primary node type
378 // NodeType primaryType = context.getPrimaryNodeType();
379 // String primaryTypeName = primaryType.getName();
380 // if (byType.containsKey(primaryTypeName)) {
381 // types.add(primaryTypeName);
383 // for (NodeType superType : primaryType.getDeclaredSupertypes()) {
384 // if (byType.containsKey(superType.getName())) {
385 // types.add(superType.getName());
389 // if (context.isNodeType(EntityType.entity.get())) {
390 // if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
391 // String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
392 // if (byType.containsKey(entityTypeName)) {
393 // types.add(entityTypeName);
398 // if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
399 // types.add("nt:folder");
402 // if (types.size() == 0)
403 // throw new IllegalArgumentException(
404 // "No type found for " + context + " (" + listTypes(context) + ")");
405 // String type = types.iterator().next();
406 // if (!byType.containsKey(type))
407 // throw new IllegalArgumentException("No component found for " + context + " with type " + type);
408 // return byType.get(type).get();
409 // } catch (RepositoryException e) {
410 // throw new IllegalStateException(e);
414 Set
<String
> types
= new TreeSet
<>();
415 if (content
.hasContentClass(EntityType
.entity
.qName())) {
416 String type
= content
.attr(EntityName
.type
.qName());
417 if (type
!= null && byType
.containsKey(type
))
421 List
<QName
> objectClasses
= content
.getContentClasses();
422 for (QName cc
: objectClasses
) {
423 String type
= cc
.getPrefix() + ":" + cc
.getLocalPart();
424 if (byType
.containsKey(type
))
427 if (types
.size() == 0) {
428 throw new IllegalArgumentException("No type found for " + content
+ " (" + objectClasses
+ ")");
430 String type
= types
.iterator().next();
431 if (!byType
.containsKey(type
))
432 throw new IllegalArgumentException("No component found for " + content
+ " with type " + type
);
433 return byType
.get(type
).get();
437 // private static String listTypes(Node context) {
439 // StringBuilder sb = new StringBuilder();
440 // sb.append(context.getPrimaryNodeType().getName());
441 // for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
443 // sb.append(superType.getName());
446 // for (NodeType nodeType : context.getMixinNodeTypes()) {
448 // sb.append(nodeType.getName());
449 // if (nodeType.getName().equals(EntityType.local.get()))
450 // sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString());
451 // for (NodeType superType : nodeType.getDeclaredSupertypes()) {
453 // sb.append(superType.getName());
456 // return sb.toString();
457 // } catch (RepositoryException e) {
458 // throw new JcrException(e);
463 public void setState(CmsUi cmsUi
, String state
) {
464 AppUi ui
= (AppUi
) cmsUi
;
467 if (!state
.startsWith("/")) {
468 // if (cmsUi instanceof SwtAppUi) {
469 // SwtAppUi ui = (SwtAppUi) cmsUi;
470 if (LOGIN
.equals(state
)) {
471 String appTitle
= "";
472 if (ui
.getTitle() != null)
473 appTitle
= ui
.getTitle().lead();
474 ui
.getCmsView().stateChanged(state
, appTitle
);
477 Map
<String
, Object
> properties
= new HashMap
<>();
478 String layerId
= HOME_STATE
.equals(state
) ? defaultLayerPid
: state
;
479 properties
.put(SuiteUxEvent
.LAYER
, layerId
);
480 properties
.put(SuiteUxEvent
.CONTENT_PATH
, HOME_STATE
);
481 ui
.getCmsView().sendEvent(SuiteUxEvent
.switchLayer
.topic(), properties
);
485 // SwtAppUi suiteUi = (SwtAppUi) cmsUi;
486 if (ui
.isLoginScreen()) {
490 Content node
= stateToNode(ui
, state
);
492 ui
.getCmsView().navigateTo(HOME_STATE
);
494 ui
.getCmsView().sendEvent(SuiteUxEvent
.switchLayer
.topic(), SuiteUxEvent
.eventProperties(node
));
495 ui
.getCmsView().sendEvent(SuiteUxEvent
.refreshPart
.topic(), SuiteUxEvent
.eventProperties(node
));
499 // TODO move it to an internal package?
500 private static String
nodeToState(Content node
) {
501 return node
.getPath();
504 private Content
stateToNode(CmsUi suiteUi
, String state
) {
507 if (state
== null || !state
.startsWith("/"))
512 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
513 suiteUi
.getCmsView());
514 return contentSession
.get(path
);
522 public void onEvent(String topic
, Map
<String
, Object
> event
) {
524 // Specific UI related events
525 SwtAppUi ui
= getRelatedUi(event
);
528 ui
.updateLastAccess();
529 ui
.getCmsView().runAs(() -> {
531 String appTitle
= "";
532 if (ui
.getTitle() != null)
533 appTitle
= ui
.getTitle().lead();
535 if (isTopic(topic
, SuiteUxEvent
.refreshPart
)) {
536 Content node
= getContentFromEvent(ui
, event
);
539 SwtUiProvider uiProvider
= findByType(uiProvidersByType
, node
);
540 SwtAppLayer layer
= findByType(layersByType
, node
);
541 ui
.switchToLayer(layer
, node
);
542 layer
.view(uiProvider
, ui
.getCurrentWorkArea(), node
);
543 ui
.getCmsView().stateChanged(nodeToState(node
), stateTitle(appTitle
, CmsUxUtils
.getTitle(node
)));
544 } else if (isTopic(topic
, SuiteUxEvent
.openNewPart
)) {
545 Content node
= getContentFromEvent(ui
, event
);
548 SwtUiProvider uiProvider
= findByType(uiProvidersByType
, node
);
549 SwtAppLayer layer
= findByType(layersByType
, node
);
550 ui
.switchToLayer(layer
, node
);
551 layer
.open(uiProvider
, ui
.getCurrentWorkArea(), node
);
552 ui
.getCmsView().stateChanged(nodeToState(node
), stateTitle(appTitle
, CmsUxUtils
.getTitle(node
)));
553 } else if (isTopic(topic
, SuiteUxEvent
.switchLayer
)) {
554 String layerId
= get(event
, SuiteUxEvent
.LAYER
);
555 if (layerId
!= null) {
556 SwtAppLayer suiteLayer
= findLayer(layerId
);
557 if (suiteLayer
== null)
558 throw new IllegalArgumentException("No layer '" + layerId
+ "' available.");
559 Localized layerTitle
= suiteLayer
.getTitle();
560 // FIXME make sure we don't rebuild the work area twice
561 Composite workArea
= ui
.switchToLayer(layerId
, ui
.getUserDir());
563 if (layerTitle
!= null)
564 title
= layerTitle
.lead();
565 Content nodeFromState
= getContentFromEvent(ui
, event
);
566 if (nodeFromState
!= null && nodeFromState
.getPath().equals(ui
.getUserDir().getPath())) {
567 // default layer view is forced
568 String state
= defaultLayerPid
.equals(layerId
) ?
"~" : layerId
;
569 ui
.getCmsView().stateChanged(state
, stateTitle(appTitle
, title
));
570 suiteLayer
.view(null, workArea
, nodeFromState
);
572 Content layerCurrentContext
= suiteLayer
.getCurrentContext(workArea
);
573 if (layerCurrentContext
!= null && !layerCurrentContext
.equals(ui
.getUserDir())) {
574 // layer was already showing a context so we set the state to it
575 ui
.getCmsView().stateChanged(nodeToState(layerCurrentContext
),
576 stateTitle(appTitle
, CmsUxUtils
.getTitle(layerCurrentContext
)));
578 // no context was shown
579 ui
.getCmsView().stateChanged(layerId
, stateTitle(appTitle
, title
));
583 Content node
= getContentFromEvent(ui
, event
);
585 SwtAppLayer layer
= findByType(layersByType
, node
);
586 ui
.switchToLayer(layer
, node
);
590 } catch (Exception e
) {
591 CmsFeedback
.error("Cannot handle event " + topic
+ " " + event
, e
);
592 // log.error("Cannot handle event " + event, e);
597 private String
stateTitle(String appTitle
, String additionalTitle
) {
598 return additionalTitle
== null ? appTitle
: appTitle
+ " - " + additionalTitle
;
601 private boolean isTopic(String topic
, CmsEvent cmsEvent
) {
602 Objects
.requireNonNull(topic
);
603 return topic
.equals(cmsEvent
.topic());
606 protected Content
getContentFromEvent(SwtAppUi ui
, Map
<String
, Object
> event
) {
607 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
610 String path
= get(event
, SuiteUxEvent
.CONTENT_PATH
);
612 if (path
!= null && (path
.equals(HOME_STATE
) || path
.equals("")))
613 return ui
.getUserDir();
617 // // look for a user
618 // String username = get(event, SuiteUxEvent.USERNAME);
619 // if (username == null)
621 // User user = cmsUserManager.getUser(username);
624 // node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
626 node
= contentSession
.get(path
);
631 private SwtAppUi
getRelatedUi(Map
<String
, Object
> eventProperties
) {
632 WeakReference
<SwtAppUi
> uiRef
= managedUis
.get(get(eventProperties
, CMS_VIEW_UID_PROPERTY
));
638 public static String
get(Map
<String
, Object
> eventProperties
, String key
) {
639 Object value
= eventProperties
.get(key
);
642 return value
.toString();
647 * Dependency injection.
650 public void addUiProvider(SwtUiProvider uiProvider
, Map
<String
, Object
> properties
) {
651 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
652 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
653 RankedObject
.putIfHigherRank(uiProvidersByPid
, pid
, uiProvider
, properties
);
655 if (properties
.containsKey(EntityConstants
.TYPE
)) {
656 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
657 for (String type
: types
) {
658 RankedObject
.putIfHigherRank(uiProvidersByType
, type
, uiProvider
, properties
);
663 public void removeUiProvider(SwtUiProvider uiProvider
, Map
<String
, Object
> properties
) {
664 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
665 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
666 if (uiProvidersByPid
.containsKey(pid
)) {
667 if (uiProvidersByPid
.get(pid
).equals(new RankedObject
<SwtUiProvider
>(uiProvider
, properties
))) {
668 uiProvidersByPid
.remove(pid
);
672 if (properties
.containsKey(EntityConstants
.TYPE
)) {
673 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
674 for (String type
: types
) {
675 if (uiProvidersByType
.containsKey(type
)) {
676 if (uiProvidersByType
.get(type
).equals(new RankedObject
<SwtUiProvider
>(uiProvider
, properties
))) {
677 uiProvidersByType
.remove(type
);
684 public void addLayer(SwtAppLayer layer
, Map
<String
, Object
> properties
) {
685 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
686 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
687 RankedObject
.putIfHigherRank(layersByPid
, pid
, layer
, properties
);
689 if (properties
.containsKey(EntityConstants
.TYPE
)) {
690 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
691 for (String type
: types
)
692 RankedObject
.putIfHigherRank(layersByType
, type
, layer
, properties
);
696 public void removeLayer(SwtAppLayer layer
, Map
<String
, Object
> properties
) {
697 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
698 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
699 if (layersByPid
.containsKey(pid
)) {
700 if (layersByPid
.get(pid
).equals(new RankedObject
<SwtAppLayer
>(layer
, properties
))) {
701 layersByPid
.remove(pid
);
705 if (properties
.containsKey(EntityConstants
.TYPE
)) {
706 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
707 for (String type
: types
) {
708 if (layersByType
.containsKey(type
)) {
709 if (layersByType
.get(type
).equals(new RankedObject
<SwtAppLayer
>(layer
, properties
))) {
710 layersByType
.remove(type
);
717 public void setContentRepository(ContentRepository contentRepository
) {
718 this.contentRepository
= contentRepository
;
721 public void setAppUserState(AppUserState appUserState
) {
722 this.appUserState
= appUserState
;
726 * Dedicated class to clean up the UI in order to avoid illegal access issues
729 private class CleanUpUi
implements DisposeListener
{
730 private static final long serialVersionUID
= 1905900302262082463L;
733 public CleanUpUi(String uid
) {
738 public void widgetDisposed(DisposeEvent e
) {
739 managedUis
.remove(uid
);
740 if (log
.isDebugEnabled())
741 log
.debug("App " + appPid
+ " - Suite UI " + uid
+ " has been disposed (" + managedUis
.size()
742 + " UIs still being managed).");