1 package org
.argeo
.app
.ui
;
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
.jcr
.Node
;
17 import javax
.jcr
.RepositoryException
;
18 import javax
.jcr
.nodetype
.NodeType
;
19 import javax
.xml
.namespace
.QName
;
21 import org
.argeo
.api
.acr
.Content
;
22 import org
.argeo
.api
.acr
.ContentRepository
;
23 import org
.argeo
.api
.acr
.spi
.ProvidedSession
;
24 import org
.argeo
.api
.cms
.CmsConstants
;
25 import org
.argeo
.api
.cms
.CmsEventSubscriber
;
26 import org
.argeo
.api
.cms
.CmsLog
;
27 import org
.argeo
.api
.cms
.CmsSession
;
28 import org
.argeo
.api
.cms
.directory
.CmsUserManager
;
29 import org
.argeo
.api
.cms
.ux
.CmsTheme
;
30 import org
.argeo
.api
.cms
.ux
.CmsUi
;
31 import org
.argeo
.api
.cms
.ux
.CmsView
;
32 import org
.argeo
.app
.api
.EntityConstants
;
33 import org
.argeo
.app
.api
.EntityNames
;
34 import org
.argeo
.app
.api
.EntityType
;
35 import org
.argeo
.app
.api
.RankedObject
;
36 import org
.argeo
.app
.core
.SuiteUtils
;
37 import org
.argeo
.cms
.AbstractCmsApp
;
38 import org
.argeo
.cms
.LocaleUtils
;
39 import org
.argeo
.cms
.Localized
;
40 import org
.argeo
.cms
.acr
.ContentUtils
;
41 import org
.argeo
.cms
.jcr
.CmsJcrUtils
;
42 import org
.argeo
.cms
.jcr
.acr
.JcrContent
;
43 import org
.argeo
.cms
.jcr
.acr
.JcrContentProvider
;
44 import org
.argeo
.cms
.swt
.CmsSwtUtils
;
45 import org
.argeo
.cms
.swt
.acr
.SwtUiProvider
;
46 import org
.argeo
.cms
.swt
.dialogs
.CmsFeedback
;
47 import org
.argeo
.cms
.util
.LangUtils
;
48 import org
.argeo
.cms
.ux
.CmsUxUtils
;
49 import org
.argeo
.eclipse
.ui
.specific
.UiContext
;
50 import org
.argeo
.jcr
.JcrException
;
51 import org
.eclipse
.swt
.SWT
;
52 import org
.eclipse
.swt
.widgets
.Composite
;
53 import org
.osgi
.framework
.Constants
;
54 import org
.osgi
.service
.useradmin
.User
;
56 /** The Argeo Suite App. */
57 public class SuiteApp
extends AbstractCmsApp
implements CmsEventSubscriber
{
58 private final static CmsLog log
= CmsLog
.getLog(SuiteApp
.class);
60 public final static String PUBLIC_BASE_PATH_PROPERTY
= "publicBasePath";
61 public final static String DEFAULT_UI_NAME_PROPERTY
= "defaultUiName";
62 public final static String DEFAULT_THEME_ID_PROPERTY
= "defaultThemeId";
63 public final static String DEFAULT_LAYER_PROPERTY
= "defaultLayer";
64 private final static String LOGIN
= "login";
65 private final static String HOME_STATE
= "~";
67 private String publicBasePath
= null;
69 private String pidPrefix
;
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
<SuiteLayer
>> layersByPid
= Collections
.synchronizedSortedMap(new TreeMap
<>());
89 private Map
<String
, RankedObject
<SuiteLayer
>> layersByType
= Collections
.synchronizedSortedMap(new TreeMap
<>());
91 private CmsUserManager cmsUserManager
;
93 // TODO make more optimal or via CmsSession/CmsView
94 private Map
<String
, SuiteUi
> managedUis
= new HashMap
<>();
97 private ContentRepository contentRepository
;
98 private JcrContentProvider jcrContentProvider
;
101 // private Repository repository;
103 public void init(Map
<String
, Object
> properties
) {
104 for (SuiteUxEvent event
: SuiteUxEvent
.values()) {
105 getCmsContext().getCmsEventBus().addEventSubscriber(event
.topic(), this);
108 if (log
.isDebugEnabled())
109 log
.info("Argeo Suite App started");
111 if (properties
.containsKey(DEFAULT_UI_NAME_PROPERTY
))
112 defaultUiName
= LangUtils
.get(properties
, DEFAULT_UI_NAME_PROPERTY
);
113 if (properties
.containsKey(DEFAULT_THEME_ID_PROPERTY
))
114 defaultThemeId
= LangUtils
.get(properties
, DEFAULT_THEME_ID_PROPERTY
);
115 if (properties
.containsKey(DEFAULT_LAYER_PROPERTY
))
116 defaultLayerPid
= LangUtils
.get(properties
, DEFAULT_LAYER_PROPERTY
);
117 publicBasePath
= LangUtils
.get(properties
, PUBLIC_BASE_PATH_PROPERTY
);
119 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
120 String servicePid
= properties
.get(Constants
.SERVICE_PID
).toString();
121 if (servicePid
.endsWith(".app")) {
122 pidPrefix
= servicePid
.substring(0, servicePid
.length() - "app".length());
126 if (pidPrefix
== null)
127 throw new IllegalArgumentException("PID prefix must be set.");
129 headerPid
= pidPrefix
+ "header";
130 footerPid
= pidPrefix
+ "footer";
131 leadPanePid
= pidPrefix
+ "leadPane";
132 adminLeadPanePid
= pidPrefix
+ "adminLeadPane";
133 loginScreenPid
= pidPrefix
+ "loginScreen";
136 public void destroy(Map
<String
, Object
> properties
) {
137 for (SuiteUi ui
: managedUis
.values())
138 if (!ui
.isDisposed()) {
139 ui
.getDisplay().syncExec(() -> ui
.dispose());
141 if (log
.isDebugEnabled())
142 log
.info("Argeo Suite App stopped");
147 public Set
<String
> getUiNames() {
148 HashSet
<String
> uiNames
= new HashSet
<>();
149 uiNames
.add(defaultUiName
);
150 uiNames
.add(adminUiName
);
155 public CmsUi
initUi(Object parent
) {
156 Composite uiParent
= (Composite
) parent
;
157 String uiName
= uiParent
.getData(UI_NAME_PROPERTY
) != null ? uiParent
.getData(UI_NAME_PROPERTY
).toString()
159 CmsView cmsView
= CmsSwtUtils
.getCmsView(uiParent
);
161 throw new IllegalStateException("No CMS view is registered.");
162 CmsTheme theme
= getTheme(uiName
);
164 CmsSwtUtils
.registerCmsTheme(uiParent
.getShell(), theme
);
165 SuiteUi argeoSuiteUi
= new SuiteUi(uiParent
, SWT
.INHERIT_DEFAULT
);
166 String uid
= cmsView
.getUid();
167 managedUis
.put(uid
, argeoSuiteUi
);
168 argeoSuiteUi
.addDisposeListener((e
) -> {
169 managedUis
.remove(uid
);
170 if (log
.isDebugEnabled())
171 log
.debug("Suite UI " + uid
+ " has been disposed.");
177 public String
getThemeId(String uiName
) {
178 String themeId
= System
.getProperty("org.argeo.app.theme.default");
181 return defaultThemeId
;
185 public void refreshUi(CmsUi cmsUi
, String state
) {
187 Content context
= null;
188 SuiteUi ui
= (SuiteUi
) cmsUi
;
190 String uiName
= Objects
.toString(ui
.getParent().getData(UI_NAME_PROPERTY
), null);
192 throw new IllegalStateException("UI name should not be null");
193 CmsView cmsView
= CmsSwtUtils
.getCmsView(ui
);
195 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
, cmsView
);
197 SwtUiProvider headerUiProvider
= findUiProvider(headerPid
);
198 SwtUiProvider footerUiProvider
= findUiProvider(footerPid
);
199 SwtUiProvider leadPaneUiProvider
;
200 if (adminUiName
.equals(uiName
)) {
201 leadPaneUiProvider
= findUiProvider(adminLeadPanePid
);
203 leadPaneUiProvider
= findUiProvider(leadPanePid
);
206 Localized appTitle
= null;
207 if (headerUiProvider
instanceof DefaultHeader
) {
208 appTitle
= ((DefaultHeader
) headerUiProvider
).getTitle();
210 ui
.setTitle(appTitle
);
212 if (cmsView
.isAnonymous() && publicBasePath
== null) {// internal app, must login
214 ui
.setLoginScreen(true);
215 if (headerUiProvider
!= null)
216 refreshPart(headerUiProvider
, ui
.getHeader(), context
);
217 ui
.refreshBelowHeader(false);
218 refreshPart(findUiProvider(loginScreenPid
), ui
.getBelowHeader(), context
);
219 if (footerUiProvider
!= null)
220 refreshPart(footerUiProvider
, ui
.getFooter(), context
);
221 ui
.layout(true, true);
224 if (LOGIN
.equals(state
))
226 if (ui
.isLoginScreen()) {
227 ui
.setLoginScreen(false);
229 CmsSession cmsSession
= cmsView
.getCmsSession();
230 if (ui
.getUserDir() == null) {
231 // FIXME NPE on CMSSession when logging in from anonymous
232 if (cmsSession
== null || cmsView
.isAnonymous()) {
233 assert publicBasePath
!= null;
234 Content userDir
= contentSession
235 .get(ContentUtils
.SLASH
+ CmsConstants
.SYS_WORKSPACE
+ publicBasePath
);
236 ui
.setUserDir(userDir
);
238 Node userDirNode
= jcrContentProvider
.doInAdminSession((adminSession
) -> {
239 Node node
= SuiteUtils
.getOrCreateCmsSessionNode(adminSession
, cmsSession
);
242 Content userDir
= contentSession
243 .get(ContentUtils
.SLASH
+ CmsConstants
.SYS_WORKSPACE
+ userDirNode
.getPath());
244 ui
.setUserDir(userDir
);
245 // Content userDir = contentSession.getSessionRunDir();
246 // ui.setUserDir(userDir);
249 initLocale(cmsSession
);
250 context
= stateToNode(ui
, state
);
252 context
= ui
.getUserDir();
254 if (headerUiProvider
!= null)
255 refreshPart(headerUiProvider
, ui
.getHeader(), context
);
256 ui
.refreshBelowHeader(true);
257 for (String key
: layersByPid
.keySet()) {
258 SuiteLayer layer
= layersByPid
.get(key
).get();
259 ui
.addLayer(key
, layer
);
262 if (leadPaneUiProvider
!= null)
263 refreshPart(leadPaneUiProvider
, ui
.getLeadPane(), context
);
264 if (footerUiProvider
!= null)
265 refreshPart(footerUiProvider
, ui
.getFooter(), context
);
266 ui
.layout(true, true);
267 setState(ui
, state
!= null ? state
: defaultLayerPid
);
269 } catch (Exception e
) {
270 CmsFeedback
.error("Unexpected exception", e
);
274 private void initLocale(CmsSession cmsSession
) {
275 if (cmsSession
== null)
277 Locale locale
= cmsSession
.getLocale();
278 UiContext
.setLocale(locale
);
279 LocaleUtils
.setThreadLocale(locale
);
283 private void refreshPart(SwtUiProvider uiProvider
, Composite part
, Content context
) {
284 CmsSwtUtils
.clear(part
);
285 uiProvider
.createUiPart(part
, context
);
288 private SwtUiProvider
findUiProvider(String pid
) {
289 if (!uiProvidersByPid
.containsKey(pid
))
291 return uiProvidersByPid
.get(pid
).get();
294 private SuiteLayer
findLayer(String pid
) {
295 if (!layersByPid
.containsKey(pid
))
297 return layersByPid
.get(pid
).get();
300 private <T
> T
findByType(Map
<String
, RankedObject
<T
>> byType
, Content content
) {
302 throw new IllegalArgumentException("A node should be provided");
304 if (content
instanceof JcrContent
) {
305 Node context
= ((JcrContent
) content
).getJcrNode();
308 Set
<String
> types
= new TreeSet
<>();
309 for (NodeType mixinType
: context
.getMixinNodeTypes()) {
310 String mixinTypeName
= mixinType
.getName();
311 if (byType
.containsKey(mixinTypeName
)) {
312 types
.add(mixinTypeName
);
314 for (NodeType superType
: mixinType
.getDeclaredSupertypes()) {
315 if (byType
.containsKey(superType
.getName())) {
316 types
.add(superType
.getName());
321 NodeType primaryType
= context
.getPrimaryNodeType();
322 String primaryTypeName
= primaryType
.getName();
323 if (byType
.containsKey(primaryTypeName
)) {
324 types
.add(primaryTypeName
);
326 for (NodeType superType
: primaryType
.getDeclaredSupertypes()) {
327 if (byType
.containsKey(superType
.getName())) {
328 types
.add(superType
.getName());
332 if (context
.isNodeType(EntityType
.entity
.get())) {
333 if (context
.hasProperty(EntityNames
.ENTITY_TYPE
)) {
334 String entityTypeName
= context
.getProperty(EntityNames
.ENTITY_TYPE
).getString();
335 if (byType
.containsKey(entityTypeName
)) {
336 types
.add(entityTypeName
);
341 if (CmsJcrUtils
.isUserHome(context
) && byType
.containsKey("nt:folder")) {// home node
342 types
.add("nt:folder");
345 if (types
.size() == 0)
346 throw new IllegalArgumentException(
347 "No type found for " + context
+ " (" + listTypes(context
) + ")");
348 String type
= types
.iterator().next();
349 if (!byType
.containsKey(type
))
350 throw new IllegalArgumentException("No component found for " + context
+ " with type " + type
);
351 return byType
.get(type
).get();
352 } catch (RepositoryException e
) {
353 throw new IllegalStateException(e
);
357 List
<QName
> objectClasses
= content
.getContentClasses();
358 Set
<String
> types
= new TreeSet
<>();
359 for (QName cc
: objectClasses
) {
360 String type
= cc
.getPrefix() + ":" + cc
.getLocalPart();
361 if (byType
.containsKey(type
))
364 if (types
.size() == 0) {
365 throw new IllegalArgumentException("No type found for " + content
+ " (" + objectClasses
+ ")");
367 String type
= types
.iterator().next();
368 if (!byType
.containsKey(type
))
369 throw new IllegalArgumentException("No component found for " + content
+ " with type " + type
);
370 return byType
.get(type
).get();
374 private static String
listTypes(Node context
) {
376 StringBuilder sb
= new StringBuilder();
377 sb
.append(context
.getPrimaryNodeType().getName());
378 for (NodeType superType
: context
.getPrimaryNodeType().getDeclaredSupertypes()) {
380 sb
.append(superType
.getName());
383 for (NodeType nodeType
: context
.getMixinNodeTypes()) {
385 sb
.append(nodeType
.getName());
386 if (nodeType
.getName().equals(EntityType
.local
.get()))
387 sb
.append('/').append(context
.getProperty(EntityNames
.ENTITY_TYPE
).getString());
388 for (NodeType superType
: nodeType
.getDeclaredSupertypes()) {
390 sb
.append(superType
.getName());
393 return sb
.toString();
394 } catch (RepositoryException e
) {
395 throw new JcrException(e
);
400 public void setState(CmsUi cmsUi
, String state
) {
403 if (!state
.startsWith("/")) {
404 if (cmsUi
instanceof SuiteUi
) {
405 SuiteUi ui
= (SuiteUi
) cmsUi
;
406 if (LOGIN
.equals(state
)) {
407 String appTitle
= "";
408 if (ui
.getTitle() != null)
409 appTitle
= ui
.getTitle().lead();
410 ui
.getCmsView().stateChanged(state
, appTitle
);
413 Map
<String
, Object
> properties
= new HashMap
<>();
414 String layerId
= HOME_STATE
.equals(state
) ? defaultLayerPid
: state
;
415 properties
.put(SuiteUxEvent
.LAYER
, layerId
);
416 properties
.put(SuiteUxEvent
.CONTENT_PATH
, HOME_STATE
);
417 ui
.getCmsView().sendEvent(SuiteUxEvent
.switchLayer
.topic(), properties
);
421 SuiteUi suiteUi
= (SuiteUi
) cmsUi
;
422 if (suiteUi
.isLoginScreen()) {
426 Content node
= stateToNode(suiteUi
, state
);
428 suiteUi
.getCmsView().navigateTo(HOME_STATE
);
430 suiteUi
.getCmsView().sendEvent(SuiteUxEvent
.switchLayer
.topic(), SuiteUxEvent
.eventProperties(node
));
431 suiteUi
.getCmsView().sendEvent(SuiteUxEvent
.refreshPart
.topic(), SuiteUxEvent
.eventProperties(node
));
435 // TODO move it to an internal package?
436 static String
nodeToState(Content node
) {
437 return node
.getPath();
440 private Content
stateToNode(SuiteUi suiteUi
, String state
) {
443 if (state
== null || !state
.startsWith("/"))
448 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
449 suiteUi
.getCmsView());
450 return contentSession
.get(path
);
458 public void onEvent(String topic
, Map
<String
, Object
> event
) {
460 // Specific UI related events
461 SuiteUi ui
= getRelatedUi(event
);
464 ui
.getCmsView().runAs(() -> {
466 String appTitle
= "";
467 if (ui
.getTitle() != null)
468 appTitle
= ui
.getTitle().lead() + " - ";
470 if (SuiteUiUtils
.isTopic(topic
, SuiteUxEvent
.refreshPart
)) {
471 Content node
= getContentFromEvent(ui
, event
);
474 SwtUiProvider uiProvider
= findByType(uiProvidersByType
, node
);
475 SuiteLayer layer
= findByType(layersByType
, node
);
476 ui
.switchToLayer(layer
, node
);
477 layer
.view(uiProvider
, ui
.getCurrentWorkArea(), node
);
478 ui
.getCmsView().stateChanged(nodeToState(node
), appTitle
+ CmsUxUtils
.getTitle(node
));
479 } else if (SuiteUiUtils
.isTopic(topic
, SuiteUxEvent
.openNewPart
)) {
480 Content node
= getContentFromEvent(ui
, event
);
483 SwtUiProvider uiProvider
= findByType(uiProvidersByType
, node
);
484 SuiteLayer layer
= findByType(layersByType
, node
);
485 ui
.switchToLayer(layer
, node
);
486 layer
.open(uiProvider
, ui
.getCurrentWorkArea(), node
);
487 ui
.getCmsView().stateChanged(nodeToState(node
), appTitle
+ CmsUxUtils
.getTitle(node
));
488 } else if (SuiteUiUtils
.isTopic(topic
, SuiteUxEvent
.switchLayer
)) {
489 String layerId
= get(event
, SuiteUxEvent
.LAYER
);
490 if (layerId
!= null) {
491 SuiteLayer suiteLayer
= findLayer(layerId
);
492 if (suiteLayer
== null)
493 throw new IllegalArgumentException("No layer '" + layerId
+ "' available.");
494 Localized layerTitle
= suiteLayer
.getTitle();
495 // FIXME make sure we don't rebuild the work area twice
496 Composite workArea
= ui
.switchToLayer(layerId
, ui
.getUserDir());
498 if (layerTitle
!= null)
499 title
= layerTitle
.lead();
500 Content nodeFromState
= getContentFromEvent(ui
, event
);
501 if (nodeFromState
!= null && nodeFromState
.getPath().equals(ui
.getUserDir().getPath())) {
502 // default layer view is forced
503 String state
= defaultLayerPid
.equals(layerId
) ?
"~" : layerId
;
504 ui
.getCmsView().stateChanged(state
, appTitle
+ title
);
505 suiteLayer
.view(null, workArea
, nodeFromState
);
507 Content layerCurrentContext
= suiteLayer
.getCurrentContext(workArea
);
508 if (layerCurrentContext
!= null && !layerCurrentContext
.equals(ui
.getUserDir())) {
509 // layer was already showing a context so we set the state to it
510 ui
.getCmsView().stateChanged(nodeToState(layerCurrentContext
),
511 appTitle
+ CmsUxUtils
.getTitle(layerCurrentContext
));
513 // no context was shown
514 ui
.getCmsView().stateChanged(layerId
, appTitle
+ title
);
518 Content node
= getContentFromEvent(ui
, event
);
520 SuiteLayer layer
= findByType(layersByType
, node
);
521 ui
.switchToLayer(layer
, node
);
525 } catch (Exception e
) {
526 CmsFeedback
.error("Cannot handle event " + topic
+ " " + event
, e
);
527 // log.error("Cannot handle event " + event, e);
532 protected Content
getContentFromEvent(SuiteUi ui
, Map
<String
, Object
> event
) {
533 ProvidedSession contentSession
= (ProvidedSession
) CmsUxUtils
.getContentSession(contentRepository
,
536 String path
= get(event
, SuiteUxEvent
.CONTENT_PATH
);
538 if (path
!= null && (path
.equals(HOME_STATE
) || path
.equals("")))
539 return ui
.getUserDir();
543 String username
= get(event
, SuiteUxEvent
.USERNAME
);
544 if (username
== null)
546 User user
= cmsUserManager
.getUser(username
);
549 node
= ContentUtils
.roleToContent(cmsUserManager
, contentSession
, user
);
551 node
= contentSession
.get(path
);
556 private SuiteUi
getRelatedUi(Map
<String
, Object
> eventProperties
) {
557 return managedUis
.get(get(eventProperties
, CMS_VIEW_UID_PROPERTY
));
560 public static String
get(Map
<String
, Object
> eventProperties
, String key
) {
561 Object value
= eventProperties
.get(key
);
564 return value
.toString();
569 * Dependency injection.
572 public void addUiProvider(SwtUiProvider uiProvider
, Map
<String
, Object
> properties
) {
573 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
574 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
575 RankedObject
.putIfHigherRank(uiProvidersByPid
, pid
, uiProvider
, properties
);
577 if (properties
.containsKey(EntityConstants
.TYPE
)) {
578 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
579 for (String type
: types
) {
580 RankedObject
.putIfHigherRank(uiProvidersByType
, type
, uiProvider
, properties
);
585 public void removeUiProvider(SwtUiProvider uiProvider
, Map
<String
, Object
> properties
) {
586 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
587 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
588 if (uiProvidersByPid
.containsKey(pid
)) {
589 if (uiProvidersByPid
.get(pid
).equals(new RankedObject
<SwtUiProvider
>(uiProvider
, properties
))) {
590 uiProvidersByPid
.remove(pid
);
594 if (properties
.containsKey(EntityConstants
.TYPE
)) {
595 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
596 for (String type
: types
) {
597 if (uiProvidersByType
.containsKey(type
)) {
598 if (uiProvidersByType
.get(type
).equals(new RankedObject
<SwtUiProvider
>(uiProvider
, properties
))) {
599 uiProvidersByType
.remove(type
);
606 public void addLayer(SuiteLayer layer
, Map
<String
, Object
> properties
) {
607 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
608 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
609 RankedObject
.putIfHigherRank(layersByPid
, pid
, layer
, properties
);
611 if (properties
.containsKey(EntityConstants
.TYPE
)) {
612 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
613 for (String type
: types
)
614 RankedObject
.putIfHigherRank(layersByType
, type
, layer
, properties
);
618 public void removeLayer(SuiteLayer layer
, Map
<String
, Object
> properties
) {
619 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
620 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
621 if (layersByPid
.containsKey(pid
)) {
622 if (layersByPid
.get(pid
).equals(new RankedObject
<SuiteLayer
>(layer
, properties
))) {
623 layersByPid
.remove(pid
);
627 if (properties
.containsKey(EntityConstants
.TYPE
)) {
628 List
<String
> types
= LangUtils
.toStringList(properties
.get(EntityConstants
.TYPE
));
629 for (String type
: types
) {
630 if (layersByType
.containsKey(type
)) {
631 if (layersByType
.get(type
).equals(new RankedObject
<SuiteLayer
>(layer
, properties
))) {
632 layersByType
.remove(type
);
639 public void setCmsUserManager(CmsUserManager cmsUserManager
) {
640 this.cmsUserManager
= cmsUserManager
;
643 protected ContentRepository
getContentRepository() {
644 return contentRepository
;
647 public void setContentRepository(ContentRepository contentRepository
) {
648 this.contentRepository
= contentRepository
;
651 public void setJcrContentProvider(JcrContentProvider jcrContentProvider
) {
652 this.jcrContentProvider
= jcrContentProvider
;