]>
git.argeo.org Git - gpl/argeo-suite.git/blob - org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java
1 package org
.argeo
.suite
.ui
;
3 import static org
.argeo
.cms
.ui
.CmsView
.CMS_VIEW_UID_PROPERTY
;
5 import java
.util
.Collections
;
6 import java
.util
.HashMap
;
7 import java
.util
.HashSet
;
10 import java
.util
.TreeMap
;
11 import java
.util
.TreeSet
;
13 import javax
.jcr
.Node
;
14 import javax
.jcr
.RepositoryException
;
15 import javax
.jcr
.Session
;
16 import javax
.jcr
.nodetype
.NodeType
;
18 import org
.apache
.commons
.logging
.Log
;
19 import org
.apache
.commons
.logging
.LogFactory
;
20 import org
.argeo
.api
.NodeUtils
;
21 import org
.argeo
.cms
.ui
.AbstractCmsApp
;
22 import org
.argeo
.cms
.ui
.CmsTheme
;
23 import org
.argeo
.cms
.ui
.CmsUiProvider
;
24 import org
.argeo
.cms
.ui
.CmsView
;
25 import org
.argeo
.cms
.ui
.dialogs
.CmsFeedback
;
26 import org
.argeo
.cms
.ui
.util
.CmsEvent
;
27 import org
.argeo
.cms
.ui
.util
.CmsUiUtils
;
28 import org
.argeo
.entity
.EntityConstants
;
29 import org
.argeo
.entity
.EntityNames
;
30 import org
.argeo
.entity
.EntityTypes
;
31 import org
.argeo
.jcr
.Jcr
;
32 import org
.argeo
.jcr
.JcrUtils
;
33 import org
.argeo
.suite
.RankedObject
;
34 import org
.eclipse
.swt
.SWT
;
35 import org
.eclipse
.swt
.widgets
.Composite
;
36 import org
.osgi
.framework
.Constants
;
37 import org
.osgi
.service
.event
.Event
;
38 import org
.osgi
.service
.event
.EventHandler
;
40 /** The Argeo Suite App. */
41 public class SuiteApp
extends AbstractCmsApp
implements EventHandler
{
42 private final static Log log
= LogFactory
.getLog(SuiteApp
.class);
44 public final static String PID_PREFIX
= "argeo.suite.ui.";
45 public final static String HEADER_PID
= PID_PREFIX
+ "header";
46 public final static String LEAD_PANE_PID
= PID_PREFIX
+ "leadPane";
47 public final static String LOGIN_SCREEN_PID
= PID_PREFIX
+ "loginScreen";
48 // public final static String DASHBOARD_LAYER_PID = PID_PREFIX +
50 public final static String DASHBOARD_PID
= PID_PREFIX
+ "dashboard";
51 public final static String RECENT_ITEMS_PID
= PID_PREFIX
+ "recentItems";
53 private final static String DEFAULT_UI_NAME
= "app";
54 private final static String DEFAULT_THEME_ID
= "org.argeo.suite.theme.default";
56 private Map
<String
, RankedObject
<CmsUiProvider
>> uiProvidersByPid
= Collections
.synchronizedMap(new HashMap
<>());
57 private Map
<String
, RankedObject
<CmsUiProvider
>> uiProvidersByType
= Collections
.synchronizedMap(new HashMap
<>());
58 private Map
<String
, RankedObject
<SuiteLayer
>> layers
= Collections
.synchronizedSortedMap(new TreeMap
<>());
60 // TODO make more optimal or via CmsSession/CmsView
61 private Map
<String
, SuiteUi
> managedUis
= new HashMap
<>();
63 // private CmsUiProvider headerPart = null;
65 public void init(Map
<String
, String
> properties
) {
66 if (log
.isDebugEnabled())
67 log
.info("Argeo Suite App started");
70 public void destroy(Map
<String
, String
> properties
) {
71 for (SuiteUi ui
: managedUis
.values())
74 if (log
.isDebugEnabled())
75 log
.info("Argeo Suite App stopped");
80 public Set
<String
> getUiNames() {
81 HashSet
<String
> uiNames
= new HashSet
<>();
82 uiNames
.add(DEFAULT_UI_NAME
);
87 public Composite
initUi(Composite parent
) {
88 String uiName
= parent
.getData(UI_NAME_PROPERTY
) != null ? parent
.getData(UI_NAME_PROPERTY
).toString() : null;
89 CmsView cmsView
= CmsView
.getCmsView(parent
);
91 throw new IllegalStateException("No CMS view is registered.");
92 CmsTheme theme
= getTheme(uiName
);
94 CmsTheme
.registerCmsTheme(parent
.getShell(), theme
);
95 SuiteUi argeoSuiteUi
= new SuiteUi(parent
, SWT
.NONE
);
96 String uid
= cmsView
.getUid();
97 managedUis
.put(uid
, argeoSuiteUi
);
98 argeoSuiteUi
.addDisposeListener((e
) -> {
99 managedUis
.remove(uid
);
100 if (log
.isDebugEnabled())
101 log
.debug("Suite UI " + uid
+ " has been disposed.");
103 refreshUi(argeoSuiteUi
, null);
108 public String
getThemeId(String uiName
) {
109 // TODO make it configurable
110 return DEFAULT_THEME_ID
;
114 public void refreshUi(Composite parent
, String state
) {
117 SuiteUi ui
= (SuiteUi
) parent
;
118 refreshPart(findUiProvider(HEADER_PID
), ui
.getHeader(), context
);
119 CmsView cmsView
= CmsView
.getCmsView(parent
);
120 if (cmsView
.isAnonymous()) {
121 ui
.refreshBelowHeader(false);
122 refreshPart(findUiProvider(LOGIN_SCREEN_PID
), ui
.getBelowHeader(), context
);
125 if (ui
.getUserHome() == null)
126 ui
.initSessions(getRepository());
127 context
= ui
.getUserHome();
129 } catch (RepositoryException e
) {
132 ui
.refreshBelowHeader(true);
134 for (String key
: layers
.keySet()) {
135 SuiteLayer layer
= layers
.get(key
).get();
136 ui
.addLayer(key
, layer
);
139 // ui.addLayer(ArgeoSuiteUi.DASHBOARD_LAYER);
140 // ui.addLayer("documents");
141 // ui.addLayer("locations");
142 // ui.addLayer("people");
143 // ui.switchToLayer(DASHBOARD_LAYER_PID, context);
145 // refreshPart(findUiProvider(DASHBOARD_PID), ui.getTabbedArea().getCurrent(), context);
146 refreshPart(findUiProvider(LEAD_PANE_PID
), ui
.getLeadPane(), context
);
147 // refreshPart(findUiProvider(RECENT_ITEMS_PID), ui.getEntryArea(), context);
149 ui
.layout(true, true);
150 } catch (Exception e
) {
151 CmsFeedback
.show("Unexpected exception", e
);
155 private void refreshPart(CmsUiProvider uiProvider
, Composite part
, Node context
) {
156 CmsUiUtils
.clear(part
);
157 uiProvider
.createUiPart(part
, context
);
160 private CmsUiProvider
findUiProvider(String pid
) {
161 if (!uiProvidersByPid
.containsKey(pid
))
162 throw new IllegalArgumentException("No UI provider registered as " + pid
);
163 return uiProvidersByPid
.get(pid
).get();
166 private CmsUiProvider
findUiProvider(Node context
) {
169 Set
<String
> types
= new TreeSet
<>();
170 for (NodeType nodeType
: context
.getMixinNodeTypes()) {
171 String typeName
= nodeType
.getName();
172 if (uiProvidersByType
.containsKey(typeName
)) {
178 NodeType nodeType
= context
.getPrimaryNodeType();
179 String typeName
= nodeType
.getName();
180 if (uiProvidersByType
.containsKey(typeName
)) {
185 if (context
.isNodeType(EntityTypes
.ENTITY_ENTITY
)) {
186 String typeName
=context
.getProperty(EntityNames
.ENTITY_TYPE
).getString();
187 if (uiProvidersByType
.containsKey(typeName
)) {
192 // if (context.getPath().equals("/")) {// root node
193 // types.add("nt:folder");
195 if (NodeUtils
.isUserHome(context
) && uiProvidersByType
.containsKey("nt:folder")) {// home node
196 types
.add("nt:folder");
199 if (types
.size() == 0)
200 throw new IllegalArgumentException("No UI provider found for " + context
);
201 return uiProvidersByType
.get(types
.iterator().next()).get();
202 } catch (RepositoryException e
) {
203 throw new IllegalStateException(e
);
206 // private CmsUiProvider findUiProvider(String pid, Node context) {
207 // CmsUiProvider found = null;
208 // if (pid != null) {
209 // SortedMap<RankingKey, CmsUiProvider> subMap = uiProvidersByPid.subMap(RankingKey.minPid(pid),
210 // RankingKey.maxPid(pid));
211 // providers: for (RankingKey key : subMap.keySet()) {
212 // if (key.getPid() == null || !key.getPid().equals(pid))
214 // found = subMap.get(key);
216 // if (found != null)
220 // if (found == null && context != null) {
221 // SortedMap<RankingKey, CmsUiProvider> subMap = null;
222 // String dataType = null;
223 // if (Jcr.isNodeType(context, EntityTypes.ENTITY_ENTITY)) {
224 // dataType = Jcr.get(context, EntityNames.ENTITY_TYPE);
225 // subMap = uiProvidersByPid.subMap(RankingKey.minDataType(dataType), RankingKey.maxDataType(dataType));
227 // providers: for (RankingKey key : subMap.keySet()) {
228 // if (key.getDataType() == null || !key.getDataType().equals(dataType))
230 // found = subMap.get(key);
232 // if (found == null)
233 // found = uiProvidersByPid.get(new RankingKey(null, null, null, dataType, null));
234 // if (found != null)
239 // if (log.isWarnEnabled())
240 // log.warn("No UI provider found for" + (pid != null ? " pid " + pid : "")
241 // + (context != null ? " " + context : ""));
242 // return new CmsUiProvider() {
245 // public Control createUi(Composite parent, Node context) throws RepositoryException {
252 public void setState(Composite parent
, String state
) {
253 CmsView cmsView
= CmsView
.getCmsView(parent
);
254 // for the time being we systematically open a session, in order to make sure
255 // that home is initialised
256 Session session
= null;
258 if (state
!= null && state
.startsWith("/")) {
259 String path
= state
.substring(1);
261 if (path
.equals("")) {
265 int index
= path
.indexOf('/');
267 log
.error("Cannot interpret // " + state
);
268 cmsView
.navigateTo("~");
270 } else if (index
> 0) {
271 workspace
= path
.substring(0, index
);
272 path
= path
.substring(index
);
273 } else {// index<0, assuming root node
278 session
= getRepository().login(workspace
);
280 Node node
= session
.getNode(path
);
282 refreshEntityUi(null, node
);
284 } catch (RepositoryException e
) {
285 log
.error("Cannot load state " + state
, e
);
286 cmsView
.navigateTo("~");
288 JcrUtils
.logoutQuietly(session
);
292 private void refreshEntityUi(Composite parent
, Node context
) {
296 * Dependency injection.
299 public void addUiProvider(CmsUiProvider uiProvider
, Map
<String
, Object
> properties
) {
300 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
301 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
302 RankedObject
.putIfHigherRank(uiProvidersByPid
, pid
, uiProvider
, properties
);
304 if (properties
.containsKey(EntityConstants
.TYPE
)) {
305 // TODO manage String arrays as well
306 String type
= (String
) properties
.get(EntityConstants
.TYPE
);
307 RankedObject
.putIfHigherRank(uiProvidersByType
, type
, uiProvider
, properties
);
311 public void removeUiProvider(CmsUiProvider uiProvider
, Map
<String
, Object
> properties
) {
312 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
313 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
314 if (uiProvidersByPid
.containsKey(pid
)) {
315 if (uiProvidersByPid
.get(pid
).equals(new RankedObject
<CmsUiProvider
>(uiProvider
, properties
))) {
316 uiProvidersByPid
.remove(pid
);
323 public void addLayer(SuiteLayer layer
, Map
<String
, Object
> properties
) {
324 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
325 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
326 RankedObject
.putIfHigherRank(layers
, pid
, layer
, properties
);
330 public void removeLayer(SuiteLayer layer
, Map
<String
, Object
> properties
) {
331 if (properties
.containsKey(Constants
.SERVICE_PID
)) {
332 String pid
= (String
) properties
.get(Constants
.SERVICE_PID
);
333 if (layers
.containsKey(pid
)) {
334 if (layers
.get(pid
).equals(new RankedObject
<SuiteLayer
>(layer
, properties
))) {
342 public void handleEvent(Event event
) {
344 // Specific UI related events
345 SuiteUi ui
= getRelatedUi(event
);
347 String currentLayerId
= ui
.getCurrentLayerId();
348 SuiteLayer layer
= currentLayerId
!= null ? layers
.get(currentLayerId
).get() : null;
349 if (isTopic(event
, SuiteEvent
.refreshPart
)) {
350 String nodeId
= get(event
, SuiteEvent
.NODE_ID
);
351 String workspace
= get(event
, SuiteEvent
.WORKSPACE
);
352 Node node
= Jcr
.getNodeById(ui
.getSession(workspace
), nodeId
);
353 CmsUiProvider uiProvider
= findUiProvider(node
);
354 layer
.view(uiProvider
, ui
.getCurrentWorkArea(), node
);
355 } else if (isTopic(event
, SuiteEvent
.openNewPart
)) {
356 String nodeId
= get(event
, SuiteEvent
.NODE_ID
);
357 String workspace
= get(event
, SuiteEvent
.WORKSPACE
);
358 Node node
= Jcr
.getNodeById(ui
.getSession(workspace
), nodeId
);
359 CmsUiProvider uiProvider
= findUiProvider(node
);
360 layer
.open(uiProvider
, ui
.getCurrentWorkArea(), node
);
361 } else if (isTopic(event
, SuiteEvent
.switchLayer
)) {
362 String layerId
= get(event
, SuiteEvent
.LAYER
);
363 ui
.switchToLayer(layerId
, Jcr
.getRootNode(ui
.getSession(null)));
365 } catch (Exception e
) {
366 log
.error("Cannot handle event " + event
, e
);
367 // CmsView.getCmsView(ui).exception(e);
372 private SuiteUi
getRelatedUi(Event event
) {
373 return managedUis
.get(get(event
, CMS_VIEW_UID_PROPERTY
));
376 private static boolean isTopic(Event event
, CmsEvent cmsEvent
) {
377 return event
.getTopic().equals(cmsEvent
.topic());
380 private static String
get(Event event
, String key
) {
381 Object value
= event
.getProperty(key
);
383 throw new IllegalArgumentException("Property " + key
+ " must be set");
384 return value
.toString();