]> 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.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.Repository;
18 import javax.jcr.RepositoryException;
19 import javax.jcr.Session;
20 import javax.jcr.nodetype.NodeType;
21 import javax.naming.InvalidNameException;
22 import javax.naming.ldap.LdapName;
23
24 import org.argeo.api.acr.Content;
25 import org.argeo.api.acr.ContentRepository;
26 import org.argeo.api.acr.ContentSession;
27 import org.argeo.api.acr.spi.ProvidedSession;
28 import org.argeo.api.cms.CmsConstants;
29 import org.argeo.api.cms.CmsLog;
30 import org.argeo.api.cms.CmsSession;
31 import org.argeo.api.cms.CmsTheme;
32 import org.argeo.api.cms.CmsUi;
33 import org.argeo.api.cms.CmsView;
34 import org.argeo.app.api.EntityConstants;
35 import org.argeo.app.api.EntityNames;
36 import org.argeo.app.api.EntityType;
37 import org.argeo.app.api.RankedObject;
38 import org.argeo.app.core.SuiteUtils;
39 import org.argeo.cms.AbstractCmsApp;
40 import org.argeo.cms.CmsUserManager;
41 import org.argeo.cms.LocaleUtils;
42 import org.argeo.cms.Localized;
43 import org.argeo.cms.jcr.CmsJcrUtils;
44 import org.argeo.cms.jcr.acr.JcrContent;
45 import org.argeo.cms.jcr.acr.JcrContentProvider;
46 import org.argeo.cms.swt.CmsSwtUtils;
47 import org.argeo.cms.swt.dialogs.CmsFeedback;
48 import org.argeo.cms.ui.CmsUiProvider;
49 import org.argeo.cms.ux.CmsUxUtils;
50 import org.argeo.eclipse.ui.specific.UiContext;
51 import org.argeo.jcr.Jcr;
52 import org.argeo.jcr.JcrException;
53 import org.argeo.util.LangUtils;
54 import org.eclipse.swt.SWT;
55 import org.eclipse.swt.widgets.Composite;
56 import org.osgi.framework.Constants;
57 import org.osgi.service.event.Event;
58 import org.osgi.service.event.EventHandler;
59 import org.osgi.service.useradmin.User;
60
61 /** The Argeo Suite App. */
62 public class SuiteApp extends AbstractCmsApp implements EventHandler {
63 private final static CmsLog log = CmsLog.getLog(SuiteApp.class);
64
65 public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath";
66 public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName";
67 public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId";
68 public final static String DEFAULT_LAYER_PROPERTY = "defaultLayer";
69 private final static String LOGIN = "login";
70 private final static String HOME_STATE = "~";
71
72 private String publicBasePath = null;
73
74 private String pidPrefix;
75 private String headerPid;
76 private String footerPid;
77 private String leadPanePid;
78 private String adminLeadPanePid;
79 private String loginScreenPid;
80
81 private String defaultUiName = "app";
82 private String adminUiName = "admin";
83
84 // FIXME such default names make refactoring more dangerous
85 @Deprecated
86 private String defaultLayerPid = "argeo.suite.ui.dashboardLayer";
87 @Deprecated
88 private String defaultThemeId = "org.argeo.app.theme.default";
89
90 private Map<String, RankedObject<CmsUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
91 private Map<String, RankedObject<CmsUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
92 private Map<String, RankedObject<SuiteLayer>> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>());
93 private Map<String, RankedObject<SuiteLayer>> layersByType = Collections.synchronizedSortedMap(new TreeMap<>());
94
95 private CmsUserManager cmsUserManager;
96
97 // TODO make more optimal or via CmsSession/CmsView
98 private Map<String, SuiteUi> managedUis = new HashMap<>();
99
100 // ACR
101 private ContentRepository contentRepository;
102 private JcrContentProvider jcrContentProvider;
103
104 // JCR
105 private Repository repository;
106
107 public void init(Map<String, Object> properties) {
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 ContentSession contentSession = CmsUxUtils.getContentSession(contentRepository, cmsView);
196
197 CmsUiProvider headerUiProvider = findUiProvider(headerPid);
198 CmsUiProvider footerUiProvider = findUiProvider(footerPid);
199 CmsUiProvider 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 if (headerUiProvider != null)
215 refreshPart(headerUiProvider, ui.getHeader(), context);
216 ui.refreshBelowHeader(false);
217 refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context);
218 if (footerUiProvider != null)
219 refreshPart(footerUiProvider, ui.getFooter(), context);
220 ui.layout(true, true);
221 setState(ui, LOGIN);
222 } else {
223 if (LOGIN.equals(state))
224 state = null;
225 CmsSession cmsSession = cmsView.getCmsSession();
226 if (ui.getUserDirNode() == null) {
227 // FIXME NPE on CMSSession when logging in from anonymous
228 if (cmsSession == null || cmsView.isAnonymous()) {
229 assert publicBasePath != null;
230 Content userDir = contentSession.get(CmsConstants.SYS_WORKSPACE + publicBasePath);
231 ui.setUserDir(userDir);
232 // ui.initSessions(getRepository(), publicBasePath);
233 } else {
234 Session adminSession = null;
235 try {
236 adminSession = CmsJcrUtils.openDataAdminSession(getRepository(), null);
237 Node userDirNode = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
238 Content userDir = contentSession.get(CmsConstants.SYS_WORKSPACE + userDirNode.getPath());
239 ui.setUserDir(userDir);
240 // ui.initSessions(getRepository(), userDirNode.getPath());
241 } finally {
242 Jcr.logout(adminSession);
243 }
244 }
245 }
246 initLocale(cmsSession);
247 context = stateToNode(ui, state);
248 if (context == null)
249 context = ui.getUserDirNode();
250
251 if (headerUiProvider != null)
252 refreshPart(headerUiProvider, ui.getHeader(), context);
253 ui.refreshBelowHeader(true);
254 for (String key : layersByPid.keySet()) {
255 SuiteLayer layer = layersByPid.get(key).get();
256 ui.addLayer(key, layer);
257 }
258
259 if (leadPaneUiProvider != null)
260 refreshPart(leadPaneUiProvider, ui.getLeadPane(), context);
261 if (footerUiProvider != null)
262 refreshPart(footerUiProvider, ui.getFooter(), context);
263 ui.layout(true, true);
264 setState(ui, state != null ? state : defaultLayerPid);
265 }
266 } catch (Exception e) {
267 CmsFeedback.show("Unexpected exception", e);
268 }
269 }
270
271 private void initLocale(CmsSession cmsSession) {
272 if (cmsSession == null)
273 return;
274 Locale locale = cmsSession.getLocale();
275 UiContext.setLocale(locale);
276 LocaleUtils.setThreadLocale(locale);
277
278 }
279
280 private void refreshPart(CmsUiProvider uiProvider, Composite part, Content context) {
281 CmsSwtUtils.clear(part);
282 uiProvider.createUiPart(part, context);
283 }
284
285 private CmsUiProvider findUiProvider(String pid) {
286 if (!uiProvidersByPid.containsKey(pid))
287 return null;
288 return uiProvidersByPid.get(pid).get();
289 }
290
291 private SuiteLayer findLayer(String pid) {
292 if (!layersByPid.containsKey(pid))
293 return null;
294 return layersByPid.get(pid).get();
295 }
296
297 private <T> T findByType(Map<String, RankedObject<T>> byType, Content content) {
298 if (content == null)
299 throw new IllegalArgumentException("A node should be provided");
300
301 if(content instanceof JcrContent) {
302 Node context = ((JcrContent)content).getJcrNode();
303 try {
304 // mixins
305 Set<String> types = new TreeSet<>();
306 for (NodeType mixinType : context.getMixinNodeTypes()) {
307 String mixinTypeName = mixinType.getName();
308 if (byType.containsKey(mixinTypeName)) {
309 types.add(mixinTypeName);
310 }
311 for (NodeType superType : mixinType.getDeclaredSupertypes()) {
312 if (byType.containsKey(superType.getName())) {
313 types.add(superType.getName());
314 }
315 }
316 }
317 // primary node type
318 NodeType primaryType = context.getPrimaryNodeType();
319 String primaryTypeName = primaryType.getName();
320 if (byType.containsKey(primaryTypeName)) {
321 types.add(primaryTypeName);
322 }
323 for (NodeType superType : primaryType.getDeclaredSupertypes()) {
324 if (byType.containsKey(superType.getName())) {
325 types.add(superType.getName());
326 }
327 }
328 // entity type
329 if (context.isNodeType(EntityType.entity.get())) {
330 if (context.hasProperty(EntityNames.ENTITY_TYPE)) {
331 String entityTypeName = context.getProperty(EntityNames.ENTITY_TYPE).getString();
332 if (byType.containsKey(entityTypeName)) {
333 types.add(entityTypeName);
334 }
335 }
336 }
337
338 // if (context.getPath().equals("/")) {// root node
339 // types.add("nt:folder");
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("No type found for " + context + " (" + listTypes(context) + ")");
347 String type = types.iterator().next();
348 if (!byType.containsKey(type))
349 throw new IllegalArgumentException("No component found for " + context + " with type " + type);
350 return byType.get(type).get();
351 } catch (RepositoryException e) {
352 throw new IllegalStateException(e);
353 }
354
355 }else {
356 throw new UnsupportedOperationException("Content "+content.getClass().getName()+" is not supported.");
357 }
358 }
359
360 private static String listTypes(Node context) {
361 try {
362 StringBuilder sb = new StringBuilder();
363 sb.append(context.getPrimaryNodeType().getName());
364 for (NodeType superType : context.getPrimaryNodeType().getDeclaredSupertypes()) {
365 sb.append(' ');
366 sb.append(superType.getName());
367 }
368
369 for (NodeType nodeType : context.getMixinNodeTypes()) {
370 sb.append(' ');
371 sb.append(nodeType.getName());
372 if (nodeType.getName().equals(EntityType.local.get()))
373 sb.append('/').append(context.getProperty(EntityNames.ENTITY_TYPE).getString());
374 for (NodeType superType : nodeType.getDeclaredSupertypes()) {
375 sb.append(' ');
376 sb.append(superType.getName());
377 }
378 }
379 return sb.toString();
380 } catch (RepositoryException e) {
381 throw new JcrException(e);
382 }
383 }
384
385 @Override
386 public void setState(CmsUi cmsUi, String state) {
387 if (state == null)
388 return;
389 if (!state.startsWith("/")) {
390 if (cmsUi instanceof SuiteUi) {
391 SuiteUi ui = (SuiteUi) cmsUi;
392 if (LOGIN.equals(state)) {
393 String appTitle = "";
394 if (ui.getTitle() != null)
395 appTitle = ui.getTitle().lead();
396 ui.getCmsView().stateChanged(state, appTitle);
397 return;
398 }
399 Map<String, Object> properties = new HashMap<>();
400 String layerId = HOME_STATE.equals(state) ? defaultLayerPid : state;
401 properties.put(SuiteEvent.LAYER, layerId);
402 properties.put(SuiteEvent.NODE_PATH, HOME_STATE);
403 ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties);
404 }
405 return;
406 }
407 SuiteUi suiteUi = (SuiteUi) cmsUi;
408 Content node = stateToNode(suiteUi, state);
409 if (node == null) {
410 suiteUi.getCmsView().navigateTo(HOME_STATE);
411 } else {
412 suiteUi.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node));
413 suiteUi.getCmsView().sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node));
414 }
415 }
416
417 // TODO move it to an internal package?
418 static String nodeToState(Content node) {
419 return node.getPath();
420 }
421
422 private Content stateToNode(SuiteUi suiteUi, String state) {
423 if (suiteUi == null)
424 return null;
425 if (state == null || !state.startsWith("/"))
426 return null;
427
428 String path=state;
429 // String path = state.substring(1);
430 // String workspace;
431 // if (path.equals("")) {
432 // workspace = null;
433 // path = "/";
434 // } else {
435 // int index = path.indexOf('/');
436 // if (index == 0) {
437 // log.error("Cannot interpret " + state);
438 //// cmsView.navigateTo("~");
439 // return null;
440 // } else if (index > 0) {
441 // workspace = path.substring(0, index);
442 // path = path.substring(index);
443 // } else {// index<0, assuming root node
444 // workspace = path;
445 // path = "/";
446 // }
447 // }
448
449 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
450 suiteUi.getCmsView());
451 return contentSession.get(path);
452 // Session session = jcrContentProvider.getJcrSession(contentSession, workspace);
453 //// Session session = suiteUi.getSession(workspace);
454 // if (session == null)
455 // return null;
456 // Node node = Jcr.getNode(session, path);
457 // return node;
458 }
459
460 /*
461 * Events management
462 */
463
464 @Override
465 public void handleEvent(Event event) {
466
467 // Specific UI related events
468 SuiteUi ui = getRelatedUi(event);
469 if (ui == null)
470 return;
471 try {
472 String appTitle = "";
473 if (ui.getTitle() != null)
474 appTitle = ui.getTitle().lead() + " - ";
475
476 // String currentLayerId = ui.getCurrentLayerId();
477 // SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null;
478 if (SuiteUiUtils.isTopic(event, SuiteEvent.refreshPart)) {
479 Content node = getNode(ui, event);
480 if (node == null)
481 return;
482 CmsUiProvider uiProvider = findByType(uiProvidersByType, node);
483 SuiteLayer layer = findByType(layersByType, node);
484 ui.switchToLayer(layer, node);
485 ui.getCmsView().runAs(() -> layer.view(uiProvider, ui.getCurrentWorkArea(), node));
486 ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
487 } else if (SuiteUiUtils.isTopic(event, SuiteEvent.openNewPart)) {
488 Content node = getNode(ui, event);
489 if (node == null)
490 return;
491 CmsUiProvider uiProvider = findByType(uiProvidersByType, node);
492 SuiteLayer layer = findByType(layersByType, node);
493 ui.switchToLayer(layer, node);
494 ui.getCmsView().runAs(() -> layer.open(uiProvider, ui.getCurrentWorkArea(), node));
495 ui.getCmsView().stateChanged(nodeToState(node), appTitle + CmsUxUtils.getTitle(node));
496 } else if (SuiteUiUtils.isTopic(event, SuiteEvent.switchLayer)) {
497 String layerId = get(event, SuiteEvent.LAYER);
498 if (layerId != null) {
499 // ui.switchToLayer(layerId, ui.getUserDir());
500 SuiteLayer suiteLayer = findLayer(layerId);
501 if (suiteLayer == null)
502 throw new IllegalArgumentException("No layer '" + layerId + "' available.");
503 Localized layerTitle = suiteLayer.getTitle();
504 // FIXME make sure we don't rebuild the work area twice
505 Composite workArea = ui.getCmsView().doAs(() -> ui.switchToLayer(layerId, ui.getUserDirNode()));
506 String title = null;
507 if (layerTitle != null)
508 title = layerTitle.lead();
509 Content nodeFromState = getNode(ui, event);
510 if (nodeFromState != null && nodeFromState.getPath().equals(ui.getUserDirNode().getPath())) {
511 // default layer view is forced
512 String state = defaultLayerPid.equals(layerId) ? "~" : layerId;
513 ui.getCmsView().stateChanged(state, appTitle + title);
514 suiteLayer.view(null, workArea, nodeFromState);
515 } else {
516 Content layerCurrentContext = suiteLayer.getCurrentContext(workArea);
517 if (layerCurrentContext != null) {
518 // layer was already showing a context so we set the state to it
519 ui.getCmsView().stateChanged(nodeToState(layerCurrentContext),
520 appTitle + CmsUxUtils.getTitle(layerCurrentContext));
521 } else {
522 // no context was shown
523 ui.getCmsView().stateChanged(layerId, appTitle + title);
524 }
525 }
526 } else {
527 Content node = getNode(ui, event);
528 if (node != null) {
529 SuiteLayer layer = findByType(layersByType, node);
530 ui.getCmsView().runAs(() -> ui.switchToLayer(layer, node));
531 }
532 }
533 }
534 } catch (Exception e) {
535 log.error("Cannot handle event " + event, e);
536 // CmsView.getCmsView(ui).exception(e);
537 }
538
539 }
540
541 private Content getNode(SuiteUi ui, Event event) {
542 ProvidedSession contentSession = (ProvidedSession) CmsUxUtils.getContentSession(contentRepository,
543 ui.getCmsView());
544
545 String path = get(event,SuiteEvent.CONTENT_PATH);
546
547 // String nodePath = get(event, SuiteEvent.NODE_PATH);
548 if (path != null && path.equals(HOME_STATE))
549 return ui.getUserDir();
550 // String workspace = get(event, SuiteEvent.WORKSPACE);
551
552 // Session session = jcrContentProvider.getJcrSession(contentSession, workspace);
553 //// Session session = ui.getSession(workspace);
554 Content node;
555 if (path == null) {
556 // look for a user
557 String username = get(event, SuiteEvent.USERNAME);
558 if (username == null)
559 return null;
560 User user = cmsUserManager.getUser(username);
561 if (user == null)
562 return null;
563 LdapName userDn;
564 try {
565 userDn = new LdapName(user.getName());
566 } catch (InvalidNameException e) {
567 throw new IllegalArgumentException("Badly formatted username", e);
568 }
569 String userNodePath = SuiteUtils.getUserNodePath(userDn);
570 // FIXME deal with home path
571 return null;
572 // if (Jcr.itemExists(session, userNodePath))
573 // node = Jcr.getNode(session, userNodePath);
574 // else {
575 // Session adminSession = null;
576 // try {
577 // adminSession = CmsJcrUtils.openDataAdminSession(getRepository(), workspace);
578 // SuiteUtils.getOrCreateUserNode(adminSession, userDn);
579 // } finally {
580 // Jcr.logout(adminSession);
581 // }
582 // node = Jcr.getNode(session, userNodePath);
583 // }
584 } else {
585 node = contentSession.get(path);
586 }
587 return node;
588 }
589
590 private SuiteUi getRelatedUi(Event event) {
591 return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY));
592 }
593
594 public static String get(Event event, String key) {
595 Object value = event.getProperty(key);
596 if (value == null)
597 return null;
598 // throw new IllegalArgumentException("Property " + key + " must be set");
599 return value.toString();
600
601 }
602
603 /*
604 * Dependency injection.
605 */
606
607 public void addUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
608 if (properties.containsKey(Constants.SERVICE_PID)) {
609 String pid = (String) properties.get(Constants.SERVICE_PID);
610 RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties);
611 }
612 if (properties.containsKey(EntityConstants.TYPE)) {
613 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
614 for (String type : types)
615 RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties);
616 }
617 }
618
619 public void removeUiProvider(CmsUiProvider uiProvider, Map<String, Object> properties) {
620 if (properties.containsKey(Constants.SERVICE_PID)) {
621 String pid = (String) properties.get(Constants.SERVICE_PID);
622 if (uiProvidersByPid.containsKey(pid)) {
623 if (uiProvidersByPid.get(pid).equals(new RankedObject<CmsUiProvider>(uiProvider, properties))) {
624 uiProvidersByPid.remove(pid);
625 }
626 }
627 }
628 if (properties.containsKey(EntityConstants.TYPE)) {
629 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
630 for (String type : types) {
631 if (uiProvidersByType.containsKey(type)) {
632 if (uiProvidersByType.get(type).equals(new RankedObject<CmsUiProvider>(uiProvider, properties))) {
633 uiProvidersByType.remove(type);
634 }
635 }
636 }
637 }
638 }
639
640 public void addLayer(SuiteLayer layer, Map<String, Object> properties) {
641 if (properties.containsKey(Constants.SERVICE_PID)) {
642 String pid = (String) properties.get(Constants.SERVICE_PID);
643 RankedObject.putIfHigherRank(layersByPid, pid, layer, properties);
644 }
645 if (properties.containsKey(EntityConstants.TYPE)) {
646 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
647 for (String type : types)
648 RankedObject.putIfHigherRank(layersByType, type, layer, properties);
649 }
650 }
651
652 public void removeLayer(SuiteLayer layer, Map<String, Object> properties) {
653 if (properties.containsKey(Constants.SERVICE_PID)) {
654 String pid = (String) properties.get(Constants.SERVICE_PID);
655 if (layersByPid.containsKey(pid)) {
656 if (layersByPid.get(pid).equals(new RankedObject<SuiteLayer>(layer, properties))) {
657 layersByPid.remove(pid);
658 }
659 }
660 }
661 if (properties.containsKey(EntityConstants.TYPE)) {
662 List<String> types = LangUtils.toStringList(properties.get(EntityConstants.TYPE));
663 for (String type : types) {
664 if (layersByType.containsKey(type)) {
665 if (layersByType.get(type).equals(new RankedObject<SuiteLayer>(layer, properties))) {
666 layersByType.remove(type);
667 }
668 }
669 }
670 }
671 }
672
673 public void setCmsUserManager(CmsUserManager cmsUserManager) {
674 this.cmsUserManager = cmsUserManager;
675 }
676
677 protected Repository getRepository() {
678 return repository;
679 }
680
681 public void setRepository(Repository repository) {
682 this.repository = repository;
683 }
684
685 protected ContentRepository getContentRepository() {
686 return contentRepository;
687 }
688
689 public void setContentRepository(ContentRepository contentRepository) {
690 this.contentRepository = contentRepository;
691 }
692
693 public void setJcrContentProvider(JcrContentProvider jcrContentProvider) {
694 this.jcrContentProvider = jcrContentProvider;
695 }
696
697 }