]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Document and improve execution model
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 18:20:06 +0000 (18:20 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 18:20:06 +0000 (18:20 +0000)
Improve UI

ASSIGNED - bug 17: Generalize agent management and registration beyond JMS
https://bugzilla.argeo.org/show_bug.cgi?id=17

git-svn-id: https://svn.argeo.org/slc/trunk@4466 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

27 files changed:
eclipse/plugins/org.argeo.slc.client.ui/icons/agentFactory.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/choices.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpec.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecAttribute.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecs.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/process_completed.png [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/process_error.png [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/process_running.png [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/process_scheduled.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcImages.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrExecutionModulesView.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrProcessListView.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractExecutionValue.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/AbstractSpecAttribute.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionSpec.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveAccessor.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveUtils.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/PrimitiveValue.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValue.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/RefValueChoice.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionSpec.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionSpecAttribute.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcNames.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcTypes.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionModulesListener.java
runtime/org.argeo.slc.support.jcr/src/main/resources/org/argeo/slc/jcr/slc.cnd

diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/agentFactory.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/agentFactory.gif
new file mode 100644 (file)
index 0000000..b51ae39
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/agentFactory.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/choices.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/choices.gif
new file mode 100644 (file)
index 0000000..da2f577
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/choices.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpec.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpec.gif
new file mode 100644 (file)
index 0000000..1ff93cb
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpec.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecAttribute.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecAttribute.gif
new file mode 100644 (file)
index 0000000..bee687c
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecAttribute.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecs.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecs.gif
new file mode 100644 (file)
index 0000000..0b63124
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/executionSpecs.gif differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/process_completed.png b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_completed.png
new file mode 100644 (file)
index 0000000..0ad64e7
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_completed.png differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/process_error.png b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_error.png
new file mode 100644 (file)
index 0000000..e66c98e
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_error.png differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/process_running.png b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_running.png
new file mode 100644 (file)
index 0000000..471c091
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_running.png differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/process_scheduled.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_scheduled.gif
new file mode 100644 (file)
index 0000000..b7f03d5
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/process_scheduled.gif differ
index d9fe3cddb104a267bc82aa37960b471ed89b1477..6254166c528f799dc9588d6eb811c7320a0d3bbf 100644 (file)
@@ -6,6 +6,7 @@ import static org.argeo.slc.client.ui.ClientUiPlugin.img;
 /** Shared images. */
 public class SlcImages {
        public final static Image AGENT = img("icons/agent.gif");
+       public final static Image AGENT_FACTORY = img("icons/agentFactory.gif");
        public final static Image MODULE = img("icons/module.png");
        public final static Image FOLDER = img("icons/folder.gif");
        public final static Image FLOW = img("icons/flow.png");
@@ -16,4 +17,12 @@ public class SlcImages {
        public final static Image RELAUNCH = img("icons/relaunch.gif");
        public final static Image REMOVE_ONE = img("icons/remove_one.gif");
        public final static Image REMOVE_ALL = img("icons/removeAll.png");
+       public final static Image EXECUTION_SPECS = img("icons/executionSpecs.gif");
+       public final static Image EXECUTION_SPEC = img("icons/executionSpec.gif");
+       public final static Image EXECUTION_SPEC_ATTRIBUTE = img("icons/executionSpecAttribute.gif");
+       public final static Image CHOICES = img("icons/choices.gif");
+       public final static Image PROCESS_ERROR = img("icons/process_error.png");
+       public final static Image PROCESS_SCHEDULED = img("icons/process_scheduled.gif");
+       public final static Image PROCESS_RUNNING = img("icons/process_running.png");
+       public final static Image PROCESS_COMPLETED = img("icons/process_completed.png");
 }
index 59157a3702bfb5a6d3fab4ebe3364786603a5b5d..e5696ee9e652a8a10d3ae346e7377e4e4eab502c 100644 (file)
@@ -9,6 +9,7 @@ import javax.jcr.Node;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
 
@@ -103,17 +104,19 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes,
                                        new String[] { SlcJcrConstants.VM_AGENT_FACTORY_PATH });
                }
 
-//             @Override
-//             protected Object[] getChildren(Node node) throws RepositoryException {
-//                     if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY)) {
-//                             List<AgentNodesWrapper> wrappers = new ArrayList<AgentNodesWrapper>();
-//                             for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
-//                                     wrappers.add(new AgentNodesWrapper(nit.nextNode()));
-//                             }
-//                             return wrappers.toArray();
-//                     }
-//                     return super.getChildren(node);
-//             }
+               // @Override
+               // protected Object[] getChildren(Node node) throws RepositoryException
+               // {
+               // if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY)) {
+               // List<AgentNodesWrapper> wrappers = new
+               // ArrayList<AgentNodesWrapper>();
+               // for (NodeIterator nit = node.getNodes(); nit.hasNext();) {
+               // wrappers.add(new AgentNodesWrapper(nit.nextNode()));
+               // }
+               // return wrappers.toArray();
+               // }
+               // return super.getChildren(node);
+               // }
 
                @Override
                protected Object[] sort(Object parent, Object[] children) {
@@ -131,6 +134,12 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes,
                                if (o1 instanceof Node && o2 instanceof Node) {
                                        Node node1 = (Node) o1;
                                        Node node2 = (Node) o2;
+
+                                       if (node1.getName().equals(SLC_EXECUTION_SPECS))
+                                               return -100;
+                                       if (node2.getName().equals(SLC_EXECUTION_SPECS))
+                                               return 100;
+
                                        if (node1.isNodeType(SLC_EXECUTION_FLOW)
                                                        && node2.isNodeType(SLC_EXECUTION_FLOW)) {
                                                return node1.getName().compareTo(node2.getName());
@@ -154,27 +163,27 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes,
 
        }
 
-//     /** Wraps the execution modules of an agent. */
-//     static class AgentNodesWrapper extends NodesWrapper {
-//
-//             public AgentNodesWrapper(Node node) {
-//                     super(node);
-//             }
-//
-//             protected List<WrappedNode> getWrappedNodes()
-//                             throws RepositoryException {
-//                     List<WrappedNode> children = new ArrayList<WrappedNode>();
-//                     Node executionModules = getNode();
-//                     for (NodeIterator nit = executionModules.getNodes(); nit.hasNext();) {
-//                             for (NodeIterator nitVersions = nit.nextNode().getNodes(); nitVersions
-//                                             .hasNext();) {
-//                                     children.add(new WrappedNode(this, nitVersions.nextNode()));
-//                             }
-//                     }
-//                     return children;
-//             }
-//
-//     }
+       // /** Wraps the execution modules of an agent. */
+       // static class AgentNodesWrapper extends NodesWrapper {
+       //
+       // public AgentNodesWrapper(Node node) {
+       // super(node);
+       // }
+       //
+       // protected List<WrappedNode> getWrappedNodes()
+       // throws RepositoryException {
+       // List<WrappedNode> children = new ArrayList<WrappedNode>();
+       // Node executionModules = getNode();
+       // for (NodeIterator nit = executionModules.getNodes(); nit.hasNext();) {
+       // for (NodeIterator nitVersions = nit.nextNode().getNodes(); nitVersions
+       // .hasNext();) {
+       // children.add(new WrappedNode(this, nitVersions.nextNode()));
+       // }
+       // }
+       // return children;
+       // }
+       //
+       // }
 
        class VmAgentObserver extends AsyncUiEventListener {
                protected void onEventInUiThread(EventIterator events) {
@@ -184,32 +193,56 @@ public class JcrExecutionModulesView extends ViewPart implements SlcTypes,
 
        class ViewLabelProvider extends DefaultNodeLabelProvider implements
                        ITableLabelProvider {
-               public String getColumnText(Object obj, int index) {
-                       return getText(obj);
-               }
 
-               public Image getColumnImage(Object obj, int index) {
-                       return getImage(obj);
+               @Override
+               protected String getText(Node node) throws RepositoryException {
+                       if (node.getName().equals(SLC_EXECUTION_SPECS))
+                               return "Execution Specifications";
+                       else if (node.getPath().equals(
+                                       SlcJcrConstants.VM_AGENT_FACTORY_PATH))
+                               return "Internal Agents";
+                       return super.getText(node);
                }
 
+               @Override
                public Image getImage(Node node) throws RepositoryException {
-                       if (node.isNodeType(SlcTypes.SLC_AGENT))
-                               return SlcImages.AGENT;
-                       else if (node.isNodeType(SlcTypes.SLC_MODULE))
-                               return SlcImages.MODULE;
+                       // we try to optimize a bit by putting deeper nodes first
+                       if (node.getParent().isNodeType(
+                                       SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
+                               return SlcImages.CHOICES;
+                       else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE))
+                               return SlcImages.EXECUTION_SPEC_ATTRIBUTE;
+                       else if (node.isNodeType(SlcTypes.SLC_EXECUTION_SPEC))
+                               return SlcImages.EXECUTION_SPEC;
+                       else if (node.getName().equals(SLC_EXECUTION_SPECS))
+                               return SlcImages.EXECUTION_SPECS;
                        else if (node.isNodeType(SlcTypes.SLC_EXECUTION_FLOW))
                                return SlcImages.FLOW;
+                       else if (node.isNodeType(SlcTypes.SLC_MODULE))
+                               return SlcImages.MODULE;
+                       else if (node.isNodeType(SlcTypes.SLC_AGENT))
+                               return SlcImages.AGENT;
+                       else if (node.isNodeType(SlcTypes.SLC_AGENT_FACTORY))
+                               return SlcImages.AGENT_FACTORY;
                        else
                                return SlcImages.FOLDER;
                }
 
                public String getToolTipText(Node node) throws RepositoryException {
-                       if (node.isNodeType(SlcTypes.SLC_MODULE)
+                       if (node.isNodeType(NodeType.MIX_TITLE)
                                        && node.hasProperty(Property.JCR_DESCRIPTION))
                                return node.getProperty(Property.JCR_DESCRIPTION).getString();
                        return super.getToolTipText(node);
                }
 
+               public String getColumnText(Object obj, int index) {
+                       return getText(obj);
+               }
+
+               public Image getColumnImage(Object obj, int index) {
+                       return getImage(obj);
+               }
+
        }
 
        class ViewDoubleClickListener implements IDoubleClickListener {
index ddc34a581943f63ed47d898436261e6c449fd70c..2df53034bb347c24d8cb60bc86f5dcd3e4dc1935 100644 (file)
@@ -19,8 +19,10 @@ import javax.jcr.query.Query;
 import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.client.ui.SlcImages;
 import org.argeo.slc.client.ui.editors.ProcessEditor;
 import org.argeo.slc.client.ui.editors.ProcessEditorInput;
+import org.argeo.slc.execution.ExecutionProcess;
 import org.argeo.slc.jcr.SlcJcrConstants;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
@@ -68,6 +70,7 @@ public class JcrProcessListView extends ViewPart {
 
                processesObserver = new AsyncUiEventListener() {
                        protected void onEventInUiThread(EventIterator events) {
+                               // TODO optimize by updating only the changed process
                                viewer.refresh();
                        }
                };
@@ -157,8 +160,29 @@ public class JcrProcessListView extends ViewPart {
        class LabelProvider extends ColumnLabelProvider implements
                        ITableLabelProvider {
 
-               public Image getColumnImage(Object element, int columnIndex) {
-                       return null;
+               public Image getColumnImage(Object obj, int columnIndex) {
+                       if (columnIndex != 0)
+                               return null;
+                       try {
+                               Node node = (Node) obj;
+                               String status = node.getProperty(SlcNames.SLC_STATUS)
+                                               .getString();
+                               if (status.equals(ExecutionProcess.NEW)
+                                               || status.equals(ExecutionProcess.INITIALIZED)
+                                               || status.equals(ExecutionProcess.SCHEDULED))
+                                       return SlcImages.PROCESS_SCHEDULED;
+                               else if (status.equals(ExecutionProcess.ERROR)
+                                               || status.equals(ExecutionProcess.UNKOWN))
+                                       return SlcImages.PROCESS_ERROR;
+                               else if (status.equals(ExecutionProcess.COMPLETED))
+                                       return SlcImages.PROCESS_COMPLETED;
+                               else if (status.equals(ExecutionProcess.RUNNING))
+                                       return SlcImages.PROCESS_RUNNING;
+                               else
+                                       throw new SlcException("Unkown status " + status);
+                       } catch (RepositoryException e) {
+                               throw new SlcException("Cannot get column text", e);
+                       }
                }
 
                public String getColumnText(Object obj, int index) {
index be5a367d8585defbc8e2f36a7b50287e57415b97..4aaf800e29b61ff2e3aea05d7469c4d154039bf6 100644 (file)
@@ -18,7 +18,7 @@ package org.argeo.slc.core.execution;
 
 import java.io.Serializable;
 
-public abstract class AbstractExecutionValue implements Serializable{
+/** Value to be used by an execution */
+public abstract class AbstractExecutionValue implements Serializable {
        private static final long serialVersionUID = 1558444746120706961L;
-
 }
index dd976f223d122cfd63fce92110a10228b57b6f3e..abe0451148edf725a0713a3892ee425a6de3d0d5 100644 (file)
@@ -20,29 +20,30 @@ import java.io.Serializable;
 
 import org.argeo.slc.execution.ExecutionSpecAttribute;
 
+/** Canonical implementation of the execution spec attribute booleans. */
 public abstract class AbstractSpecAttribute implements ExecutionSpecAttribute,
                Serializable {
        private static final long serialVersionUID = 6494963738891709440L;
-       private Boolean isParameter = false;
-       private Boolean isFrozen = false;
+       private Boolean isImmutable = false;
+       private Boolean isConstant = false;
        private Boolean isHidden = false;
 
        /** Has to be set at instantiation */
-       public Boolean getIsParameter() {
-               return isParameter;
+       public Boolean getIsImmutable() {
+               return isImmutable;
        }
 
-       public void setIsParameter(Boolean isParameter) {
-               this.isParameter = isParameter;
+       public void setIsImmutable(Boolean isImmutable) {
+               this.isImmutable = isImmutable;
        }
 
        /** Cannot be overridden at runtime */
-       public Boolean getIsFrozen() {
-               return isFrozen;
+       public Boolean getIsConstant() {
+               return isConstant;
        }
 
-       public void setIsFrozen(Boolean isFinal) {
-               this.isFrozen = isFinal;
+       public void setIsConstant(Boolean isConstant) {
+               this.isConstant = isConstant;
        }
 
        /** Should not be shown to the end user */
@@ -54,4 +55,27 @@ public abstract class AbstractSpecAttribute implements ExecutionSpecAttribute,
                this.isHidden = isHidden;
        }
 
+       /*
+        * DEPRECATED
+        */
+       /** @deprecated use {@link #getIsImmutable()} instead */
+       public Boolean getIsParameter() {
+               return isImmutable;
+       }
+
+       /** @deprecated use {@link #getIsConstant()} instead */
+       public Boolean getIsFrozen() {
+               return isConstant;
+       }
+
+       /** @deprecated use {@link #setIsImmutable(Boolean)} instead */
+       public void setIsParameter(Boolean isParameter) {
+               this.isImmutable = isParameter;
+       }
+
+       /** @deprecated use {@link #setIsConstant(Boolean)} instead */
+       public void setIsFrozen(Boolean isFrozen) {
+               this.isConstant = isFrozen;
+       }
+
 }
index d47325d349b9065263d1974ee573847fc0959390..f7d64b9e2d0eb5697be6d8008f2b3f72f7c3217c 100644 (file)
@@ -21,7 +21,6 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -36,6 +35,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 import org.springframework.context.ConfigurableApplicationContext;
 
+/** Spring based implementation of execution specifications. */
 public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware,
                ApplicationContextAware, InitializingBean, Serializable {
        private static final long serialVersionUID = 5159882223926926539L;
@@ -46,7 +46,7 @@ public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware,
        private String description;
        private Map<String, ExecutionSpecAttribute> attributes = new HashMap<String, ExecutionSpecAttribute>();
 
-       private String name = getClass().getName() + "#" + UUID.randomUUID();
+       private String name = INTERNAL_NAME;
 
        public Map<String, ExecutionSpecAttribute> getAttributes() {
                return attributes;
@@ -60,6 +60,10 @@ public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware,
                this.name = name;
        }
 
+       /**
+        * The Spring bean name (only relevant for specs declared has high-level
+        * beans)
+        */
        public String getName() {
                return name;
        }
@@ -68,6 +72,10 @@ public class DefaultExecutionSpec implements ExecutionSpec, BeanNameAware,
                return ((ExecutionSpec) obj).getName().equals(name);
        }
 
+       /**
+        * The Spring bean description (only relevant for specs declared has
+        * high-level beans)
+        */
        public String getDescription() {
                return description;
        }
index 21756907fbd321900ee404b970633a40d370f440..c5b29dfb8c2897d9c6645b78d7bb475b7e5748af 100644 (file)
@@ -16,6 +16,7 @@
 
 package org.argeo.slc.core.execution;
 
+/** Abstraction of access to primitive values */
 public interface PrimitiveAccessor {
        public String getType();
 
index a4e09f650edb50812ad2aa900c6ff43061c61cbc..c5a3a8605b950b4e584472c00bbb70d6be98a9cb 100644 (file)
@@ -16,7 +16,7 @@
 
 package org.argeo.slc.core.execution;
 
-
+/** Converts to and from primitive types. */
 public class PrimitiveUtils {
        public final static String TYPE_STRING = "string";
        public final static String TYPE_INTEGER = "integer";
index c19cfa4c38269c089c448c55ec5dd095ab8e0004..4dffd7928ac0577218646084e4f814192f1142f0 100644 (file)
@@ -16,6 +16,7 @@
 
 package org.argeo.slc.core.execution;
 
+/** Primitive value to be used by an execution. */
 public class PrimitiveValue extends AbstractExecutionValue implements
                PrimitiveAccessor {
        private static final long serialVersionUID = 533414290998374166L;
index fb5bf2e8238b7006f52657c8b505f8c2b8a0108f..3795100f6724ea33b7aa8bbe5f1581bbc14a90e0 100644 (file)
@@ -16,6 +16,7 @@
 
 package org.argeo.slc.core.execution;
 
+/** Reference value to be used by an execution */
 public class RefValue extends AbstractExecutionValue {
        private static final long serialVersionUID = -8951231456757181687L;
        private String ref;
index e1ac35e71cc255158cbfbbbbba24e3ded50c2fdf..51531d33682b849f5c839892fb273bf624a7675b 100644 (file)
@@ -18,6 +18,7 @@ package org.argeo.slc.core.execution;
 
 import java.io.Serializable;
 
+/** A choice of ref value to be shown to the end user. */
 public class RefValueChoice implements Serializable {
        private static final long serialVersionUID = -1133645722307507774L;
        private String name;
index 8111cc7d9cda529ef30cf76613283c0fa1a4ba2b..e437740eb43150e6cf0eb01d30a9544383dddac2 100644 (file)
@@ -23,9 +23,23 @@ import java.util.Map;
  * necessary for the corresponding ExecutionFlow.
  */
 public interface ExecutionSpec {
-       public Map<String, ExecutionSpecAttribute> getAttributes();
+       /**
+        * The name for an internal spec (for backward compatibility where a
+        * non-null name is expected)
+        */
+       public final static String INTERNAL_NAME = "__SLC_EXECUTION_SPEC_INTERNAL";
 
+       /**
+        * The name identifying the execution spec within its application context.
+        * Can be null. An execution spec can be referenced only if its name is not
+        * null or different from {@link #INTERNAL_NAME}
+        */
        public String getName();
 
+       /** An optional description. Can be null. */
        public String getDescription();
+
+       /** The attributes managed by this execution spec */
+       public Map<String, ExecutionSpecAttribute> getAttributes();
+
 }
index 4866f637702f3e635c47a5138773da4ce0e1d36f..e7259b8f7754221789f0490c0ade714817b080ee 100644 (file)
 package org.argeo.slc.execution;
 
 /**
- * This interface stands for one attribute of a given flow.
- * 
- * We mainly have two implementations :
+ * Possible attribute of an execution flow.
  * 
+ * There are mainly two implementations :<br>
  * + Primitive attributes (no predefined choice, the end user must compute a
- * String, a Float, an Integer...)
- * 
- * + RefSpecAttribute which enable two things + a reference to another object of
- * the application context + the display of some choices among which the end
- * user can choose.
+ * String, a Float, an Integer...)<br>
+ * + RefSpecAttribute which enable two things<br>
+ * ++ a reference to another object of the application context<br>
+ * ++ the display of some choices among which the end user can choose.<br>
  * 
  * @see org.argeo.slc.core.execution.PrimitiveSpecAttribute
  * @see org.argeo.slc.core.execution.RefSpecAttribute
@@ -34,12 +32,35 @@ package org.argeo.slc.execution;
  *      helper, among others to cast the various type of primitive attribute.
  */
 public interface ExecutionSpecAttribute {
+       /**
+        * Whether this attribute has to be set at instantiation of the flow and
+        * cannot be modified afterwards. If the attribute is not immutable (that
+        * is, this method returns false), it can be set at execution time.
+        */
+       public Boolean getIsImmutable();
+
+       /**
+        * Whether this attribute must be explicitly set and cannot be modified.
+        * This attribute is then basically a constant within a given application
+        * context. {@link #getValue()} cannot return null if the attribute is a
+        * constant.
+        */
+       public Boolean getIsConstant();
+
+       /** Whether this attribute will be hidden to end users. */
+       public Boolean getIsHidden();
+
+       /**
+        * The default value for this attribute. Can be null, except if
+        * {@link #getIsFrozen()} is <code>true</code>, in which case it represents
+        * the constant value of this attribute.
+        */
        public Object getValue();
 
+       /** @deprecated use {@link #getIsImmutable()} instead */
        public Boolean getIsParameter();
 
+       /** @deprecated use {@link #getIsConstant()} instead */
        public Boolean getIsFrozen();
 
-       public Boolean getIsHidden();
-
 }
index 7f0f18a0cc2742acfd4ec66536594c36dc99dfd1..e4d5d6e6ee768b128d91a4af28df47fb7721ad0a 100644 (file)
@@ -3,7 +3,13 @@ package org.argeo.slc.jcr;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
 
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
 import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.PrimitiveAccessor;
+import org.argeo.slc.core.execution.PrimitiveUtils;
 import org.argeo.slc.deploy.ModuleDescriptor;
 
 /**
@@ -61,6 +67,41 @@ public class SlcJcrUtils {
 
        }
 
+       /**
+        * Set the value of the primitive accessor as a JCR property. Does nothing
+        * if the value is null.
+        */
+       public static void setPrimitiveAsProperty(Node node, String propertyName,
+                       PrimitiveAccessor primitiveAccessor) {
+               String type = primitiveAccessor.getType();
+               Object value = primitiveAccessor.getValue();
+               if (value == null)
+                       return;
+               if (value instanceof CharSequence)
+                       value = PrimitiveUtils.convert(type,
+                                       ((CharSequence) value).toString());
+
+               try {
+                       if (type.equals(PrimitiveUtils.TYPE_STRING))
+                               node.setProperty(propertyName, value.toString());
+                       else if (type.equals(PrimitiveUtils.TYPE_INTEGER))
+                               node.setProperty(propertyName, (long) ((Integer) value));
+                       else if (type.equals(PrimitiveUtils.TYPE_LONG))
+                               node.setProperty(propertyName, ((Long) value));
+                       else if (type.equals(PrimitiveUtils.TYPE_FLOAT))
+                               node.setProperty(propertyName, (double) ((Float) value));
+                       else if (type.equals(PrimitiveUtils.TYPE_DOUBLE))
+                               node.setProperty(propertyName, ((Double) value));
+                       else if (type.equals(PrimitiveUtils.TYPE_BOOLEAN))
+                               node.setProperty(propertyName, ((Boolean) value));
+                       else
+                               throw new SlcException("Unsupported type " + type);
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot set primitive " + primitiveAccessor
+                                       + " as property " + propertyName + " on " + node, e);
+               }
+       }
+
        /** Prevents instantiation */
        private SlcJcrUtils() {
 
index 15d1e44282c876f4426b798965e01ff42de7482a..7d906c03652c8a3f0f58b67db05348a406c2df6a 100644 (file)
@@ -5,11 +5,17 @@ public interface SlcNames {
 
        public final static String SLC_UUID = "slc:uuid";
        public final static String SLC_STATUS = "slc:status";
+       public final static String SLC_TYPE = "slc:type";
        public final static String SLC_NAME = "slc:name";
        public final static String SLC_VERSION = "slc:version";
+       public final static String SLC_VALUE = "slc:value";
        public final static String SLC_ADDRESS = "slc:address";
 
+       public final static String SLC_EXECUTION_SPECS = "slc:executionSpecs";
        public final static String SLC_FLOW = "slc:flow";
-       //public final static String SLC_EXECUTION_MODULES = "slc:executionModules";
+
+       public final static String SLC_IS_IMMUTABLE = "slc:isImmutable";
+       public final static String SLC_IS_CONSTANT = "slc:isConstant";
+       public final static String SLC_IS_HIDDEN = "slc:isHidden";
 
 }
index 4a3afc9331b08e6a1250b13456fd70ebfeb4c4f1..6ac10e3b014dfd9db213f998d2dfd2810a2d913c 100644 (file)
@@ -7,8 +7,13 @@ public interface SlcTypes {
        public final static String SLC_AGENT = "slc:agent";
        public final static String SLC_MODULE = "slc:module";
        public final static String SLC_EXECUTION_MODULE = "slc:executionModule";
+       public final static String SLC_EXECUTION_SPEC = "slc:executionSpec";
        public final static String SLC_EXECUTION_FLOW = "slc:executionFlow";
        public final static String SLC_PROCESS = "slc:process";
        public final static String SLC_REALIZED_FLOW = "slc:realizedFlow";
 
+       public final static String SLC_EXECUTION_SPEC_ATTRIBUTE = "slc:executionSpecAttribute";
+       public final static String SLC_PRIMITIVE_SPEC_ATTRIBUTE = "slc:primitiveSpecAttribute";
+       public final static String SLC_REF_SPEC_ATTRIBUTE = "slc:refSpecAttribute";
+
 }
index b019ff970a072d575263d56447ab70ec567d2c45..27d7b6b3b3e374ccc0209981105855551a4d43d6 100644 (file)
@@ -8,14 +8,20 @@ import javax.jcr.NodeIterator;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
+import org.argeo.slc.core.execution.RefSpecAttribute;
+import org.argeo.slc.core.execution.RefValueChoice;
 import org.argeo.slc.deploy.ModuleDescriptor;
 import org.argeo.slc.execution.ExecutionFlowDescriptor;
 import org.argeo.slc.execution.ExecutionModulesListener;
+import org.argeo.slc.execution.ExecutionSpec;
+import org.argeo.slc.execution.ExecutionSpecAttribute;
 import org.argeo.slc.jcr.SlcJcrUtils;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
@@ -24,7 +30,8 @@ import org.argeo.slc.jcr.SlcTypes;
  * Synchronizes the local execution runtime with a JCR repository. For the time
  * being the state is completely reset from one start to another.
  */
-public class JcrExecutionModulesListener implements ExecutionModulesListener {
+public class JcrExecutionModulesListener implements ExecutionModulesListener,
+               SlcNames {
        private final static Log log = LogFactory
                        .getLog(JcrExecutionModulesListener.class);
        private JcrAgent agent;
@@ -73,10 +80,8 @@ public class JcrExecutionModulesListener implements ExecutionModulesListener {
                                        .getNode(moduleNodeName) : agentNode
                                        .addNode(moduleNodeName);
                        moduleNode.addMixin(SlcTypes.SLC_EXECUTION_MODULE);
-                       moduleNode.setProperty(SlcNames.SLC_NAME,
-                                       moduleDescriptor.getName());
-                       moduleNode.setProperty(SlcNames.SLC_VERSION,
-                                       moduleDescriptor.getVersion());
+                       moduleNode.setProperty(SLC_NAME, moduleDescriptor.getName());
+                       moduleNode.setProperty(SLC_VERSION, moduleDescriptor.getVersion());
                        moduleNode.setProperty(Property.JCR_TITLE,
                                        moduleDescriptor.getTitle());
                        moduleNode.setProperty(Property.JCR_DESCRIPTION,
@@ -104,44 +109,119 @@ public class JcrExecutionModulesListener implements ExecutionModulesListener {
        }
 
        public synchronized void executionFlowAdded(ModuleDescriptor module,
-                       ExecutionFlowDescriptor executionFlow) {
+                       ExecutionFlowDescriptor efd) {
                try {
                        Node agentNode = session.getNode(agent.getNodePath());
                        Node moduleNode = agentNode.getNode(SlcJcrUtils
                                        .getModuleNodeName(module));
-                       String relativePath = getExecutionFlowRelativePath(executionFlow);
+                       String relativePath = getExecutionFlowRelativePath(efd);
+                       @SuppressWarnings("unused")
                        Node flowNode = null;
                        if (!moduleNode.hasNode(relativePath)) {
-                               Iterator<String> names = Arrays.asList(relativePath.split("/"))
-                                               .iterator();
-                               // create intermediary paths
-                               Node currNode = moduleNode;
-                               while (names.hasNext()) {
-                                       String name = names.next();
-                                       if (currNode.hasNode(name))
-                                               currNode = currNode.getNode(name);
-                                       else {
-                                               if (names.hasNext())
-                                                       currNode = currNode.addNode(name);
-                                               else
-                                                       flowNode = currNode.addNode(name,
-                                                                       SlcTypes.SLC_EXECUTION_FLOW);
-                                       }
-                               }
-                               flowNode.setProperty(SlcNames.SLC_NAME, executionFlow.getName());
+                               flowNode = createExecutionFlowNode(moduleNode, relativePath,
+                                               efd);
                                session.save();
                        } else {
                                flowNode = moduleNode.getNode(relativePath);
                        }
 
                        if (log.isTraceEnabled())
-                               log.trace("Flow " + executionFlow + " added to JCR");
+                               log.trace("Flow " + efd + " added to JCR");
                } catch (RepositoryException e) {
                        JcrUtils.discardQuietly(session);
-                       throw new SlcException("Cannot add flow " + executionFlow
-                                       + " from module " + module, e);
+                       throw new SlcException("Cannot add flow " + efd + " from module "
+                                       + module, e);
+               }
+
+       }
+
+       protected Node createExecutionFlowNode(Node moduleNode,
+                       String relativePath, ExecutionFlowDescriptor efd)
+                       throws RepositoryException {
+               Node flowNode = null;
+               Iterator<String> names = Arrays.asList(relativePath.split("/"))
+                               .iterator();
+               // create intermediary paths
+               Node currNode = moduleNode;
+               while (names.hasNext()) {
+                       String name = names.next();
+                       if (currNode.hasNode(name))
+                               currNode = currNode.getNode(name);
+                       else {
+                               if (names.hasNext())
+                                       currNode = currNode.addNode(name);
+                               else
+                                       flowNode = currNode.addNode(name,
+                                                       SlcTypes.SLC_EXECUTION_FLOW);
+                       }
                }
+               flowNode.setProperty(SLC_NAME, efd.getName());
+               String[] tokens = relativePath.split("/");
+               flowNode.setProperty(Property.JCR_TITLE, tokens[tokens.length - 1]);
+               if (efd.getDescription() != null
+                               && efd.getDescription().trim().equals(""))
+                       flowNode.setProperty(Property.JCR_DESCRIPTION, efd.getDescription());
 
+               // execution spec
+               ExecutionSpec executionSpec = efd.getExecutionSpec();
+               String esName = executionSpec.getName();
+               if (esName != null && !esName.equals(ExecutionSpec.INTERNAL_NAME)) {
+                       Node executionSpecsNode = moduleNode.hasNode(SLC_EXECUTION_SPECS) ? moduleNode
+                                       .getNode(SLC_EXECUTION_SPECS) : moduleNode
+                                       .addNode(SLC_EXECUTION_SPECS);
+                       Node executionSpecNode = executionSpecsNode.addNode(esName,
+                                       SlcTypes.SLC_EXECUTION_SPEC);
+                       executionSpecNode.setProperty(Property.JCR_TITLE, esName);
+                       if (executionSpec.getDescription() != null
+                                       && !executionSpec.getDescription().trim().equals(""))
+                               executionSpecNode.setProperty(Property.JCR_DESCRIPTION,
+                                               executionSpec.getDescription());
+                       mapExecutionSpec(executionSpecNode, executionSpec);
+               } else {
+                       mapExecutionSpec(flowNode, executionSpec);
+               }
+               return flowNode;
+       }
+
+       /**
+        * Base can be either an execution spec node, or an execution flow node (in
+        * case the execution spec is internal)
+        */
+       protected void mapExecutionSpec(Node baseNode, ExecutionSpec executionSpec)
+                       throws RepositoryException {
+               for (String attrName : executionSpec.getAttributes().keySet()) {
+                       ExecutionSpecAttribute esa = executionSpec.getAttributes().get(
+                                       attrName);
+                       Node attrNode = baseNode.addNode(attrName);
+                       // booleans
+                       attrNode.addMixin(SlcTypes.SLC_EXECUTION_SPEC_ATTRIBUTE);
+                       attrNode.setProperty(SLC_IS_IMMUTABLE, esa.getIsImmutable());
+                       attrNode.setProperty(SLC_IS_CONSTANT, esa.getIsConstant());
+                       attrNode.setProperty(SLC_IS_HIDDEN, esa.getIsHidden());
+
+                       if (esa instanceof PrimitiveSpecAttribute) {
+                               attrNode.addMixin(SlcTypes.SLC_PRIMITIVE_SPEC_ATTRIBUTE);
+                               PrimitiveSpecAttribute psa = (PrimitiveSpecAttribute) esa;
+                               SlcJcrUtils.setPrimitiveAsProperty(attrNode, SLC_VALUE, psa);
+                               attrNode.setProperty(SLC_TYPE, psa.getType());
+                       } else if (esa instanceof RefSpecAttribute) {
+                               attrNode.addMixin(SlcTypes.SLC_REF_SPEC_ATTRIBUTE);
+                               RefSpecAttribute rsa = (RefSpecAttribute) esa;
+                               attrNode.setProperty(SLC_TYPE, rsa.getTargetClassName());
+                               if (rsa.getChoices() != null) {
+                                       for (RefValueChoice choice : rsa.getChoices()) {
+                                               Node choiceNode = attrNode.addNode(choice.getName());
+                                               choiceNode.addMixin(NodeType.MIX_TITLE);
+                                               choiceNode.setProperty(Property.JCR_TITLE,
+                                                               choice.getName());
+                                               if (choice.getDescription() != null
+                                                               && !choice.getDescription().trim().equals(""))
+                                                       choiceNode.setProperty(Property.JCR_DESCRIPTION,
+                                                                       choice.getDescription());
+                                       }
+                               }
+                       }
+               }
        }
 
        public synchronized void executionFlowRemoved(ModuleDescriptor module,
index 6b79bc9c47e4d14b820c4c9113f84759b9b06c7e..3bdf51ce95831c2d6fb30e6ee04c1408bf6f5fb2 100644 (file)
@@ -22,8 +22,34 @@ mixin
 [slc:executionModule] > slc:activableModule
 mixin
 
+[slc:executionSpec] > nt:unstructured, mix:referenceable, mix:title
+- slc:name (STRING)
++ * (slc:executionSpecAttribute) *
+
+[slc:executionSpecAttribute] > nt:base
+mixin abstract
+- slc:isImmutable (BOOLEAN) m
+- slc:isConstant (BOOLEAN) m
+- slc:isHidden (BOOLEAN) m
+
+[slc:primitiveSpecAttribute] > slc:executionSpecAttribute
+mixin
+- slc:type (STRING) m
+- slc:value (UNDEFINED)
+
+[slc:refSpecAttribute] > slc:executionSpecAttribute
+mixin
+// typically a class name
+- slc:type (STRING)
++ slc:value
++ * (mix:title)
+
 [slc:executionFlow] > nt:unstructured, mix:title
 - slc:name (STRING) m
+// if the execution spec is a referenceable node
+- slc:executionSpec (REFERENCE)
+// if the execution spec is internal (without name)
++ * (slc:executionSpecAttribute) *
 
 // PROCESS
 [slc:process] > nt:unstructured, mix:created, mix:lastModified