From: Bruno Sinou Date: Thu, 7 Nov 2013 16:04:20 +0000 (+0000) Subject: work on a first draft of the AKB UI X-Git-Tag: argeo-slc-2.1.7~294 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=c5a5cb9a47fdafcc95f1b8902f31b62a0e6a9674;p=gpl%2Fargeo-slc.git work on a first draft of the AKB UI git-svn-id: https://svn.argeo.org/slc/trunk@6595 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml b/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml index 22c33a6e8..fc42e1386 100644 --- a/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml +++ b/modules/org.argeo.slc.akb.services/META-INF/spring/services.xml @@ -5,10 +5,10 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - + + + diff --git a/plugins/org.argeo.slc.akb.ui/META-INF/spring/commands.xml b/plugins/org.argeo.slc.akb.ui/META-INF/spring/commands.xml index 3b2e6ccb0..43e7e4b39 100644 --- a/plugins/org.argeo.slc.akb.ui/META-INF/spring/commands.xml +++ b/plugins/org.argeo.slc.akb.ui/META-INF/spring/commands.xml @@ -4,4 +4,9 @@ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> + + + + diff --git a/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml b/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml index 7809cbfad..25b421588 100644 --- a/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml +++ b/plugins/org.argeo.slc.akb.ui/META-INF/spring/editors.xml @@ -3,5 +3,12 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + + + + + + \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/META-INF/spring/views.xml b/plugins/org.argeo.slc.akb.ui/META-INF/spring/views.xml index f592db19b..8b2565f84 100644 --- a/plugins/org.argeo.slc.akb.ui/META-INF/spring/views.xml +++ b/plugins/org.argeo.slc.akb.ui/META-INF/spring/views.xml @@ -10,4 +10,8 @@ scope="prototype"> + + + diff --git a/plugins/org.argeo.slc.akb.ui/plugin.xml b/plugins/org.argeo.slc.akb.ui/plugin.xml index 891619d21..bdf9dfeee 100644 --- a/plugins/org.argeo.slc.akb.ui/plugin.xml +++ b/plugins/org.argeo.slc.akb.ui/plugin.xml @@ -27,16 +27,52 @@ name="Search" restorable="true"> + + + + + + + + + + + + + + + - diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/AkbEnvPerspective.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/AkbEnvPerspective.java index abd7f90ca..cfd6d3571 100644 --- a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/AkbEnvPerspective.java +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/AkbEnvPerspective.java @@ -1,6 +1,7 @@ package org.argeo.slc.akb.ui; import org.argeo.slc.akb.ui.views.AkbDefaultView; +import org.argeo.slc.akb.ui.views.AkbTemplatesTreeView; import org.eclipse.ui.IFolderLayout; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveFactory; @@ -16,6 +17,7 @@ public class AkbEnvPerspective implements IPerspectiveFactory { IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.3f, editorArea); + left.addView(AkbTemplatesTreeView.ID); left.addView(AkbDefaultView.ID); } } diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/commands/OpenAkbNodeEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/commands/OpenAkbNodeEditor.java new file mode 100644 index 000000000..c02f118b6 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/commands/OpenAkbNodeEditor.java @@ -0,0 +1,109 @@ +package org.argeo.slc.akb.ui.commands; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.akb.AkbException; +import org.argeo.slc.akb.AkbTypes; +import org.argeo.slc.akb.ui.AkbUiPlugin; +import org.argeo.slc.akb.ui.editors.AkbConnectorAliasEditor; +import org.argeo.slc.akb.ui.editors.AkbEnvTemplateEditor; +import org.argeo.slc.akb.ui.editors.AkbNodeEditorInput; +import org.eclipse.core.commands.AbstractHandler; +import org.eclipse.core.commands.ExecutionEvent; +import org.eclipse.core.commands.ExecutionException; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.handlers.HandlerUtil; + +/** + * Opens or show an AKB specific node in a single repository / single workspace + * environment given some parameters, namely : + * + */ +public class OpenAkbNodeEditor extends AbstractHandler { + public final static String ID = AkbUiPlugin.PLUGIN_ID + + ".openAkbNodeEditor"; + + /* DEPENDENCY INJECTION */ + private Repository repository; + + public final static String PARAM_NODE_JCR_ID = "param.nodeJcrId"; + public final static String PARAM_NODE_TYPE = "param.nodeType"; + public final static String PARAM_PARENT_NODE_JCR_ID = "param.parentNodeJcrId"; + + public Object execute(ExecutionEvent event) throws ExecutionException { + + String nodeType = event.getParameter(PARAM_NODE_TYPE); + String nodeJcrId = event.getParameter(PARAM_NODE_JCR_ID); + String parentNodeJcrId = event.getParameter(PARAM_PARENT_NODE_JCR_ID); + + Session session = null; + try { + session = repository.login(); + Node node = null; + + if (nodeJcrId == null) + if (parentNodeJcrId == null) + throw new AkbException( + "Define a parent node to create a new node"); + else + node = createNewNode(session, nodeType, parentNodeJcrId); + else + node = session.getNodeByIdentifier(nodeJcrId); + + String editorId = getEditorForNode(node); + + AkbNodeEditorInput eei = new AkbNodeEditorInput( + node.getIdentifier()); + + HandlerUtil.getActiveWorkbenchWindow(event).getActivePage() + .openEditor(eei, editorId); + } catch (PartInitException pie) { + throw new AkbException( + "Unexpected PartInitException while opening akb node editor", + pie); + } catch (RepositoryException e) { + throw new AkbException("unexpected JCR error while opening " + + nodeType + " editor", e); + } finally { + JcrUtils.logoutQuietly(session); + } + return null; + } + + private Node createNewNode(Session session, String nodeType, + String parentNodeJcrId) throws RepositoryException { + Node parentNode = session.getNodeByIdentifier(parentNodeJcrId); + Node node = parentNode.addNode("new", nodeType); + // corresponding node is saved but not checked in, in order to ease + // cancel actions. + session.save(); + return node; + } + + private String getEditorForNode(Node node) throws RepositoryException { + String editorId = null; + + if (node.isNodeType(AkbTypes.AKB_CONNECTOR_ALIAS)) + editorId = AkbConnectorAliasEditor.ID; + else if (node.isNodeType(AkbTypes.AKB_ENV_TEMPLATE)) + editorId = AkbEnvTemplateEditor.ID; + else + throw new AkbException("Editor is undefined for node " + node); + return editorId; + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AbstractAkbNodeEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AbstractAkbNodeEditor.java new file mode 100644 index 000000000..ba2963e63 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AbstractAkbNodeEditor.java @@ -0,0 +1,122 @@ +package org.argeo.slc.akb.ui.editors; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.akb.AkbException; +import org.argeo.slc.akb.ui.AkbUiPlugin; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.part.EditorPart; + +/** + * Parent Abstract Node editor for AKB. Manage life cycle of the JCR session that + * is bound to it. + */ +public abstract class AbstractAkbNodeEditor extends EditorPart { + // private final static Log log = LogFactory + // .getLog(AbstractEntityEditor.class); + + // We use a one session per editor pattern to secure various nodes and + // changes life cycle + private Repository repository; + private Session session; + + // Business Objects + private Node akbNode; + + // LIFE CYCLE + public void init(IEditorSite site, IEditorInput input) + throws PartInitException { + setSite(site); + setInput(input); + try { + session = repository.login(); + AkbNodeEditorInput anei = (AkbNodeEditorInput) getEditorInput(); + akbNode = session.getNodeByIdentifier(anei.getIdentifier()); + + // try to set a default part name + updatePartName(); + + // update tooltip + // String displayName = CommonsJcrUtils.get(getEntity(), + // Property.JCR_TITLE); + + // if (CommonsJcrUtils.isEmptyString(displayName)) + // displayName = "current item"; + // setTitleToolTip("Display and edit information for " + + // displayName); + } catch (RepositoryException e) { + throw new AkbException("Unable open editor for akb node", e); + } + } + + /** + * Overwrite to provide a specific part Name + */ + protected void updatePartName() { + // String name = CommonsJcrUtils.get(entity, Property.JCR_TITLE); + // if (CommonsJcrUtils.checkNotEmptyString(name)) { + // if (name.length() > SHORT_NAME_LENGHT) + // name = name.substring(0, SHORT_NAME_LENGHT - 1) + "..."; + // setPartName(name); + // } + } + + /* EXPOSES TO CHILDREN CLASSES */ + protected Session getSession() { + return session; + } + + @Override + public void dispose() { + try { + // if (cNode != null) + // CommonsJcrUtils.cancelAndCheckin(cNode); + } + + finally { + JcrUtils.logoutQuietly(session); + } + super.dispose(); + } + + @Override + public void doSaveAs() { + // unused compulsory method + } + + @Override + public void doSave(IProgressMonitor monitor) { + throw new AkbException("Implement this"); + } + + @Override + public boolean isDirty() { + try { + return session.hasPendingChanges(); + } catch (Exception e) { + throw new AkbException("Error getting session status.", e); + } + } + + @Override + public boolean isSaveAsAllowed() { + return false; + } + + @Override + public void setFocus() { + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbConnectorAliasEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbConnectorAliasEditor.java new file mode 100644 index 000000000..2ff704c45 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbConnectorAliasEditor.java @@ -0,0 +1,18 @@ +package org.argeo.slc.akb.ui.editors; + +import org.argeo.slc.akb.ui.AkbUiPlugin; +import org.eclipse.swt.widgets.Composite; + +/** + * Display and edit a connector Alias + */ +public class AkbConnectorAliasEditor extends AbstractAkbNodeEditor { + + public final static String ID = AkbUiPlugin.PLUGIN_ID + + ".akbConnectorAliasEditor"; + + /* CONTENT CREATION */ + @Override + public void createPartControl(Composite parent) { + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbEnvTemplateEditor.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbEnvTemplateEditor.java new file mode 100644 index 000000000..8a16202fe --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbEnvTemplateEditor.java @@ -0,0 +1,18 @@ +package org.argeo.slc.akb.ui.editors; + +import org.argeo.slc.akb.ui.AkbUiPlugin; +import org.eclipse.swt.widgets.Composite; + +/** + * Display and edit a connector Alias + */ +public class AkbEnvTemplateEditor extends AbstractAkbNodeEditor { + + public final static String ID = AkbUiPlugin.PLUGIN_ID + + ".akbEnvTemplateEditor"; + + /* CONTENT CREATION */ + @Override + public void createPartControl(Composite parent) { + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbNodeEditorInput.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbNodeEditorInput.java new file mode 100644 index 000000000..be77afe31 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/editors/AkbNodeEditorInput.java @@ -0,0 +1,65 @@ +package org.argeo.slc.akb.ui.editors; + +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IPersistableElement; + +/** + * Editor input for all editors that display info on a given AKB JCR Node. + * Relies on the Jcr ID + */ +public class AkbNodeEditorInput implements IEditorInput { + + private final String jcrId; + + /** the Jcr ID cannot be null */ + public AkbNodeEditorInput(String jcrId) { + this.jcrId = jcrId; + } + + public String getIdentifier() { + return jcrId; + } + + public boolean exists() { + return true; + } + + public ImageDescriptor getImageDescriptor() { + return null; + } + + public String getName() { + return jcrId; + } + + public IPersistableElement getPersistable() { + return null; + } + + public String getToolTipText() { + return "Display and edit information about a given AKB Jcr Node"; + } + + @SuppressWarnings("rawtypes") + public Object getAdapter(Class adapter) { + return null; + } + + public int hashCode() { + return jcrId.hashCode(); + } + + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + AkbNodeEditorInput other = (AkbNodeEditorInput) obj; + if (!jcrId.equals(other.getIdentifier())) + return false; + return true; + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/AkbTreeLabelProvider.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/AkbTreeLabelProvider.java new file mode 100644 index 000000000..8fb639cc7 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/AkbTreeLabelProvider.java @@ -0,0 +1,53 @@ +package org.argeo.slc.akb.ui.providers; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.eclipse.ui.TreeParent; +import org.argeo.slc.akb.AkbException; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +/** Basic label provider for an AKB tree */ +public class AkbTreeLabelProvider extends LabelProvider { + // private final static Log log = LogFactory + // .getLog(ResultTreeLabelProvider.class); + + @Override + public String getText(Object element) { + try { + + if (element instanceof Node) { + Node node = (Node) element; + if (node.isNodeType(NodeType.MIX_TITLE)) + return node.getProperty(Property.JCR_TITLE).getString(); + else + return node.getName(); + } + } catch (RepositoryException e) { + throw new AkbException("Unexpected error while getting " + + "Custom node label", e); + } + return ((TreeParent) element).getName(); + } + + public Image getImage(Object obj) { + // if (obj instanceof SingleResultNode) { + // // FIXME add realtime modification of process icon (SCHEDULED, + // // RUNNING, COMPLETED...) + // // Node resultNode = ((SingleResultNode) obj).getNode(); + // // int status = SlcJcrUtils.aggregateTestStatus(resultNode); + // return SlcImages.PROCESS_COMPLETED; + // } else if (obj instanceof ResultParent) { + // ResultParent rParent = (ResultParent) obj; + // if (SlcUiConstants.DEFAULT_MY_RESULTS_FOLDER_LABEL.equals(rParent + // .getName())) + // return SlcImages.MY_RESULTS_FOLDER; + // else + // return SlcImages.FOLDER; + // } else + return null; + } +} diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/TemplatesTreeContentProvider.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/TemplatesTreeContentProvider.java new file mode 100644 index 000000000..6d57dce63 --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/providers/TemplatesTreeContentProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.akb.ui.providers; + +import org.argeo.eclipse.ui.TreeParent; +import org.eclipse.jface.viewers.ITreeContentProvider; +import org.eclipse.jface.viewers.Viewer; + +/** Basic content provider for a tree of AKB environment templates */ +public class TemplatesTreeContentProvider implements ITreeContentProvider { + + /** + * @param parent + * Pass current user home as parameter + * + */ + public Object[] getElements(Object parent) { + if (parent instanceof Object[]) + return (Object[]) parent; + else + return null; + } + + public Object getParent(Object child) { + return ((TreeParent) child).getParent(); + } + + public Object[] getChildren(Object parent) { + return ((TreeParent) parent).getChildren(); + } + + public boolean hasChildren(Object parent) { + return ((TreeParent) parent).hasChildren(); + } + + public void dispose() { + // FIXME implement if needed + } + + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + } +} \ No newline at end of file diff --git a/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/views/AkbTemplatesTreeView.java b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/views/AkbTemplatesTreeView.java new file mode 100644 index 000000000..9e82b4beb --- /dev/null +++ b/plugins/org.argeo.slc.akb.ui/src/main/java/org/argeo/slc/akb/ui/views/AkbTemplatesTreeView.java @@ -0,0 +1,464 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.slc.akb.ui.views; + +import java.util.HashMap; +import java.util.Map; + +import javax.jcr.Node; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; + +import org.argeo.eclipse.ui.utils.CommandUtils; +import org.argeo.slc.akb.AkbException; +import org.argeo.slc.akb.AkbNames; +import org.argeo.slc.akb.AkbTypes; +import org.argeo.slc.akb.ui.AkbUiPlugin; +import org.argeo.slc.akb.ui.commands.OpenAkbNodeEditor; +import org.argeo.slc.akb.ui.providers.AkbTreeLabelProvider; +import org.argeo.slc.akb.ui.providers.TemplatesTreeContentProvider; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.part.ViewPart; + +/** SLC generic JCR Result tree view. */ +public class AkbTemplatesTreeView extends ViewPart { + // private final static Log log = + // LogFactory.getLog(JcrResultTreeView.class); + + public final static String ID = AkbUiPlugin.PLUGIN_ID + + ".akbTemplatesTreeView"; + + /* DEPENDENCY INJECTION */ + private Session session; + + // This page widgets + private TreeViewer resultTreeViewer; + + // Usefull business objects + private Node templatesParentNode; + + // private EventListener myResultsObserver = null; + // private EventListener allResultsObserver = null; + // + // // under My Results + // private final static String[] observedNodeTypesUnderMyResult = { + // SlcTypes.SLC_TEST_RESULT, SlcTypes.SLC_RESULT_FOLDER, + // SlcTypes.SLC_MY_RESULT_ROOT_FOLDER }; + // + // private final static String[] observedNodeTypesUnderAllResults = { + // SlcTypes.SLC_TEST_RESULT, NodeType.NT_UNSTRUCTURED }; + // + // private boolean isResultFolder = false; + + // /** + // * To be overridden to adapt size of form and result frames. + // */ + // protected int[] getWeights() { + // return new int[] { 70, 30 }; + // } + + private void initialize() { + try { + templatesParentNode = session + .getNode(AkbNames.AKB_TEMPLATES_BASE_PATH); + } catch (RepositoryException e) { + throw new AkbException("unable to initialize AKB Browser view", e); + } + } + + @Override + public void createPartControl(Composite parent) { + initialize(); + + createResultsTreeViewer(parent); + + // parent.setLayout(new FillLayout()); + // // Main layout + // SashForm sashForm = new SashForm(parent, SWT.VERTICAL); + // sashForm.setSashWidth(4); + // sashForm.setLayout(new FillLayout()); + + // Create the tree on top of the view + // Composite top = new Composite(sashForm, SWT.NONE); + // GridLayout gl = new GridLayout(1, false); + // top.setLayout(gl); + // resultTreeViewer = createResultsTreeViewer(top); + + // // Create the property viewer on the bottom + // Composite bottom = new Composite(sashForm, SWT.NONE); + // bottom.setLayout(new GridLayout(1, false)); + // propertiesViewer = createPropertiesViewer(bottom); + // + // sashForm.setWeights(getWeights()); + + // setOrderedInput(resultTreeViewer); + + // Initialize observer + // try { + // ObservationManager observationManager = session.getWorkspace() + // .getObservationManager(); + // myResultsObserver = new MyResultsObserver(resultTreeViewer + // .getTree().getDisplay()); + // allResultsObserver = new AllResultsObserver(resultTreeViewer + // .getTree().getDisplay()); + // + // // observe tree changes under MyResults + // observationManager.addEventListener(myResultsObserver, + // Event.NODE_ADDED | Event.NODE_REMOVED, + // SlcJcrResultUtils.getMyResultsBasePath(session), true, + // null, observedNodeTypesUnderMyResult, false); + // // observe tree changes under All results + // observationManager.addEventListener(allResultsObserver, + // Event.NODE_ADDED | Event.NODE_REMOVED, + // SlcJcrResultUtils.getSlcResultsBasePath(session), true, + // null, observedNodeTypesUnderAllResults, false); + // } catch (RepositoryException e) { + // throw new SlcException("Cannot register listeners", e); + // } + } + + /** + * Override default behaviour so that default defined order remains + * unchanged on first level of the tree + */ + // private void setOrderedInput(TreeViewer viewer) { + // // Add specific ordering + // viewer.setInput(null); + // viewer.setComparator(null); + // viewer.setInput(initializeResultTree()); + // viewer.setComparator(new ResultItemsComparator()); + // } + + // The main tree viewer + protected TreeViewer createResultsTreeViewer(Composite parent) { + int style = SWT.BORDER | SWT.MULTI; + + TreeViewer viewer = new TreeViewer(parent, style); + viewer.getTree().setLayoutData( + new GridData(SWT.FILL, SWT.FILL, true, true)); + + viewer.setContentProvider(new TemplatesTreeContentProvider()); + viewer.setLabelProvider(new AkbTreeLabelProvider()); + viewer.addDoubleClickListener(new ViewDoubleClickListener()); + + // Add label provider with label decorator + // ResultTreeLabelProvider rtLblProvider = new + // ResultTreeLabelProvider(); + // ILabelDecorator decorator = AkbUiPlugin.getDefault().getWorkbench() + // .getDecoratorManager().getLabelDecorator(); + // viewer.setLabelProvider(new DecoratingLabelProvider(rtLblProvider, + // decorator)); + // viewer.addDoubleClickListener(new ViewDoubleClickListener()); + + // Override default behaviour to insure that 2 distincts results that + // have the same name will be correctly and distincly returned by + // corresponding TreeViewer.getSelection() method. + // viewer.setComparer(new ResultItemsComparer()); + + getSite().setSelectionProvider(viewer); + + // // add drag & drop support + // int operations = DND.DROP_COPY | DND.DROP_MOVE; + // Transfer[] tt = new Transfer[] { TextTransfer.getInstance() }; + // viewer.addDragSupport(operations, tt, new ViewDragListener()); + // viewer.addDropSupport(operations, tt, new ViewDropListener(viewer)); + + // add context menu + MenuManager menuManager = new MenuManager(); + Menu menu = menuManager.createContextMenu(viewer.getTree()); + menuManager.addMenuListener(new IMenuListener() { + public void menuAboutToShow(IMenuManager manager) { + contextMenuAboutToShow(manager); + } + }); + viewer.getTree().setMenu(menu); + menuManager.setRemoveAllWhenShown(true); + + getSite().registerContextMenu(menuManager, viewer); + + // add change listener to display TestResult information in the property + // viewer + // viewer.addSelectionChangedListener(new MySelectionChangedListener()); + return viewer; + } + + // Detailed property viewer + // protected TableViewer createPropertiesViewer(Composite parent) { + // } + + @Override + public void setFocus() { + } + + // private ResultParent[] initializeResultTree() { + // try { + // // Force initialization of the tree structure if needed + // SlcJcrResultUtils.getSlcResultsParentNode(session); + // SlcJcrResultUtils.getMyResultParentNode(session); + // // Remove yesterday and last 7 days virtual folders + // // ResultParent[] roots = new ResultParent[5]; + // ResultParent[] roots = new ResultParent[3]; + // + // // My results + // roots[0] = new ParentNodeFolder(null, + // SlcJcrResultUtils.getMyResultParentNode(session), + // SlcUiConstants.DEFAULT_MY_RESULTS_FOLDER_LABEL); + // + // // today + // Calendar cal = Calendar.getInstance(); + // String relPath = JcrUtils.dateAsPath(cal); + // List datePathes = new ArrayList(); + // datePathes.add(relPath); + // roots[1] = new VirtualFolder(null, + // ResultParentUtils.getResultsForDates(session, datePathes), + // "Today"); + // + // // // Yesterday + // // cal = Calendar.getInstance(); + // // cal.add(Calendar.DAY_OF_YEAR, -1); + // // relPath = JcrUtils.dateAsPath(cal); + // // datePathes = new ArrayList(); + // // datePathes.add(relPath); + // // roots[2] = new VirtualFolder(null, + // // ResultParentUtils.getResultsForDates(session, datePathes), + // // "Yesterday"); + // // // Last 7 days + // // + // // cal = Calendar.getInstance(); + // // datePathes = new ArrayList(); + // // + // // for (int i = 0; i < 7; i++) { + // // cal.add(Calendar.DAY_OF_YEAR, -i); + // // relPath = JcrUtils.dateAsPath(cal); + // // datePathes.add(relPath); + // // } + // // roots[3] = new VirtualFolder(null, + // // ResultParentUtils.getResultsForDates(session, datePathes), + // // "Last 7 days"); + // + // // All results + // Node otherResultsPar = session.getNode(SlcJcrResultUtils + // .getSlcResultsBasePath(session)); + // // roots[4] = new ParentNodeFolder(null, otherResultsPar, + // // "All results"); + // roots[2] = new ParentNodeFolder(null, otherResultsPar, + // "All results"); + // return roots; + // } catch (RepositoryException re) { + // throw new ArgeoException( + // "Unexpected error while initializing ResultTree.", re); + // } + // } + + // Manage context menu + /** + * Defines the commands that will pop up in the context menu. + **/ + protected void contextMenuAboutToShow(IMenuManager menuManager) { + IWorkbenchWindow window = AkbUiPlugin.getDefault().getWorkbench() + .getActiveWorkbenchWindow(); + try { + // IStructuredSelection selection = (IStructuredSelection) + // resultTreeViewer + // .getSelection(); + // boolean canAddSubfolder = false; + // boolean canRenamefolder = false; + // boolean isSingleResultNode = false; + // boolean isUnderMyResult = false; + // boolean validMultipleDelete = false; + // + // // Building conditions + // if (selection.size() == 1) { + // Object obj = selection.getFirstElement(); + // if (obj instanceof SingleResultNode) + // isSingleResultNode = true; + // else if (obj instanceof ParentNodeFolder) { + // Node cNode = ((ParentNodeFolder) obj).getNode(); + // if (cNode.isNodeType(SlcTypes.SLC_RESULT_FOLDER)) { + // canAddSubfolder = true; + // canRenamefolder = true; + // isUnderMyResult = true; + // } else if (cNode + // .isNodeType(SlcTypes.SLC_MY_RESULT_ROOT_FOLDER)) { + // canAddSubfolder = true; + // } + // } + // } else { + // @SuppressWarnings("rawtypes") + // Iterator it = selection.iterator(); + // multicheck: while (it.hasNext()) { + // validMultipleDelete = true; + // Object obj = it.next(); + // if (obj instanceof SingleResultNode) + // continue multicheck; + // else if (obj instanceof ParentNodeFolder) { + // Node cNode = ((ParentNodeFolder) obj).getNode(); + // if (cNode.isNodeType(SlcTypes.SLC_RESULT_FOLDER)) + // continue multicheck; + // else { + // validMultipleDelete = false; + // break multicheck; + // } + // } else { + // validMultipleDelete = false; + // break multicheck; + // } + // } + // } + + Map params = new HashMap(); + params.put(OpenAkbNodeEditor.PARAM_PARENT_NODE_JCR_ID, + templatesParentNode.getIdentifier()); + params.put(OpenAkbNodeEditor.PARAM_NODE_TYPE, + AkbTypes.AKB_ENV_TEMPLATE); + + // Effective Refresh + CommandUtils.refreshParametrizedCommand(menuManager, window, + OpenAkbNodeEditor.ID, "Create new template...", null, true, + params); + + // + // CommandUtils.refreshCommand(menuManager, window, DeleteItems.ID, + // DeleteItems.DEFAULT_LABEL, DeleteItems.DEFAULT_IMG_DESCRIPTOR, + // isUnderMyResult || isSingleResultNode || validMultipleDelete); + // + // CommandUtils.refreshCommand(menuManager, window, + // AddResultFolder.ID, + // AddResultFolder.DEFAULT_LABEL, + // ClientUiPlugin.getDefault().getWorkbench().getSharedImages() + // .getImageDescriptor(ISharedImages.IMG_OBJ_ADD), + // canAddSubfolder); + // + // CommandUtils.refreshCommand(menuManager, window, + // RenameResultFolder.ID, + // RenameResultFolder.DEFAULT_LABEL, + // RenameResultFolder.DEFAULT_IMG_DESCRIPTOR, canRenamefolder); + // + // // Command removed for the time being. + // CommandUtils.refreshCommand(menuManager, window, + // RenameResultNode.ID, + // RenameResultNode.DEFAULT_LABEL, + // RenameResultNode.DEFAULT_IMG_DESCRIPTOR, false); + // + // // Test to be removed + // // If you use this pattern, do not forget to call + // // menuManager.setRemoveAllWhenShown(true); + // // when creating the menuManager + // + // // menuManager.add(new Action("Test") { + // // public void run() { + // // log.debug("do something"); + // // } + // // }); + } catch (RepositoryException re) { + throw new AkbException("Error while refreshing context menu", re); + } + } + + /* INNER CLASSES */ + class ViewDoubleClickListener implements IDoubleClickListener { + public void doubleClick(DoubleClickEvent evt) { + Object obj = ((IStructuredSelection) evt.getSelection()) + .getFirstElement(); + try { + if (obj instanceof Node) { + Node node = (Node) obj; + CommandUtils.callCommand(OpenAkbNodeEditor.ID, + OpenAkbNodeEditor.PARAM_NODE_JCR_ID, + node.getIdentifier()); + } + } catch (RepositoryException e) { + throw new AkbException("Cannot open " + obj, e); + } + } + } + + // class MyResultsObserver extends AsyncUiEventListener { + // + // public MyResultsObserver(Display display) { + // super(display); + // } + // + // @Override + // protected Boolean willProcessInUiThread(List events) + // throws RepositoryException { + // // unfiltered for the time being + // return true; + // } + // + // protected void onEventInUiThread(List events) + // throws RepositoryException { + // List nodesToRefresh = new ArrayList(); + // + // for (Event event : events) { + // String parPath = JcrUtils.parentPath(event.getPath()); + // if (session.nodeExists(parPath)) { + // Node node = session.getNode(parPath); + // if (!nodesToRefresh.contains(node)) { + // nodesToRefresh.add(node); + // } + // } + // } + // + // // Update check nodes + // for (Node node : nodesToRefresh) + // jcrRefresh(node); + // refresh(null); + // } + // } + + // class AllResultsObserver extends AsyncUiEventListener { + // + // public AllResultsObserver(Display display) { + // super(display); + // } + // + // @Override + // protected Boolean willProcessInUiThread(List events) + // throws RepositoryException { + // // unfiltered for the time being + // return true; + // } + // + // protected void onEventInUiThread(List events) + // throws RepositoryException { + // refresh(null); + // // if (lastSelectedSourceElementParent != null) + // // refresh(lastSelectedSourceElementParent); + // } + // } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + try { + session = repository.login(); + } catch (RepositoryException e) { + throw new AkbException("unable to log in for " + ID + " view"); + } + } +} \ No newline at end of file diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java index c341f4acc..7ba191a42 100644 --- a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbNames.java @@ -3,6 +3,21 @@ package org.argeo.slc.akb; /** Maps AKB specific JCR Property names with java constants */ public interface AkbNames { + public final static String AKB_NAMESPACE = "http://www.argeo.org/ns/akb"; + + /* DEFAULT BASE PATHS */ + public final static String AKB_BASE_PATH = "/akb:system"; + public final static String AKB_TEMPLATES_BASE_PATH = AKB_BASE_PATH + "/" + + "akb:templates"; + + public final static String AKB_ENVIRONMENTS_BASE_PATH = AKB_BASE_PATH + "/" + + "akb:environments"; + + /* ENVIRONMENT PROPERTIES */ + + /* CONNECTOR PROPERTIES */ public final static String AKB_CONNECTOR_URL = "akb:connectorUrl"; + /* ITEMS PROPERTIES */ + } \ No newline at end of file diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbTypes.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbTypes.java index 79af5b99b..82407f1ce 100644 --- a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbTypes.java +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/AkbTypes.java @@ -5,14 +5,18 @@ public interface AkbTypes { public final static String ARGEO_NOTE = "argeo:note"; - // Env and templates public final static String AKB_ENV_TEMPLATE = "akb:envTemplate"; public final static String AKB_ENV= "akb:env"; // Connectors public final static String AKB_CONNECTOR = "akb:connector"; + public final static String AKB_CONNECTOR_ALIAS = "akb:connectorAlias"; + // Various connector mixin types + public final static String AKB_SSH_CONNECTOR = "akb:sshConnector"; + public final static String AKB_JDBC_CONNECTOR = "akb:jdbcConnector"; + // Item tree public final static String AKB_ITEM_FOLDER = "akb:itemsFolder"; public final static String AKB_ITEM = "akb:item"; diff --git a/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java new file mode 100644 index 000000000..02ccdc6f6 --- /dev/null +++ b/runtime/org.argeo.slc.akb/src/main/java/org/argeo/slc/akb/core/AkbServiceImpl.java @@ -0,0 +1,79 @@ +package org.argeo.slc.akb.core; + +import java.util.Map; + +import javax.annotation.Resource; +import javax.jcr.Repository; +import javax.jcr.Session; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.jcr.JcrUtils; +import org.argeo.slc.akb.AkbException; +import org.argeo.slc.akb.AkbNames; + +/** + * Concrete access to akb services. It provides among other an initialized + * environment + */ +public class AkbServiceImpl implements AkbNames { + private final static Log log = LogFactory.getLog(AkbServiceImpl.class); + + /* DEPENDENCY INJECTION */ + private Repository repository; + + // Populate the repository in a demo context. + private Map demoData = null; + + /* Life cycle management */ + /** + * Call by each startup in order to make sure the backend is ready to + * receive/provide data. + */ + public void init() { + Session adminSession = null; + try { + adminSession = repository.login(); + + // Initialization of the model + if (!adminSession.nodeExists(AKB_TEMPLATES_BASE_PATH)) { + JcrUtils.mkdirs(adminSession, AKB_TEMPLATES_BASE_PATH); + JcrUtils.mkdirs(adminSession, AKB_ENVIRONMENTS_BASE_PATH); + adminSession.save(); + log.info("Repository has been initialized " + + "with AKB's model"); + } + + // Fill the repository in a demo context + if (demoData != null) { + // Dev only force reload at each start + // if (true) { + // if (!projectsPar.hasNodes()) { + } + } catch (Exception e) { + throw new AkbException("Cannot initialize backend", e); + } finally { + JcrUtils.logoutQuietly(adminSession); + } + // log.info("AKB service has been initialized."); + } + + /** Clean shutdown of the backend. */ + public void destroy() { + // Do nothing + } + + /** Expose injected repository */ + public Repository getRepository() { + return repository; + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setDemoData(Map demoData) { + this.demoData = demoData; + } +} \ No newline at end of file diff --git a/runtime/org.argeo.slc.akb/src/main/resources/org/argeo/slc/akb/akb.cnd b/runtime/org.argeo.slc.akb/src/main/resources/org/argeo/slc/akb/akb.cnd index a73723a01..09fed63a8 100644 --- a/runtime/org.argeo.slc.akb/src/main/resources/org/argeo/slc/akb/akb.cnd +++ b/runtime/org.argeo.slc.akb/src/main/resources/org/argeo/slc/akb/akb.cnd @@ -26,7 +26,18 @@ mixin [akb:connector] > nt:unstructured, mix:title - akb:connectorUrl (STRING) // add argeo keyring + +[akb:connectorAlias] > nt:unstructured, mix:title + +// Various connector types as mixin +[akb:sshConnector] +mixin + +[akb:jdbcConnector] +mixin + + // // GENERIC ITEM