Make Suite App more configurable.
[gpl/argeo-suite.git] / org.argeo.suite.ui / src / org / argeo / suite / ui / SuiteApp.java
index db8a8dc17e0d589d01d2ae0de04580bfe0e7744d..1c7398f31a5e9986927a402efccf92ed6b3804e0 100644 (file)
@@ -6,6 +6,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
@@ -22,6 +23,7 @@ import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.api.NodeUtils;
 import org.argeo.cms.CmsUserManager;
+import org.argeo.cms.LocaleUtils;
 import org.argeo.cms.auth.CmsSession;
 import org.argeo.cms.ui.AbstractCmsApp;
 import org.argeo.cms.ui.CmsTheme;
@@ -30,6 +32,7 @@ import org.argeo.cms.ui.CmsView;
 import org.argeo.cms.ui.dialogs.CmsFeedback;
 import org.argeo.cms.ui.util.CmsEvent;
 import org.argeo.cms.ui.util.CmsUiUtils;
+import org.argeo.eclipse.ui.specific.UiContext;
 import org.argeo.entity.EntityConstants;
 import org.argeo.entity.EntityNames;
 import org.argeo.entity.EntityType;
@@ -48,15 +51,21 @@ import org.osgi.service.useradmin.User;
 public class SuiteApp extends AbstractCmsApp implements EventHandler {
        private final static Log log = LogFactory.getLog(SuiteApp.class);
 
-       public final static String PID_PREFIX = "argeo.suite.ui.";
-       public final static String HEADER_PID = PID_PREFIX + "header";
-       public final static String LEAD_PANE_PID = PID_PREFIX + "leadPane";
-       public final static String LOGIN_SCREEN_PID = PID_PREFIX + "loginScreen";
-       public final static String DASHBOARD_PID = PID_PREFIX + "dashboard";
-       public final static String RECENT_ITEMS_PID = PID_PREFIX + "recentItems";
+       public final static String PUBLIC_BASE_PATH_PROPERTY = "publicBasePath";
+       public final static String DEFAULT_UI_NAME_PROPERTY = "defaultUiName";
+       public final static String DEFAULT_THEME_ID_PROPERTY = "defaultThemeId";
 
-       private final static String DEFAULT_UI_NAME = "app";
-       private final static String DEFAULT_THEME_ID = "org.argeo.suite.theme.default";
+       private String publicBasePath = null;
+
+       private String pidPrefix;
+       private String headerPid;
+       private String leadPanePid;
+       private String loginScreenPid;
+//     private String DASHBOARD_PID = pidPrefix + "dashboard";
+//     private String RECENT_ITEMS_PID = pidPrefix + "recentItems";
+
+       private String defaultUiName = "app";
+       private String defaultThemeId = "org.argeo.suite.theme.default";
 
        private Map<String, RankedObject<CmsUiProvider>> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>());
        private Map<String, RankedObject<CmsUiProvider>> uiProvidersByType = Collections.synchronizedMap(new HashMap<>());
@@ -70,12 +79,32 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
 
 //     private CmsUiProvider headerPart = null;
 
-       public void init(Map<String, String> properties) {
+       public void init(Map<String, Object> properties) {
                if (log.isDebugEnabled())
                        log.info("Argeo Suite App started");
+
+               if (properties.containsKey(DEFAULT_UI_NAME_PROPERTY))
+                       defaultUiName = LangUtils.get(properties, DEFAULT_UI_NAME_PROPERTY);
+               if (properties.containsKey(DEFAULT_THEME_ID_PROPERTY))
+                       defaultThemeId = LangUtils.get(properties, DEFAULT_THEME_ID_PROPERTY);
+               publicBasePath = LangUtils.get(properties, PUBLIC_BASE_PATH_PROPERTY);
+
+               if (properties.containsKey(Constants.SERVICE_PID)) {
+                       String servicePid = properties.get(Constants.SERVICE_PID).toString();
+                       if (servicePid.endsWith(".app")) {
+                               pidPrefix = servicePid.substring(0, servicePid.length() - "app".length());
+                       }
+               }
+
+               if (pidPrefix == null)
+                       throw new IllegalArgumentException("PID prefix must be set.");
+
+               headerPid = pidPrefix + "header";
+               leadPanePid = pidPrefix + "leadPane";
+               loginScreenPid = pidPrefix + "loginScreen";
        }
 
-       public void destroy(Map<String, String> properties) {
+       public void destroy(Map<String, Object> properties) {
                for (SuiteUi ui : managedUis.values())
                        if (!ui.isDisposed())
                                ui.dispose();
@@ -87,7 +116,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
        @Override
        public Set<String> getUiNames() {
                HashSet<String> uiNames = new HashSet<>();
-               uiNames.add(DEFAULT_UI_NAME);
+               uiNames.add(defaultUiName);
                return uiNames;
        }
 
@@ -114,8 +143,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
 
        @Override
        public String getThemeId(String uiName) {
-               // TODO make it configurable
-               return DEFAULT_THEME_ID;
+               return defaultThemeId;
        }
 
        @Override
@@ -123,35 +151,42 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
                try {
                        Node context = null;
                        SuiteUi ui = (SuiteUi) parent;
-                       refreshPart(findUiProvider(HEADER_PID), ui.getHeader(), context);
                        CmsView cmsView = CmsView.getCmsView(parent);
-                       if (cmsView.isAnonymous()) {
+                       if (cmsView.isAnonymous() && publicBasePath == null) {// internal app, must login
                                ui.logout();
+                               refreshPart(findUiProvider(headerPid), ui.getHeader(), context);
                                ui.refreshBelowHeader(false);
-                               refreshPart(findUiProvider(LOGIN_SCREEN_PID), ui.getBelowHeader(), context);
+                               refreshPart(findUiProvider(loginScreenPid), ui.getBelowHeader(), context);
                                ui.layout(true, true);
                        } else {
+                               CmsSession cmsSession = cmsView.getCmsSession();
                                if (ui.getUserDir() == null) {
-                                       CmsSession cmsSession = cmsView.getCmsSession();
-                                       Session adminSession = null;
-                                       try {
-                                               adminSession = NodeUtils.openDataAdminSession(getRepository(), null);
-                                               Node userDir = SuiteUtils.getOrCreateSessionDir(adminSession, cmsSession);
-                                               ui.initSessions(getRepository(), userDir.getPath());
-                                       } finally {
-                                               Jcr.logout(adminSession);
+                                       if (cmsView.isAnonymous()) {
+                                               assert publicBasePath != null;
+                                               ui.initSessions(getRepository(), publicBasePath);
+                                       } else {
+                                               Session adminSession = null;
+                                               try {
+                                                       adminSession = NodeUtils.openDataAdminSession(getRepository(), null);
+                                                       Node userDir = SuiteUtils.getOrCreateCmsSessionNode(adminSession, cmsSession);
+                                                       ui.initSessions(getRepository(), userDir.getPath());
+                                               } finally {
+                                                       Jcr.logout(adminSession);
+                                               }
                                        }
                                }
+                               initLocale(cmsSession);
                                context = stateToNode(ui, state);
                                if (context == null)
                                        context = ui.getUserDir();
 
+                               refreshPart(findUiProvider(headerPid), ui.getHeader(), context);
                                ui.refreshBelowHeader(true);
                                for (String key : layersByPid.keySet()) {
                                        SuiteLayer layer = layersByPid.get(key).get();
                                        ui.addLayer(key, layer);
                                }
-                               refreshPart(findUiProvider(LEAD_PANE_PID), ui.getLeadPane(), context);
+                               refreshPart(findUiProvider(leadPanePid), ui.getLeadPane(), context);
                                ui.layout(true, true);
                                setState(parent, state);
                        }
@@ -160,6 +195,15 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
                }
        }
 
+       private void initLocale(CmsSession cmsSession) {
+               if (cmsSession == null)
+                       return;
+               Locale locale = cmsSession.getLocale();
+               UiContext.setLocale(locale);
+               LocaleUtils.setThreadLocale(locale);
+
+       }
+
        private void refreshPart(CmsUiProvider uiProvider, Composite part, Node context) {
                CmsUiUtils.clear(part);
                uiProvider.createUiPart(part, context);
@@ -172,6 +216,8 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
        }
 
        private <T> T findByType(Map<String, RankedObject<T>> byType, Node context) {
+               if (context == null)
+                       throw new IllegalArgumentException("A node should be provided");
                try {
                        // mixins
                        Set<String> types = new TreeSet<>();
@@ -224,8 +270,22 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
 
        @Override
        public void setState(Composite parent, String state) {
-               if (state == null || !state.startsWith("/"))
+               if (state == null || state.equals("~"))
+                       return;
+               if (!state.startsWith("/") && !state.equals("~")) {
+                       if (parent instanceof SuiteUi) {
+                               SuiteUi ui = (SuiteUi) parent;
+                               String currentLayerId = ui.getCurrentLayerId();
+                               if (state.equals(currentLayerId))
+                                       return; // does nothing
+                               else {
+                                       Map<String, Object> properties = new HashMap<>();
+                                       properties.put(SuiteEvent.LAYER, state);
+                                       ui.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), properties);
+                               }
+                       }
                        return;
+               }
                SuiteUi suiteUi = (SuiteUi) parent;
                Node node = stateToNode(suiteUi, state);
                if (node == null) {
@@ -234,45 +294,6 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
                        suiteUi.getCmsView().sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node));
                        suiteUi.getCmsView().sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node));
                }
-
-//             CmsView cmsView = CmsView.getCmsView(parent);
-//             if (cmsView.isAnonymous())
-//                     return;
-//             Session session = null;
-//             try {
-//                     if (state != null && state.startsWith("/")) {
-//                             String path = state.substring(1);
-//                             String workspace;
-//                             if (path.equals("")) {
-//                                     workspace = null;
-//                                     path = "/";
-//                             } else {
-//                                     int index = path.indexOf('/');
-//                                     if (index == 0) {
-//                                             log.error("Cannot interpret " + state);
-//                                             cmsView.navigateTo("~");
-//                                             return;
-//                                     } else if (index > 0) {
-//                                             workspace = path.substring(0, index);
-//                                             path = path.substring(index);
-//                                     } else {// index<0, assuming root node
-//                                             workspace = path;
-//                                             path = "/";
-//                                     }
-//                             }
-//                             session = cmsView.doAs(() -> Jcr.login(getRepository(), workspace));
-//
-//                             Node node = session.getNode(path);
-//
-//                             cmsView.sendEvent(SuiteEvent.switchLayer.topic(), SuiteEvent.eventProperties(node));
-//                             cmsView.sendEvent(SuiteEvent.refreshPart.topic(), SuiteEvent.eventProperties(node));
-//                     }
-//             } catch (RepositoryException e) {
-//                     log.error("Cannot load state " + state, e);
-//                     cmsView.navigateTo("~");
-//             } finally {
-//                     JcrUtils.logoutQuietly(session);
-//             }
        }
 
        private String nodeToState(Node node) {
@@ -282,7 +303,7 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
        private Node stateToNode(SuiteUi suiteUi, String state) {
                if (suiteUi == null)
                        return null;
-               if (state == null)
+               if (state == null || !state.startsWith("/"))
                        return null;
 
                String path = state.substring(1);
@@ -304,8 +325,6 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
                                path = "/";
                        }
                }
-//             session = cmsView.doAs(() -> Jcr.login(getRepository(), workspace));
-
                Session session = suiteUi.getSession(workspace);
                if (session == null)
                        return null;
@@ -322,28 +341,40 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler {
 
                // Specific UI related events
                SuiteUi ui = getRelatedUi(event);
+               if (ui == null)
+                       return;
                try {
-                       String currentLayerId = ui.getCurrentLayerId();
-                       SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null;
+//                     String currentLayerId = ui.getCurrentLayerId();
+//                     SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null;
                        if (isTopic(event, SuiteEvent.refreshPart)) {
                                Node node = getNode(ui, event);
+                               if (node == null)
+                                       return;
                                CmsUiProvider uiProvider = findByType(uiProvidersByType, node);
-                               currentLayer.view(uiProvider, ui.getCurrentWorkArea(), node);
+                               SuiteLayer layer = findByType(layersByType, node);
+                               ui.switchToLayer(layer, node);
+                               ui.getCmsView().runAs(() -> layer.view(uiProvider, ui.getCurrentWorkArea(), node));
                                ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node));
                        } else if (isTopic(event, SuiteEvent.openNewPart)) {
                                Node node = getNode(ui, event);
+                               if (node == null)
+                                       return;
                                CmsUiProvider uiProvider = findByType(uiProvidersByType, node);
-                               currentLayer.open(uiProvider, ui.getCurrentWorkArea(), node);
+                               SuiteLayer layer = findByType(layersByType, node);
+                               ui.switchToLayer(layer, node);
+                               ui.getCmsView().runAs(() -> layer.open(uiProvider, ui.getCurrentWorkArea(), node));
                                ui.getCmsView().stateChanged(nodeToState(node), Jcr.getTitle(node));
                        } else if (isTopic(event, SuiteEvent.switchLayer)) {
                                String layerId = get(event, SuiteEvent.LAYER);
                                if (layerId != null) {
-                                       ui.switchToLayer(layerId, Jcr.getRootNode(ui.getSession(null)));
+//                                     ui.switchToLayer(layerId, ui.getUserDir());
+                                       ui.getCmsView().runAs(() -> ui.switchToLayer(layerId, ui.getUserDir()));
+                                       ui.getCmsView().navigateTo(layerId);
                                } else {
                                        Node node = getNode(ui, event);
                                        if (node != null) {
                                                SuiteLayer layer = findByType(layersByType, node);
-                                               ui.switchToLayer(layer, node);
+                                               ui.getCmsView().runAs(() -> ui.switchToLayer(layer, node));
                                        }
                                }
                        }