1 package org
.argeo
.app
.swt
.ux
;
3 import static org
.argeo
.api
.cms
.ux
.CmsView
.CMS_VIEW_UID_PROPERTY
;
5 import java
.util
.Collections
;
6 import java
.util
.HashMap
;
7 import java
.util
.HashSet
;
9 import java
.util
.Locale
;
11 import java
.util
.Objects
;
13 import java
.util
.TreeMap
;
14 import java
.util
.TreeSet
;
16 import javax
.xml
.namespace
.QName
;
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
;
51 /** The Argeo Suite App. */
52 public class SwtArgeoApp
extends AbstractArgeoApp
implements CmsEventSubscriber
{
53 private final static CmsLog log
= CmsLog
.getLog(SwtArgeoApp
.class);
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";
61 private final static String LOGIN
= "login";
62 private final static String HOME_STATE
= "~";
64 private String publicBasePath
= null;
66 private String appPid
;
67 private String pidPrefix
;
68 private String sharedPidPrefix
;
70 // private String headerPid;
71 // private String footerPid;
72 // private String leadPanePid;
73 // private String adminLeadPanePid;
74 // private String loginScreenPid;
76 private String defaultUiName
= "app";
77 private String adminUiName
= "admin";
79 // FIXME such default names make refactoring more dangerous
81 private String defaultLayerPid
= "argeo.suite.ui.dashboardLayer";
83 private String defaultThemeId
= "org.argeo.app.theme.default";
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
<>());
91 // private CmsUserManager cmsUserManager;
93 // TODO make more optimal or via CmsSession/CmsView
94 private Map
<String
, SwtAppUi
> managedUis
= Collections
.synchronizedMap(new HashMap
<>());
97 private ContentRepository contentRepository
;
98 private AppUserState appUserState
;
100 // private Repository repository;
102 public void start(Map
<String
, Object
> properties
) {
103 for (SuiteUxEvent event
: SuiteUxEvent
.values()) {
104 getCmsContext().getCmsEventBus().addEventSubscriber(event
.topic(), this);
107 if (log
.isDebugEnabled())
108 log
.info("Argeo Suite App started");
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
);
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
);
126 // TODO doe it make sense to accept that?
127 appPid
= "<unknown>";
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.");
135 // headerPid = pidPrefix + "header";
136 // footerPid = pidPrefix + "footer";
137 // leadPanePid = pidPrefix + "leadPane";
138 // adminLeadPanePid = pidPrefix + "adminLeadPane";
139 // loginScreenPid = pidPrefix + "loginScreen";
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());
148 if (log
.isDebugEnabled())
149 log
.info("Argeo Suite App stopped");
154 public Set
<String
> getUiNames() {
155 HashSet
<String
> uiNames
= new HashSet
<>();
156 uiNames
.add(defaultUiName
);
157 uiNames
.add(adminUiName
);
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()
166 CmsView cmsView
= CmsSwtUtils
.getCmsView(uiParent
);
168 throw new IllegalStateException("No CMS view is registered.");
169 CmsTheme theme
= getTheme(uiName
);
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.");
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().");
192 public String
getThemeId(String uiName
) {
193 String themeId
= System
.getProperty("org.argeo.app.theme.default");
196 return defaultThemeId
;
200 public void refreshUi(CmsUi cmsUi
, String state
) {
202 Content context
= null;
203 SwtAppUi ui
= (SwtAppUi
) cmsUi
;
205 String uiName
= Objects
.toString(ui
.getParent().getData(UI_NAME_PROPERTY
), null);
207 throw new IllegalStateException("UI name should not be null");
208 CmsView cmsView
= CmsSwtUtils
.getCmsView(ui
);
210 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
, cmsView
);
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());
218 leadPaneUiProvider
= findStructuralUiProvider(SwtAppUi
.Structural
.leadPane
.name());
221 Localized appTitle
= null;
222 if (headerUiProvider
instanceof DefaultHeader
) {
223 appTitle
= ((DefaultHeader
) headerUiProvider
).getTitle();
225 ui
.setTitle(appTitle
);
227 if (cmsView
.isAnonymous() && publicBasePath
== null) {// internal app, must login
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);
240 if (LOGIN
.equals(state
))
242 if (ui
.isLoginScreen()) {
243 ui
.setLoginScreen(false);
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
);
254 Content userDir
= appUserState
.getOrCreateSessionDir(contentSession
, cmsSession
);
255 ui
.setUserDir(userDir
);
256 // Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
257 // Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
260 // Content userDir = contentSession
261 // .get(ContentUtils.SLASH + CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
262 // ui.setUserDir(userDir);
265 initLocale(cmsSession
);
266 context
= stateToNode(ui
, state
);
268 context
= ui
.getUserDir();
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
);
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
);
285 } catch (Exception e
) {
286 CmsFeedback
.error("Unexpected exception", e
);
290 private void initLocale(CmsSession cmsSession
) {
291 if (cmsSession
== null)
293 Locale locale
= cmsSession
.getLocale();
294 UiContext
.setLocale(locale
);
295 LocaleUtils
.setThreadLocale(locale
);
299 private void refreshPart(SwtUiProvider uiProvider
, Composite part
, Content context
) {
300 CmsSwtUtils
.clear(part
);
301 uiProvider
.createUiPart(part
, context
);
304 private SwtUiProvider
findStructuralUiProvider(String suffix
) {
305 SwtUiProvider res
= null;
306 if (pidPrefix
!= null)
307 res
= findUiProvider(pidPrefix
+ "." + suffix
);
310 if (sharedPidPrefix
!= null)
311 res
= findUiProvider(sharedPidPrefix
+ "." + suffix
);
315 private SwtUiProvider
findUiProvider(String pid
) {
316 if (!uiProvidersByPid
.containsKey(pid
))
318 return uiProvidersByPid
.get(pid
).get();
321 private SwtAppLayer
findLayer(String pid
) {
322 if (!layersByPid
.containsKey(pid
))
324 return layersByPid
.get(pid
).get();
327 private <T
> T
findByType(Map
<String
, RankedObject
<T
>> byType
, Content content
) {
329 throw new IllegalArgumentException("A node should be provided");
331 // boolean checkJcr = false;
332 // if (checkJcr && content instanceof JcrContent) {
333 // Node context = ((JcrContent) content).getJcrNode();
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);
342 // for (NodeType superType : mixinType.getDeclaredSupertypes()) {
343 // if (byType.containsKey(superType.getName())) {
344 // types.add(superType.getName());
348 // // primary node type
349 // NodeType primaryType = context.getPrimaryNodeType();
350 // String primaryTypeName = primaryType.getName();
351 // if (byType.containsKey(primaryTypeName)) {
352 // types.add(primaryTypeName);
354 // for (NodeType superType : primaryType.getDeclaredSupertypes()) {
355 // if (byType.containsKey(superType.getName())) {
356 // types.add(superType.getName());
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);
369 // if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
370 // types.add("nt:folder");
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);
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
))
392 List
<QName
> objectClasses
= content
.getContentClasses();
393 for (QName cc
: objectClasses
) {
394 String type
= cc
.getPrefix() + ":" + cc
.getLocalPart();
395 if (byType
.containsKey(type
))
398 if (types
.size() == 0) {
399 throw new IllegalArgumentException("No type found for " + content
+ " (" + objectClasses
+ ")");
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();
408 // private static String listTypes(Node context) {
410 // StringBuilder sb = new StringBuilder();
411 // sb.append(context.getPrimaryNodeType().getName());
412 // for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
414 // sb.append(superType.getName());
417 // for (NodeType nodeType : context.getMixinNodeTypes()) {
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()) {
424 // sb.append(superType.getName());
427 // return sb.toString();
428 // } catch (RepositoryException e) {
429 // throw new JcrException(e);
434 public void setState(CmsUi cmsUi
, String state
) {
435 AppUi ui
= (AppUi
) cmsUi
;
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
);
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
);
456 // SwtAppUi suiteUi = (SwtAppUi) cmsUi;
457 if (ui
.isLoginScreen()) {
461 Content node
= stateToNode(ui
, state
);
463 ui
.getCmsView().navigateTo(HOME_STATE
);
465 ui
.getCmsView().sendEvent(SuiteUxEvent
.switchLayer
.topic(), SuiteUxEvent
.eventProperties(node
));
466 ui
.getCmsView().sendEvent(SuiteUxEvent
.refreshPart
.topic(), SuiteUxEvent
.eventProperties(node
));
470 // TODO move it to an internal package?
471 private static String
nodeToState(Content node
) {
472 return node
.getPath();
475 private Content
stateToNode(CmsUi suiteUi
, String state
) {
478 if (state
== null || !state
.startsWith("/"))
483 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
484 suiteUi
.getCmsView());
485 return contentSession
.get(path
);
493 public void onEvent(String topic
, Map
<String
, Object
> event
) {
495 // Specific UI related events
496 SwtAppUi ui
= getRelatedUi(event
);
499 ui
.getCmsView().runAs(() -> {
501 String appTitle
= "";
502 if (ui
.getTitle() != null)
503 appTitle
= ui
.getTitle().lead();
505 if (isTopic(topic
, SuiteUxEvent
.refreshPart
)) {
506 Content node
= getContentFromEvent(ui
, event
);
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
);
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());
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
);
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
)));
548 // no context was shown
549 ui
.getCmsView().stateChanged(layerId
, stateTitle(appTitle
, title
));
553 Content node
= getContentFromEvent(ui
, event
);
555 SwtAppLayer layer
= findByType(layersByType
, node
);
556 ui
.switchToLayer(layer
, node
);
560 } catch (Exception e
) {
561 CmsFeedback
.error("Cannot handle event " + topic
+ " " + event
, e
);
562 // log.error("Cannot handle event " + event, e);
567 private String
stateTitle(String appTitle
, String additionalTitle
) {
568 return additionalTitle
== null ? appTitle
: appTitle
+ " - " + additionalTitle
;
571 private boolean isTopic(String topic
, CmsEvent cmsEvent
) {
572 Objects
.requireNonNull(topic
);
573 return topic
.equals(cmsEvent
.topic());
576 protected Content
getContentFromEvent(SwtAppUi ui
, Map
<String
, Object
> event
) {
577 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
580 String path
= get(event
, SuiteUxEvent
.CONTENT_PATH
);
582 if (path
!= null && (path
.equals(HOME_STATE
) || path
.equals("")))
583 return ui
.getUserDir();
587 // // look for a user
588 // String username = get(event, SuiteUxEvent.USERNAME);
589 // if (username == null)
591 // User user = cmsUserManager.getUser(username);
594 // node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
596 node
= contentSession
.get(path
);
601 private SwtAppUi
getRelatedUi(Map
<String
, Object
> eventProperties
) {
602 return managedUis
.get(get(eventProperties
, CMS_VIEW_UID_PROPERTY
));
605 public static String
get(Map
<String
, Object
> eventProperties
, String key
) {
606 Object value
= eventProperties
.get(key
);
609 return value
.toString();
614 * Dependency injection.
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
684 // public void setCmsUserManager(CmsUserManager cmsUserManager) {
685 // this.cmsUserManager = cmsUserManager;
688 // protected ContentRepository getContentRepository() {
689 // return contentRepository;
692 public void setContentRepository(ContentRepository contentRepository
) {
693 this.contentRepository
= contentRepository
;
696 public void setAppUserState(AppUserState appUserState
) {
697 this.appUserState
= appUserState
;
701 * Dedicated class to clean up the UI in order to avoid illegal access issues
704 private class CleanUpUi
implements DisposeListener
{
705 private static final long serialVersionUID
= 1905900302262082463L;
708 public CleanUpUi(String uid
) {
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).");