/** 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");
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");
}
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;
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) {
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());
}
-// /** 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) {
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 {
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;
processesObserver = new AsyncUiEventListener() {
protected void onEventInUiThread(EventIterator events) {
+ // TODO optimize by updating only the changed process
viewer.refresh();
}
};
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) {
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;
-
}
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 */
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;
+ }
+
}
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;
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;
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;
this.name = name;
}
+ /**
+ * The Spring bean name (only relevant for specs declared has high-level
+ * beans)
+ */
public String getName() {
return name;
}
return ((ExecutionSpec) obj).getName().equals(name);
}
+ /**
+ * The Spring bean description (only relevant for specs declared has
+ * high-level beans)
+ */
public String getDescription() {
return description;
}
package org.argeo.slc.core.execution;
+/** Abstraction of access to primitive values */
public interface PrimitiveAccessor {
public String getType();
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";
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;
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;
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;
* 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();
+
}
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
* 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();
-
}
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;
/**
}
+ /**
+ * 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() {
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";
}
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";
+
}
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;
* 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;
.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,
}
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,
[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