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
.SortedMap
;
11 import java
.util
.TreeMap
;
13 import javax
.jcr
.Node
;
14 import javax
.jcr
.RepositoryException
;
15 import javax
.jcr
.Session
;
17 import org
.apache
.commons
.logging
.Log
;
18 import org
.apache
.commons
.logging
.LogFactory
;
19 import org
.argeo
.cms
.ui
.AbstractCmsApp
;
20 import org
.argeo
.cms
.ui
.CmsTheme
;
21 import org
.argeo
.cms
.ui
.CmsUiProvider
;
22 import org
.argeo
.cms
.ui
.CmsView
;
23 import org
.argeo
.cms
.ui
.dialogs
.CmsFeedback
;
24 import org
.argeo
.cms
.ui
.util
.CmsEvent
;
25 import org
.argeo
.cms
.ui
.util
.CmsUiUtils
;
26 import org
.argeo
.entity
.EntityNames
;
27 import org
.argeo
.entity
.EntityTypes
;
28 import org
.argeo
.jcr
.Jcr
;
29 import org
.argeo
.jcr
.JcrUtils
;
30 import org
.argeo
.suite
.RankingKey
;
31 import org
.eclipse
.swt
.SWT
;
32 import org
.eclipse
.swt
.widgets
.Composite
;
33 import org
.eclipse
.swt
.widgets
.Control
;
34 import org
.osgi
.service
.event
.Event
;
35 import org
.osgi
.service
.event
.EventHandler
;
37 /** The Argeo Suite App. */
38 public class ArgeoSuiteApp
extends AbstractCmsApp
implements EventHandler
{
39 private final static Log log
= LogFactory
.getLog(ArgeoSuiteApp
.class);
41 public final static String PID_PREFIX
= "argeo.suite.ui.";
42 public final static String HEADER_PID
= PID_PREFIX
+ "header";
43 public final static String LEAD_PANE_PID
= PID_PREFIX
+ "leadPane";
44 public final static String LOGIN_SCREEN_PID
= PID_PREFIX
+ "loginScreen";
45 public final static String DASHBOARD_PID
= PID_PREFIX
+ "dashboard";
46 public final static String RECENT_ITEMS_PID
= PID_PREFIX
+ "recentItems";
48 private final static String DEFAULT_UI_NAME
= "app";
49 private final static String DEFAULT_THEME_ID
= "org.argeo.suite.theme.default";
51 private SortedMap
<RankingKey
, CmsUiProvider
> uiProviders
= Collections
.synchronizedSortedMap(new TreeMap
<>());
53 // TODO make more optimal or via CmsSession/CmsView
54 private Map
<String
, ArgeoSuiteUi
> managedUis
= new HashMap
<>();
56 // private CmsUiProvider headerPart = null;
58 public void init(Map
<String
, String
> properties
) {
59 if (log
.isDebugEnabled())
60 log
.info("Argeo Suite App started");
63 public void destroy(Map
<String
, String
> properties
) {
64 for (ArgeoSuiteUi ui
: managedUis
.values())
67 if (log
.isDebugEnabled())
68 log
.info("Argeo Suite App stopped");
73 public Set
<String
> getUiNames() {
74 HashSet
<String
> uiNames
= new HashSet
<>();
75 uiNames
.add(DEFAULT_UI_NAME
);
80 public Composite
initUi(Composite parent
) {
81 String uiName
= parent
.getData(UI_NAME_PROPERTY
) != null ? parent
.getData(UI_NAME_PROPERTY
).toString() : null;
82 CmsView cmsView
= CmsView
.getCmsView(parent
);
84 throw new IllegalStateException("No CMS view is registered.");
85 CmsTheme theme
= getTheme(uiName
);
87 CmsTheme
.registerCmsTheme(parent
.getShell(), theme
);
88 ArgeoSuiteUi argeoSuiteUi
= new ArgeoSuiteUi(parent
, SWT
.NONE
);
89 String uid
= cmsView
.getUid();
90 managedUis
.put(uid
, argeoSuiteUi
);
91 argeoSuiteUi
.addDisposeListener((e
) -> {
92 managedUis
.remove(uid
);
93 if (log
.isDebugEnabled())
94 log
.debug("Suite UI " + uid
+ " has been disposed.");
96 refreshUi(argeoSuiteUi
, null);
101 public String
getThemeId(String uiName
) {
102 // TODO make it configurable
103 return DEFAULT_THEME_ID
;
107 public void refreshUi(Composite parent
, String state
) {
110 ArgeoSuiteUi ui
= (ArgeoSuiteUi
) parent
;
111 refreshPart(findUiProvider(HEADER_PID
, context
), ui
.getHeader(), context
);
112 CmsView cmsView
= CmsView
.getCmsView(parent
);
113 if (cmsView
.isAnonymous()) {
114 ui
.refreshBelowHeader(false);
115 refreshPart(findUiProvider(LOGIN_SCREEN_PID
, context
), ui
.getBelowHeader(), context
);
118 if (ui
.getSession() == null)
119 ui
.setSession(getRepository().login());
120 context
= ui
.getSession().getRootNode();
122 } catch (RepositoryException e
) {
125 ui
.refreshBelowHeader(true);
127 ui
.addLayer(ArgeoSuiteUi
.DASHBOARD_LAYER
);
128 ui
.addLayer("documents");
129 ui
.addLayer("locations");
130 ui
.addLayer("people");
131 ui
.switchToLayer(ArgeoSuiteUi
.DASHBOARD_LAYER
);
133 refreshPart(findUiProvider(DASHBOARD_PID
, context
), ui
.getTabbedArea().getCurrent(), context
);
134 refreshPart(findUiProvider(LEAD_PANE_PID
, context
), ui
.getLeadPane(), context
);
135 refreshPart(findUiProvider(RECENT_ITEMS_PID
, context
), ui
.getEntryArea(), context
);
137 ui
.layout(true, true);
138 } catch (Exception e
) {
139 CmsFeedback
.show("Unexpected exception", e
);
143 private void refreshPart(CmsUiProvider uiProvider
, Composite part
, Node context
) {
144 CmsUiUtils
.clear(part
);
145 uiProvider
.createUiPart(part
, context
);
148 private CmsUiProvider
findUiProvider(String pid
, Node context
) {
149 CmsUiProvider found
= null;
151 SortedMap
<RankingKey
, CmsUiProvider
> subMap
= uiProviders
.subMap(RankingKey
.minPid(pid
),
152 RankingKey
.maxPid(pid
));
153 providers
: for (RankingKey key
: subMap
.keySet()) {
154 if (key
.getPid() == null || !key
.getPid().equals(pid
))
156 found
= subMap
.get(key
);
162 if (found
== null && context
!= null) {
163 SortedMap
<RankingKey
, CmsUiProvider
> subMap
= null;
164 String dataType
= null;
165 if (Jcr
.isNodeType(context
, EntityTypes
.ENTITY_ENTITY
)) {
166 dataType
= Jcr
.get(context
, EntityNames
.ENTITY_TYPE
);
167 subMap
= uiProviders
.subMap(RankingKey
.minDataType(dataType
), RankingKey
.maxDataType(dataType
));
169 providers
: for (RankingKey key
: subMap
.keySet()) {
170 if (key
.getDataType() == null || !key
.getDataType().equals(dataType
))
172 found
= subMap
.get(key
);
175 found
= uiProviders
.get(new RankingKey(null, null, null, dataType
, null));
181 if (log
.isWarnEnabled())
182 log
.warn("No UI provider found for" + (pid
!= null ?
" pid " + pid
: "")
183 + (context
!= null ?
" " + context
: ""));
184 return new CmsUiProvider() {
187 public Control
createUi(Composite parent
, Node context
) throws RepositoryException
{
194 public void setState(Composite parent
, String state
) {
195 CmsView cmsView
= CmsView
.getCmsView(parent
);
196 // for the time being we systematically open a session, in order to make sure
197 // that home is initialised
198 Session session
= null;
200 if (state
!= null && state
.startsWith("/")) {
201 String path
= state
.substring(1);
203 if (path
.equals("")) {
207 int index
= path
.indexOf('/');
209 log
.error("Cannot interpret // " + state
);
210 cmsView
.navigateTo("~");
212 } else if (index
> 0) {
213 workspace
= path
.substring(0, index
);
214 path
= path
.substring(index
);
215 } else {// index<0, assuming root node
220 session
= getRepository().login(workspace
);
222 Node node
= session
.getNode(path
);
224 refreshEntityUi(null, node
);
226 } catch (RepositoryException e
) {
227 log
.error("Cannot load state " + state
, e
);
228 cmsView
.navigateTo("~");
230 JcrUtils
.logoutQuietly(session
);
234 private void refreshEntityUi(Composite parent
, Node context
) {
238 * Dependency injection.
241 public void addUiProvider(CmsUiProvider uiProvider
, Map
<String
, Object
> properties
) {
242 RankingKey partKey
= new RankingKey(properties
);
243 // String servicePid = properties.get(Constants.SERVICE_PID);
244 // if (servicePid == null) {
245 // log.error("No service pid found for " + uiProvider.getClass() + ", " + properties);
247 if (partKey
.getPid() != null || partKey
.getDataType() != null) {
248 uiProviders
.put(partKey
, uiProvider
);
249 if (log
.isDebugEnabled())
250 log
.debug("Added UI provider " + partKey
+ " (" + uiProvider
.getClass().getName() + ") to CMS app.");
256 public void removeUiProvider(CmsUiProvider uiProvider
, Map
<String
, Object
> properties
) {
257 RankingKey partKey
= new RankingKey(properties
);
258 // String servicePid = properties.get(Constants.SERVICE_PID);
259 uiProviders
.remove(partKey
);
264 public void handleEvent(Event event
) {
266 // Specific UI related events
267 ArgeoSuiteUi ui
= getRelatedUi(event
);
268 if (isTopic(event
, SuiteEvent
.refreshPart
)) {
269 Node node
= Jcr
.getNodeById(ui
.getSession(), get(event
, SuiteEvent
.NODE_ID
));
270 ui
.getTabbedArea().view(findUiProvider(DASHBOARD_PID
, node
), node
);
271 // ui.layout(true, true);
272 } else if (isTopic(event
, SuiteEvent
.openNewPart
)) {
273 Node node
= Jcr
.getNodeById(ui
.getSession(), get(event
, SuiteEvent
.NODE_ID
));
274 ui
.getTabbedArea().open(findUiProvider(DASHBOARD_PID
, node
), node
);
275 // ui.layout(true, true);
276 } else if (isTopic(event
, SuiteEvent
.switchLayer
)) {
277 String layer
= get(event
, SuiteEvent
.LAYER
);
278 ui
.switchToLayer(layer
);
283 private ArgeoSuiteUi
getRelatedUi(Event event
) {
284 return managedUis
.get(get(event
, CMS_VIEW_UID_PROPERTY
));
287 private static boolean isTopic(Event event
, CmsEvent cmsEvent
) {
288 return event
.getTopic().equals(cmsEvent
.topic());
291 private static String
get(Event event
, String key
) {
292 Object value
= event
.getProperty(key
);
294 throw new IllegalArgumentException("Property " + key
+ " must be set");
295 return value
.toString();