X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=blobdiff_plain;f=org.argeo.suite.ui%2Fsrc%2Forg%2Fargeo%2Fsuite%2Fui%2FSuiteApp.java;h=e363a62ff23d0b7ec325f5093a18701a61d2fbf9;hp=44e7d3db4678abe9360949f9305ea1b54dd7919d;hb=9cd258d2c3de54e128c780adb991ecec7e6b2b9c;hpb=f21589b7f2a19a79edcc213b867c47130faa76cd diff --git a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java index 44e7d3d..e363a62 100644 --- a/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java +++ b/org.argeo.suite.ui/src/org/argeo/suite/ui/SuiteApp.java @@ -5,6 +5,7 @@ import static org.argeo.cms.ui.CmsView.CMS_VIEW_UID_PROPERTY; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; @@ -14,10 +15,14 @@ import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.nodetype.NodeType; +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; 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.auth.CmsSession; import org.argeo.cms.ui.AbstractCmsApp; import org.argeo.cms.ui.CmsTheme; import org.argeo.cms.ui.CmsUiProvider; @@ -26,14 +31,18 @@ import org.argeo.cms.ui.dialogs.CmsFeedback; import org.argeo.cms.ui.util.CmsEvent; import org.argeo.cms.ui.util.CmsUiUtils; import org.argeo.entity.EntityConstants; +import org.argeo.entity.EntityNames; +import org.argeo.entity.EntityType; import org.argeo.jcr.Jcr; -import org.argeo.jcr.JcrUtils; import org.argeo.suite.RankedObject; +import org.argeo.suite.SuiteUtils; +import org.argeo.util.LangUtils; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.osgi.framework.Constants; import org.osgi.service.event.Event; import org.osgi.service.event.EventHandler; +import org.osgi.service.useradmin.User; /** The Argeo Suite App. */ public class SuiteApp extends AbstractCmsApp implements EventHandler { @@ -43,7 +52,6 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { 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_LAYER_PID = PID_PREFIX + "dashboardLayer"; public final static String DASHBOARD_PID = PID_PREFIX + "dashboard"; public final static String RECENT_ITEMS_PID = PID_PREFIX + "recentItems"; @@ -52,7 +60,10 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { private Map> uiProvidersByPid = Collections.synchronizedMap(new HashMap<>()); private Map> uiProvidersByType = Collections.synchronizedMap(new HashMap<>()); - private Map> layers = Collections.synchronizedSortedMap(new TreeMap<>()); + private Map> layersByPid = Collections.synchronizedSortedMap(new TreeMap<>()); + private Map> layersByType = Collections.synchronizedSortedMap(new TreeMap<>()); + + private CmsUserManager cmsUserManager; // TODO make more optimal or via CmsSession/CmsView private Map managedUis = new HashMap<>(); @@ -115,35 +126,35 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { refreshPart(findUiProvider(HEADER_PID), ui.getHeader(), context); CmsView cmsView = CmsView.getCmsView(parent); if (cmsView.isAnonymous()) { + ui.logout(); ui.refreshBelowHeader(false); refreshPart(findUiProvider(LOGIN_SCREEN_PID), ui.getBelowHeader(), context); + ui.layout(true, true); } else { - try { - if (ui.getUserHome() == null) - ui.initSessions(getRepository()); - context = ui.getUserHome(); - - } catch (RepositoryException e) { - e.printStackTrace(); + 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); + } } - ui.refreshBelowHeader(true); + context = stateToNode(ui, state); + if (context == null) + context = ui.getUserDir(); - for (String key : layers.keySet()) { - SuiteLayer layer = layers.get(key).get(); + ui.refreshBelowHeader(true); + for (String key : layersByPid.keySet()) { + SuiteLayer layer = layersByPid.get(key).get(); ui.addLayer(key, layer); } - -// ui.addLayer(ArgeoSuiteUi.DASHBOARD_LAYER); -// ui.addLayer("documents"); -// ui.addLayer("locations"); -// ui.addLayer("people"); - ui.switchToLayer(DASHBOARD_LAYER_PID, context); - -// refreshPart(findUiProvider(DASHBOARD_PID), ui.getTabbedArea().getCurrent(), context); refreshPart(findUiProvider(LEAD_PANE_PID), ui.getLeadPane(), context); -// refreshPart(findUiProvider(RECENT_ITEMS_PID), ui.getEntryArea(), context); + ui.layout(true, true); + setState(parent, state); } - ui.layout(true, true); } catch (Exception e) { CmsFeedback.show("Unexpected exception", e); } @@ -160,121 +171,247 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { return uiProvidersByPid.get(pid).get(); } - private CmsUiProvider findUiProvider(Node context) { + private T findByType(Map> byType, Node context) { try { + // mixins Set types = new TreeSet<>(); for (NodeType nodeType : context.getMixinNodeTypes()) { String typeName = nodeType.getName(); - if (uiProvidersByType.containsKey(typeName)) { + if (byType.containsKey(typeName)) { types.add(typeName); } } - NodeType nodeType = context.getPrimaryNodeType(); - String typeName = nodeType.getName(); - if (uiProvidersByType.containsKey(typeName)) { - types.add(typeName); + // primary node type + { + NodeType nodeType = context.getPrimaryNodeType(); + String typeName = nodeType.getName(); + if (byType.containsKey(typeName)) { + types.add(typeName); + } + for (NodeType mixin : nodeType.getDeclaredSupertypes()) { + if (byType.containsKey(mixin.getName())) { + types.add(mixin.getName()); + } + } } + // entity type + if (context.isNodeType(EntityType.entity.get())) { + if (context.hasProperty(EntityNames.ENTITY_TYPE)) { + String typeName = context.getProperty(EntityNames.ENTITY_TYPE).getString(); + if (byType.containsKey(typeName)) { + types.add(typeName); + } + } + } + // if (context.getPath().equals("/")) {// root node // types.add("nt:folder"); // } - if (NodeUtils.isUserHome(context)) {// home node + if (NodeUtils.isUserHome(context) && byType.containsKey("nt:folder")) {// home node types.add("nt:folder"); } if (types.size() == 0) - throw new IllegalArgumentException("No UI provider found for " + context); - return uiProvidersByType.get(types.iterator().next()).get(); + throw new IllegalArgumentException("No type found for " + context); + String type = types.iterator().next(); + if (!byType.containsKey(type)) + throw new IllegalArgumentException("No component found for " + context + " with type " + type); + return byType.get(type).get(); } catch (RepositoryException e) { throw new IllegalStateException(e); } } -// private CmsUiProvider findUiProvider(String pid, Node context) { -// CmsUiProvider found = null; -// if (pid != null) { -// SortedMap subMap = uiProvidersByPid.subMap(RankingKey.minPid(pid), -// RankingKey.maxPid(pid)); -// providers: for (RankingKey key : subMap.keySet()) { -// if (key.getPid() == null || !key.getPid().equals(pid)) -// break providers; -// found = subMap.get(key); -// } -// if (found != null) -// return found; -// } -// -// if (found == null && context != null) { -// SortedMap subMap = null; -// String dataType = null; -// if (Jcr.isNodeType(context, EntityTypes.ENTITY_ENTITY)) { -// dataType = Jcr.get(context, EntityNames.ENTITY_TYPE); -// subMap = uiProvidersByPid.subMap(RankingKey.minDataType(dataType), RankingKey.maxDataType(dataType)); -// } -// providers: for (RankingKey key : subMap.keySet()) { -// if (key.getDataType() == null || !key.getDataType().equals(dataType)) -// break providers; -// found = subMap.get(key); -// } -// if (found == null) -// found = uiProvidersByPid.get(new RankingKey(null, null, null, dataType, null)); -// if (found != null) -// return found; -// } + + @Override + public void setState(Composite parent, String state) { + if (state == null || !state.startsWith("/")) + return; + SuiteUi suiteUi = (SuiteUi) parent; + Node node = stateToNode(suiteUi, state); + if (node == null) { + suiteUi.getCmsView().navigateTo("~"); + } else { + 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)); // -// // nothing -// if (log.isWarnEnabled()) -// log.warn("No UI provider found for" + (pid != null ? " pid " + pid : "") -// + (context != null ? " " + context : "")); -// return new CmsUiProvider() { +// Node node = session.getNode(path); // -// @Override -// public Control createUi(Composite parent, Node context) throws RepositoryException { -// return parent; +// 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) { + return '/' + Jcr.getWorkspaceName(node) + Jcr.getPath(node); + } + + private Node stateToNode(SuiteUi suiteUi, String state) { + if (suiteUi == null) + return null; + if (state == null) + return null; + + 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 null; + } 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)); + + Session session = suiteUi.getSession(workspace); + if (session == null) + return null; + Node node = Jcr.getNode(session, path); + return node; + } + + /* + * Events management + */ @Override - public void setState(Composite parent, String state) { - CmsView cmsView = CmsView.getCmsView(parent); - // for the time being we systematically open a session, in order to make sure - // that home is initialised - Session session = null; + public void handleEvent(Event event) { + + // Specific UI related events + SuiteUi ui = getRelatedUi(event); try { - if (state != null && state.startsWith("/")) { - String path = state.substring(1); - String workspace; - if (path.equals("")) { - workspace = null; - path = "/"; +// String currentLayerId = ui.getCurrentLayerId(); +// SuiteLayer currentLayer = currentLayerId != null ? layersByPid.get(currentLayerId).get() : null; + if (isTopic(event, SuiteEvent.refreshPart)) { + Node node = getNode(ui, event); + CmsUiProvider uiProvider = findByType(uiProvidersByType, node); + SuiteLayer layer = findByType(layersByType, node); + ui.switchToLayer(layer, node); + 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); + CmsUiProvider uiProvider = findByType(uiProvidersByType, node); + SuiteLayer layer = findByType(layersByType, node); + ui.switchToLayer(layer, node); + 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.getCmsView().navigateTo("~"); } 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 = "/"; + Node node = getNode(ui, event); + if (node != null) { + SuiteLayer layer = findByType(layersByType, node); + ui.switchToLayer(layer, node); } } - session = getRepository().login(workspace); + } + } catch (Exception e) { + log.error("Cannot handle event " + event, e); +// CmsView.getCmsView(ui).exception(e); + } - Node node = session.getNode(path); + } - refreshEntityUi(null, node); + private Node getNode(SuiteUi ui, Event event) { + String nodePath = get(event, SuiteEvent.NODE_PATH); + String workspaceName = get(event, SuiteEvent.WORKSPACE); + Session session = ui.getSession(workspaceName); + Node node; + if (nodePath == null) { + // look for a user + String username = get(event, SuiteEvent.USERNAME); + if (username == null) + return null; + User user = cmsUserManager.getUser(username); + if (user == null) + return null; + LdapName userDn; + try { + userDn = new LdapName(user.getName()); + } catch (InvalidNameException e) { + throw new IllegalArgumentException("Badly formatted username", e); } - } catch (RepositoryException e) { - log.error("Cannot load state " + state, e); - cmsView.navigateTo("~"); - } finally { - JcrUtils.logoutQuietly(session); + String userNodePath = SuiteUtils.getUserNodePath(userDn); + if (Jcr.itemExists(session, userNodePath)) + node = Jcr.getNode(session, userNodePath); + else { + Session adminSession = null; + try { + adminSession = NodeUtils.openDataAdminSession(getRepository(), workspaceName); + SuiteUtils.getOrCreateUserNode(adminSession, userDn); + } finally { + Jcr.logout(adminSession); + } + node = Jcr.getNode(session, userNodePath); + } + } else { + node = Jcr.getNode(session, nodePath); } + return node; } - private void refreshEntityUi(Composite parent, Node context) { + private SuiteUi getRelatedUi(Event event) { + return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY)); + } + + private static boolean isTopic(Event event, CmsEvent cmsEvent) { + return event.getTopic().equals(cmsEvent.topic()); + } + + private static String get(Event event, String key) { + Object value = event.getProperty(key); + if (value == null) + return null; +// throw new IllegalArgumentException("Property " + key + " must be set"); + return value.toString(); + } /* @@ -287,9 +424,9 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { RankedObject.putIfHigherRank(uiProvidersByPid, pid, uiProvider, properties); } if (properties.containsKey(EntityConstants.TYPE)) { - // TODO manage String arrays as well - String type = (String) properties.get(EntityConstants.TYPE); - RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties); + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) + RankedObject.putIfHigherRank(uiProvidersByType, type, uiProvider, properties); } } @@ -302,70 +439,53 @@ public class SuiteApp extends AbstractCmsApp implements EventHandler { } } } - + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) { + if (uiProvidersByType.containsKey(type)) { + if (uiProvidersByType.get(type).equals(new RankedObject(uiProvider, properties))) { + uiProvidersByType.remove(type); + } + } + } + } } public void addLayer(SuiteLayer layer, Map properties) { if (properties.containsKey(Constants.SERVICE_PID)) { String pid = (String) properties.get(Constants.SERVICE_PID); - RankedObject.putIfHigherRank(layers, pid, layer, properties); + RankedObject.putIfHigherRank(layersByPid, pid, layer, properties); + } + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) + RankedObject.putIfHigherRank(layersByType, type, layer, properties); } } public void removeLayer(SuiteLayer layer, Map properties) { if (properties.containsKey(Constants.SERVICE_PID)) { String pid = (String) properties.get(Constants.SERVICE_PID); - if (layers.containsKey(pid)) { - if (layers.get(pid).equals(new RankedObject(layer, properties))) { - layers.remove(pid); + if (layersByPid.containsKey(pid)) { + if (layersByPid.get(pid).equals(new RankedObject(layer, properties))) { + layersByPid.remove(pid); } } } - } - - @Override - public void handleEvent(Event event) { - - // Specific UI related events - SuiteUi ui = getRelatedUi(event); - String currentLayerId = ui.getCurrentLayerId(); - SuiteLayer layer = layers.get(currentLayerId).get(); - if (isTopic(event, SuiteEvent.refreshPart)) { - String nodeId = get(event, SuiteEvent.NODE_ID); - String workspace = get(event, SuiteEvent.WORKSPACE); - Node node = Jcr.getNodeById(ui.getSession(workspace), nodeId); - CmsUiProvider uiProvider = findUiProvider(node); - layer.view(uiProvider, ui.getCurrentWorkArea(), node); - // ui.getTabbedArea().view(findUiProvider(DASHBOARD_PID), node); -// ui.layout(true, true); - } else if (isTopic(event, SuiteEvent.openNewPart)) { - String nodeId = get(event, SuiteEvent.NODE_ID); - String workspace = get(event, SuiteEvent.WORKSPACE); - Node node = Jcr.getNodeById(ui.getSession(workspace), nodeId); - CmsUiProvider uiProvider = findUiProvider(node); - layer.open(uiProvider, ui.getCurrentWorkArea(), node); -// ui.getTabbedArea().open(findUiProvider(DASHBOARD_PID), node); -// ui.layout(true, true); - } else if (isTopic(event, SuiteEvent.switchLayer)) { - String layerId = get(event, SuiteEvent.LAYER); - ui.switchToLayer(layerId, null); + if (properties.containsKey(EntityConstants.TYPE)) { + List types = LangUtils.toStringList(properties.get(EntityConstants.TYPE)); + for (String type : types) { + if (layersByType.containsKey(type)) { + if (layersByType.get(type).equals(new RankedObject(layer, properties))) { + layersByType.remove(type); + } + } + } } - } - private SuiteUi getRelatedUi(Event event) { - return managedUis.get(get(event, CMS_VIEW_UID_PROPERTY)); - } - - private static boolean isTopic(Event event, CmsEvent cmsEvent) { - return event.getTopic().equals(cmsEvent.topic()); + public void setCmsUserManager(CmsUserManager cmsUserManager) { + this.cmsUserManager = cmsUserManager; } - private static String get(Event event, String key) { - Object value = event.getProperty(key); - if (value == null) - throw new IllegalArgumentException("Property " + key + " must be set"); - return value.toString(); - - } }