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