]> git.argeo.org Git - gpl/argeo-suite.git/blob - swt/org.argeo.app.ui/src/org/argeo/app/ui/SuiteApp.java
Load maintenance resources relative to class
[gpl/argeo-suite.git] / swt / org.argeo.app.ui / src / org / argeo / 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.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;
55
56 /** The Argeo Suite App. */
57 public class SuiteApp extends AbstractCmsApp implements CmsEventSubscriber {
58 private final static CmsLog log = CmsLog.getLog(SuiteApp.class);
59
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 = "~";
66
67 private String publicBasePath = null;
68
69 private String pidPrefix;
70 private String headerPid;
71 private String footerPid;
72 private String leadPanePid;
73 private String adminLeadPanePid;
74 private String loginScreenPid;
75
76 private String defaultUiName = "app";
77 private String adminUiName = "admin";
78
79 // FIXME such default names make refactoring more dangerous
80 @Deprecated
81 private String defaultLayerPid = "argeo.suite.ui.dashboardLayer";
82 @Deprecated
83 private String defaultThemeId = "org.argeo.app.theme.default";
84
85 // TODO use QName as key for byType
86 private Map<String, RankedObject<SwtUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
87 private Map<String, RankedObject<SwtUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
88 private Map<String, RankedObject<SuiteLayer>> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>());
89 private Map<String, RankedObject<SuiteLayer>> layersByType = Collections.synchronizedSortedMap(new TreeMap<>());
90
91 private CmsUserManager cmsUserManager;
92
93 // TODO make more optimal or via CmsSession/CmsView
94 private Map<String, SuiteUi> managedUis = new HashMap<>();
95
96 // ACR
97 private ContentRepository contentRepository;
98 private JcrContentProvider jcrContentProvider;
99
100 // JCR
101 // private Repository repository;
102
103 public void init(Map<String, Object> properties) {
104 for (SuiteUxEvent event : SuiteUxEvent.values()) {
105 getCmsContext().getCmsEventBus().addEventSubscriber(event.topic(), this);
106 }
107
108 if (log.isDebugEnabled())
109 log.info("Argeo Suite App started");
110
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);
118
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());
123 }
124 }
125
126 if (pidPrefix == null)
127 throw new IllegalArgumentException("PID prefix must be set.");
128
129 headerPid = pidPrefix + "header";
130 footerPid = pidPrefix + "footer";
131 leadPanePid = pidPrefix + "leadPane";
132 adminLeadPanePid = pidPrefix + "adminLeadPane";
133 loginScreenPid = pidPrefix + "loginScreen";
134 }
135
136 public void destroy(Map<String, Object> properties) {
137 for (SuiteUi ui : managedUis.values())
138 if (!ui.isDisposed()) {
139 ui.getDisplay().syncExec(() -> ui.dispose());
140 }
141 if (log.isDebugEnabled())
142 log.info("Argeo Suite App stopped");
143
144 }
145
146 @Override
147 public Set<String> getUiNames() {
148 HashSet<String> uiNames = new HashSet<>();
149 uiNames.add(defaultUiName);
150 uiNames.add(adminUiName);
151 return uiNames;
152 }
153
154 @Override
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()
158 : null;
159 CmsView cmsView = CmsSwtUtils.getCmsView(uiParent);
160 if (cmsView == null)
161 throw new IllegalStateException("No CMS view is registered.");
162 CmsTheme theme = getTheme(uiName);
163 if (theme != null)
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.");
172 });
173 return argeoSuiteUi;
174 }
175
176 @Override
177 public String getThemeId(String uiName) {
178 String themeId = System.getProperty("org.argeo.app.theme.default");
179 if (themeId != null)
180 return themeId;
181 return defaultThemeId;
182 }
183
184 @Override
185 public void refreshUi(CmsUi cmsUi, String state) {
186 try {
187 Content context = null;
188 SuiteUi ui = (SuiteUi) cmsUi;
189
190 String uiName = Objects.toString(ui.getParent().getData(UI_NAME_PROPERTY), null);
191 if (uiName == null)
192 throw new IllegalStateException("UI name should not be null");
193 CmsView cmsView = CmsSwtUtils.getCmsView(ui);
194
195 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository, cmsView);
196
197 SwtUiProvider headerUiProvider = findUiProvider(headerPid);
198 SwtUiProvider footerUiProvider = findUiProvider(footerPid);
199 SwtUiProvider leadPaneUiProvider;
200 if (adminUiName.equals(uiName)) {
201 leadPaneUiProvider = findUiProvider(adminLeadPanePid);
202 } else {
203 leadPaneUiProvider = findUiProvider(leadPanePid);
204 }
205
206 Localized appTitle = null;
207 if (headerUiProvider instanceof DefaultHeader) {
208 appTitle = ((DefaultHeader) headerUiProvider).getTitle();
209 }
210 ui.setTitle(appTitle);
211
212 if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login
213 ui.logout();
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);
222 setState(ui, LOGIN);
223 } else {
224 if (LOGIN.equals(state))
225 state = null;
226 if (ui.isLoginScreen()) {
227 ui.setLoginScreen(false);
228 }
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);
237 } else {
238 Node userDirNode = jcrContentProvider.doInAdminSession((adminSession) -> {
239 Node node = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
240 return node;
241 });
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);
247 }
248 }
249 initLocale(cmsSession);
250 context = stateToNode(ui, state);
251 if (context == null)
252 context = ui.getUserDir();
253
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);
260 }
261
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);
268 }
269 } catch (Exception e) {
270 CmsFeedback.error("Unexpected exception", e);
271 }
272 }
273
274 private void initLocale(CmsSession cmsSession) {
275 if (cmsSession == null)
276 return;
277 Locale locale = cmsSession.getLocale();
278 UiContext.setLocale(locale);
279 LocaleUtils.setThreadLocale(locale);
280
281 }
282
283 private void refreshPart(SwtUiProvider uiProvider, Composite part, Content context) {
284 CmsSwtUtils.clear(part);
285 uiProvider.createUiPart(part, context);
286 }
287
288 private SwtUiProvider findUiProvider(String pid) {
289 if (!uiProvidersByPid.containsKey(pid))
290 return null;
291 return uiProvidersByPid.get(pid).get();
292 }
293
294 private SuiteLayer findLayer(String pid) {
295 if (!layersByPid.containsKey(pid))
296 return null;
297 return layersByPid.get(pid).get();
298 }
299
300 private <T> T findByType(Map<String, RankedObject<T>> byType, Content content) {
301 if (content == null)
302 throw new IllegalArgumentException("A node should be provided");
303
304 if (content instanceof JcrContent) {
305 Node context = ((JcrContent) content).getJcrNode();
306 try {
307 // mixins
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);
313 }
314 for (NodeType superType : mixinType.getDeclaredSupertypes()) {
315 if (byType.containsKey(superType.getName())) {
316 types.add(superType.getName());
317 }
318 }
319 }
320 // primary node type
321 NodeType primaryType = context.getPrimaryNodeType();
322 String primaryTypeName = primaryType.getName();
323 if (byType.containsKey(primaryTypeName)) {
324 types.add(primaryTypeName);
325 }
326 for (NodeType superType : primaryType.getDeclaredSupertypes()) {
327 if (byType.containsKey(superType.getName())) {
328 types.add(superType.getName());
329 }
330 }
331 // entity type
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);
337 }
338 }
339 }
340
341 if (CmsJcrUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node
342 types.add("nt:folder");
343 }
344
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);
354 }
355
356 } else {
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))
362 types.add(type);
363 }
364 if (types.size() == 0) {
365 throw new IllegalArgumentException("No type found for " + content + " (" + objectClasses + ")");
366 }
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();
371 }
372 }
373
374 private static String listTypes(Node context) {
375 try {
376 StringBuilder sb = new StringBuilder();
377 sb.append(context.getPrimaryNodeType().getName());
378 for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
379 sb.append(' ');
380 sb.append(superType.getName());
381 }
382
383 for (NodeType nodeType : context.getMixinNodeTypes()) {
384 sb.append(' ');
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()) {
389 sb.append(' ');
390 sb.append(superType.getName());
391 }
392 }
393 return sb.toString();
394 } catch (RepositoryException e) {
395 throw new JcrException(e);
396 }
397 }
398
399 @Override
400 public void setState(CmsUi cmsUi, String state) {
401 if (state == null)
402 return;
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);
411 return;
412 }
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);
418 }
419 return;
420 }
421 SuiteUi suiteUi = (SuiteUi) cmsUi;
422 if (suiteUi.isLoginScreen()) {
423 return;
424 }
425
426 Content node = stateToNode(suiteUi, state);
427 if (node == null) {
428 suiteUi.getCmsView().navigateTo(HOME_STATE);
429 } else {
430 suiteUi.getCmsView().sendEvent(SuiteUxEvent.switchLayer.topic(), SuiteUxEvent.eventProperties(node));
431 suiteUi.getCmsView().sendEvent(SuiteUxEvent.refreshPart.topic(), SuiteUxEvent.eventProperties(node));
432 }
433 }
434
435 // TODO move it to an internal package?
436 static String nodeToState(Content node) {
437 return node.getPath();
438 }
439
440 private Content stateToNode(SuiteUi suiteUi, String state) {
441 if (suiteUi == null)
442 return null;
443 if (state == null || !state.startsWith("/"))
444 return null;
445
446 String path = state;
447
448 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
449 suiteUi.getCmsView());
450 return contentSession.get(path);
451 }
452
453 /*
454 * Events management
455 */
456
457 @Override
458 public void onEvent(String topic, Map<String, Object> event) {
459
460 // Specific UI related events
461 SuiteUi ui = getRelatedUi(event);
462 if (ui == null)
463 return;
464 ui.getCmsView().runAs(() -> {
465 try {
466 String appTitle = "";
467 if (ui.getTitle() != null)
468 appTitle = ui.getTitle().lead() + " - ";
469
470 if (SuiteUiUtils.isTopic(topic, SuiteUxEvent.refreshPart)) {
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.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);
481 if (node == null)
482 return;
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());
497 String title = null;
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);
506 } else {
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));
512 } else {
513 // no context was shown
514 ui.getCmsView().stateChanged(layerId, appTitle + title);
515 }
516 }
517 } else {
518 Content node = getContentFromEvent(ui, event);
519 if (node != null) {
520 SuiteLayer layer = findByType(layersByType, node);
521 ui.switchToLayer(layer, node);
522 }
523 }
524 }
525 } catch (Exception e) {
526 CmsFeedback.error("Cannot handle event " + topic + " " + event, e);
527 // log.error("Cannot handle event " + event, e);
528 }
529 });
530 }
531
532 protected Content getContentFromEvent(SuiteUi ui, Map<String, Object> event) {
533 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
534 ui.getCmsView());
535
536 String path = get(event, SuiteUxEvent.CONTENT_PATH);
537
538 if (path != null && (path.equals(HOME_STATE) || path.equals("")))
539 return ui.getUserDir();
540 Content node;
541 if (path == null) {
542 // look for a user
543 String username = get(event, SuiteUxEvent.USERNAME);
544 if (username == null)
545 return null;
546 User user = cmsUserManager.getUser(username);
547 if (user == null)
548 return null;
549 node = ContentUtils.roleToContent(cmsUserManager, contentSession, user);
550 } else {
551 node = contentSession.get(path);
552 }
553 return node;
554 }
555
556 private SuiteUi getRelatedUi(Map<String, Object> eventProperties) {
557 return managedUis.get(get(eventProperties, CMS_VIEW_UID_PROPERTY));
558 }
559
560 public static String get(Map<String, Object> eventProperties, String key) {
561 Object value = eventProperties.get(key);
562 if (value == null)
563 return null;
564 return value.toString();
565
566 }
567
568 /*
569 * Dependency injection.
570 */
571
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);
576 }
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);
581 }
582 }
583 }
584
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);
591 }
592 }
593 }
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);
600 }
601 }
602 }
603 }
604 }
605
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);
610 }
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);
615 }
616 }
617
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);
624 }
625 }
626 }
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);
633 }
634 }
635 }
636 }
637 }
638
639 public void setCmsUserManager(CmsUserManager cmsUserManager) {
640 this.cmsUserManager = cmsUserManager;
641 }
642
643 protected ContentRepository getContentRepository() {
644 return contentRepository;
645 }
646
647 public void setContentRepository(ContentRepository contentRepository) {
648 this.contentRepository = contentRepository;
649 }
650
651 public void setJcrContentProvider(JcrContentProvider jcrContentProvider) {
652 this.jcrContentProvider = jcrContentProvider;
653 }
654
655 }