Almost complete implementation of the flow namespace
authorMathieu Baudier <mbaudier@argeo.org>
Thu, 14 Jan 2010 20:51:30 +0000 (20:51 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Thu, 14 Jan 2010 20:51:30 +0000 (20:51 +0000)
git-svn-id: https://svn.argeo.org/slc/trunk@3286 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

runtime/org.argeo.slc.core/.settings/org.eclipse.pde.core.prefs [new file with mode: 0644]
runtime/org.argeo.slc.core/pom.xml
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowNamespaceHandler.java
runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java [new file with mode: 0644]
runtime/org.argeo.slc.core/src/main/resources/org/argeo/slc/core/execution/xml/slc-flow-0.12.xsd

diff --git a/runtime/org.argeo.slc.core/.settings/org.eclipse.pde.core.prefs b/runtime/org.argeo.slc.core/.settings/org.eclipse.pde.core.prefs
new file mode 100644 (file)
index 0000000..ab64d57
--- /dev/null
@@ -0,0 +1,4 @@
+#Tue Jan 12 18:56:33 CET 2010
+eclipse.preferences.version=1
+pluginProject.equinox=false
+pluginProject.extensions=false
index 9b305e67eebacb7e37bc5055e3c5efcae03e2302..f2ced2108756ce558d47698fe235316e0d41f1ab 100644 (file)
@@ -12,6 +12,7 @@
        <name>SLC Core</name>
        <description>Basic implementations of SLC Specifications</description>
        <build>
+               <outputDirectory>bin</outputDirectory>
                <resources>
                        <resource>
                                <directory>src/main/resources</directory>
index 2d2d28babbddb5cd8f84ad1d8b361299a275504f..a692279b816eef47d409464ea3651055a14e4b5e 100644 (file)
@@ -46,7 +46,7 @@ public class DefaultExecutionFlowDescriptorConverter implements
                ExecutionSpec executionSpec = executionFlowDescriptor
                                .getExecutionSpec();
 
-               if (executionSpec == null)
+               if (executionSpec == null && log.isTraceEnabled())
                        log.warn("Execution spec is null for " + executionFlowDescriptor);
 
                if (values != null && executionSpec != null) {
index 306beace251c45e2cc3e2dd31d8969c0bdd9a67f..85269778c895c442c568f17a7a924cb2ab748617 100644 (file)
@@ -5,8 +5,10 @@ import java.util.List;
 
 import org.argeo.slc.SlcException;
 import org.argeo.slc.core.execution.DefaultExecutionFlow;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
 import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
 import org.springframework.beans.factory.xml.ParserContext;
 import org.springframework.util.StringUtils;
@@ -16,41 +18,79 @@ import org.w3c.dom.NodeList;
 
 public class FlowBeanDefinitionParser extends
                AbstractSingleBeanDefinitionParser {
-//     private Log log = LogFactory.getLog(FlowBeanDefinitionParser.class);
+       // private Log log = LogFactory.getLog(FlowBeanDefinitionParser.class);
 
        @SuppressWarnings("unchecked")
        @Override
        protected void doParse(Element element, ParserContext parserContext,
                        BeanDefinitionBuilder builder) {
-               String path = element.getAttribute("lenient");
+               String path = element.getAttribute("path");
                if (StringUtils.hasText(path))
                        builder.addPropertyValue("path", path);
 
-               List<Element> children = new ArrayList<Element>();
+               String spec = element.getAttribute("spec");
+               if (StringUtils.hasText(spec))
+                       builder.getRawBeanDefinition().getConstructorArgumentValues()
+                                       .addGenericArgumentValue(new RuntimeBeanReference(spec));
+
+               String abstrac = element.getAttribute("abstract");
+               if (StringUtils.hasText(abstrac))
+                       builder.setAbstract(Boolean.parseBoolean(abstrac));
+
+               String parent = element.getAttribute("parent");
+               if (StringUtils.hasText(parent))
+                       builder.setParentName(parent);
+
+               List<Element> execElems = new ArrayList<Element>();
+               List<Element> argsElems = new ArrayList<Element>();
                NodeList nodeList = element.getChildNodes();
                for (int i = 0; i < nodeList.getLength(); i++) {
                        Node node = nodeList.item(i);
-                       if (node instanceof Element)
-                               children.add((Element) node);
+                       if (node instanceof Element) {
+                               if ("arg".equals(node.getLocalName()))
+                                       argsElems.add((Element) node);
+                               else
+                                       execElems.add((Element) node);
+                       }
+               }
+
+               // Arguments
+               if (argsElems.size() != 0) {
+                       ManagedMap args = new ManagedMap(argsElems.size());
+                       for (Element argElem : argsElems) {
+                               if (argElem.hasAttribute("value"))
+                                       args.put(argElem.getAttribute("name"), argElem
+                                                       .getAttribute("value"));
+                               else if (argElem.hasAttribute("ref"))
+                                       args.put(argElem.getAttribute("name"),
+                                                       new RuntimeBeanReference(argElem
+                                                                       .getAttribute("ref")));
+                               else
+                                       throw new SlcException("No value defined.");
+                       }
+                       builder.getRawBeanDefinition().getConstructorArgumentValues()
+                                       .addGenericArgumentValue(args);
                }
-               // children.addAll(DomUtils.getChildElementsByTagName(element, "bean"));
-               // children.addAll(DomUtils.getChildElementsByTagName(element, "ref"));
 
-               ManagedList executables = new ManagedList(children.size());
-               for (int i = 0; i < children.size(); i++) {
-                       Element child = children.get(i);
-                       String name = child.getNodeName();
-                       if ("bean".equals(name) || "ref".equals(name)) {
-                               Object target = parseBeanReference(element, (Element) child,
-                                               parserContext, builder);
-                               executables.add(target);
-                       } else if ("flow".equals(name)) {
-                               // TODO
-                       } else {
-                               throw new SlcException("Unsupported children '" + name + "'");
+               // Executables
+               if (execElems.size() != 0) {
+                       ManagedList executables = new ManagedList(execElems.size());
+                       for (int i = 0; i < execElems.size(); i++) {
+                               Element child = execElems.get(i);
+                               String name = child.getLocalName();
+                               if ("bean".equals(name) || "ref".equals(name)) {
+                                       Object target = parseBeanReference((Element) child,
+                                                       parserContext, builder);
+                                       executables.add(target);
+                               } else if ("flow".equals(name)) {
+                                       throw new SlcException(
+                                                       "Nested flows are not yet supported use a standard ref to another flow.");
+                               } else {
+                                       throw new SlcException("Unsupported child '" + name + "'");
+                               }
                        }
+                       builder.addPropertyValue("executables", executables);
                }
-               builder.addPropertyValue("executables", executables);
        }
 
        @Override
@@ -59,7 +99,7 @@ public class FlowBeanDefinitionParser extends
        }
 
        // parse nested bean definition
-       private Object parseBeanReference(Element parent, Element element,
+       private Object parseBeanReference(Element element,
                        ParserContext parserContext, BeanDefinitionBuilder builder) {
                return parserContext.getDelegate().parsePropertySubElement(element,
                                builder.getBeanDefinition());
index f20b193ca5b1a44abcafea19fc201506fa4c894b..024591c9681182c4eb1a69ad6c0baabf88857206 100644 (file)
@@ -6,6 +6,7 @@ public class FlowNamespaceHandler extends NamespaceHandlerSupport {
 
        public void init() {
                registerBeanDefinitionParser("flow", new FlowBeanDefinitionParser());
+               registerBeanDefinitionParser("spec", new SpecBeanDefinitionParser());
                registerBeanDefinitionDecoratorForAttribute("as-flow",
                                new AsFlowDecorator());
        }
diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/SpecBeanDefinitionParser.java
new file mode 100644 (file)
index 0000000..2847365
--- /dev/null
@@ -0,0 +1,161 @@
+package org.argeo.slc.core.execution.xml;
+
+import java.util.List;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.core.execution.DefaultExecutionSpec;
+import org.argeo.slc.core.execution.PrimitiveSpecAttribute;
+import org.argeo.slc.core.execution.RefSpecAttribute;
+import org.argeo.slc.core.execution.RefValueChoice;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.ManagedList;
+import org.springframework.beans.factory.support.ManagedMap;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class SpecBeanDefinitionParser extends
+               AbstractSingleBeanDefinitionParser {
+       private Log log = LogFactory.getLog(SpecBeanDefinitionParser.class);
+
+       @SuppressWarnings("unchecked")
+       @Override
+       protected void doParse(Element element, ParserContext parserContext,
+                       BeanDefinitionBuilder builder) {
+               ManagedMap specAttrs = new ManagedMap();
+
+               // Primitives
+               for (Element child : (List<Element>) DomUtils
+                               .getChildElementsByTagName(element, "primitive")) {
+                       BeanDefinitionBuilder childBuilder = BeanDefinitionBuilder
+                                       .genericBeanDefinition(PrimitiveSpecAttribute.class);
+                       addAbstractSpecAttributeProperties(childBuilder, child);
+                       addValue(childBuilder, child, parserContext);
+
+                       String type = child.getAttribute("type");
+                       if (StringUtils.hasText(type))
+                               childBuilder.addPropertyValue("type", type);
+
+                       String name = child.getAttribute("name");
+                       specAttrs.put(name, childBuilder.getBeanDefinition());
+                       if (log.isTraceEnabled())
+                               log.debug("Added primitive attribute " + name);
+               }
+
+               // Refs
+               for (Element child : (List<Element>) DomUtils
+                               .getChildElementsByTagName(element, "ref")) {
+                       BeanDefinitionBuilder childBuilder = BeanDefinitionBuilder
+                                       .genericBeanDefinition(RefSpecAttribute.class);
+                       addAbstractSpecAttributeProperties(childBuilder, child);
+                       addValue(childBuilder, child, parserContext);
+
+                       String targetClassName = child.getAttribute("targetClass");
+                       if (StringUtils.hasText(targetClassName))
+                               childBuilder.addPropertyValue("targetClass", targetClassName);
+
+                       // Choices
+                       NodeList choicesNd = child.getElementsByTagName("choices");
+                       if (choicesNd.getLength() > 0) {
+                               Element choicesElem = (Element) choicesNd.item(0);
+                               List choices = DomUtils.getChildElementsByTagName(choicesElem,
+                                               "choice");
+                               ManagedList choiceBeans = new ManagedList(choices.size());
+                               for (Element choiceElem : (List<Element>) choices) {
+                                       BeanDefinitionBuilder choiceBuilder = BeanDefinitionBuilder
+                                                       .genericBeanDefinition(RefValueChoice.class);
+                                       choiceBuilder.addPropertyValue("name", choiceElem
+                                                       .getAttribute("name"));
+                                       String desc = choiceElem.getAttribute("description");
+                                       if (StringUtils.hasText(desc))
+                                               choiceBuilder.addPropertyValue("description", desc);
+
+                                       choiceBeans.add(choiceBuilder.getBeanDefinition());
+                               }
+
+                       }
+
+                       String name = child.getAttribute("name");
+                       specAttrs.put(name, childBuilder.getBeanDefinition());
+                       if (log.isTraceEnabled())
+                               log.debug("Added spec attribute " + name);
+               }
+
+               builder.addPropertyValue("attributes", specAttrs);
+       }
+
+       protected void addAbstractSpecAttributeProperties(
+                       BeanDefinitionBuilder specAttr, Element element) {
+
+               addBooleanProperty("isParameter", specAttr, element);
+               addBooleanProperty("isFrozen", specAttr, element);
+               addBooleanProperty("isHidden", specAttr, element);
+       }
+
+       protected void addValue(BeanDefinitionBuilder specAttr, Element element,
+                       ParserContext parserContext) {
+               Boolean alreadySet = false;
+               if (element.hasAttribute("value")) {
+                       specAttr.addPropertyValue("value", element.getAttribute("value"));
+                       alreadySet = true;
+               }
+
+               if (element.hasAttribute("value-ref")) {
+                       if (alreadySet)
+                               throw new SlcException("Multiple value definition for "
+                                               + specAttr);
+                       specAttr.addPropertyValue("value", new RuntimeBeanReference(element
+                                       .getAttribute("value-ref")));
+               }
+
+               Element valueElem = DomUtils.getChildElementByTagName(element, "value");
+               if (valueElem != null) {
+                       if (alreadySet)
+                               throw new SlcException("Multiple value definition for "
+                                               + specAttr);
+
+                       NodeList valueChildNd = valueElem.getChildNodes();
+
+                       for (int i = 0; i < valueChildNd.getLength(); i++) {
+                               Node node = valueChildNd.item(i);
+                               if (node != null && node instanceof Element) {
+                                       specAttr.addPropertyValue("value", parseBeanReference(
+                                                       (Element) node, parserContext, specAttr));
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       private void addBooleanProperty(String name,
+                       BeanDefinitionBuilder specAttr, Element element) {
+               String bool = element.getAttribute(name);
+               if (StringUtils.hasText(bool))
+                       specAttr.addPropertyValue(name, Boolean.parseBoolean(bool));
+
+       }
+
+       @Override
+       protected Class<DefaultExecutionSpec> getBeanClass(Element element) {
+               return DefaultExecutionSpec.class;
+       }
+
+       // parse nested bean definition
+       private Object parseBeanReference(Element element,
+                       ParserContext parserContext, BeanDefinitionBuilder builder) {
+               return parserContext.getDelegate().parsePropertySubElement(element,
+                               builder.getBeanDefinition());
+       }
+
+       protected boolean shouldGenerateIdAsFallback() {
+               return false;
+       }
+
+}
index 4534138ec0da699d43741b5c5a734f3856357a9f..fcb5b93e148a889f42a9b4d4006de2534bc46b9f 100644 (file)
 <?xml version="1.0" encoding="UTF-8"?>
 <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-       xmlns:beans="http://www.springframework.org/schema/beans"
+       xmlns:flow="http://www.argeo.org/schema/slc-flow" xmlns:beans="http://www.springframework.org/schema/beans"
        targetNamespace="http://www.argeo.org/schema/slc-flow"
        elementFormDefault="qualified" attributeFormDefault="unqualified">
 
        <xsd:import namespace="http://www.springframework.org/schema/beans" />
 
-
        <xsd:element name="flow">
                <xsd:complexType>
                        <xsd:complexContent>
                                <xsd:extension base="beans:identifiedType">
                                        <xsd:sequence>
-                                               <xsd:any minOccurs="1" maxOccurs="unbounded" />
+                                               <xsd:sequence>
+                                                       <xsd:element name="arg" minOccurs="0" maxOccurs="unbounded"
+                                                               type="flow:argType" />
+                                               </xsd:sequence>
+                                               <xsd:sequence>
+                                                       <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                                                               <xsd:element ref="beans:bean" />
+                                                               <xsd:element ref="beans:ref" />
+                                                       </xsd:choice>
+                                                       <!--
+                                                               <xsd:any namespace="##other" processContents="strict"
+                                                               minOccurs="0" maxOccurs="unbounded" />
+                                                       -->
+                                               </xsd:sequence>
                                        </xsd:sequence>
                                        <xsd:attribute name="path" type="xsd:string" />
+                                       <xsd:attribute name="spec" type="xsd:string" />
+                                       <xsd:attribute name="parent" type="xsd:string" />
+                                       <xsd:attribute name="abstract" type="xsd:boolean"
+                                               default="false" />
+                               </xsd:extension>
+                       </xsd:complexContent>
+               </xsd:complexType>
+       </xsd:element>
+
+       <xsd:element name="spec">
+               <xsd:complexType>
+                       <xsd:complexContent>
+                               <xsd:extension base="beans:identifiedType">
+                                       <xsd:sequence>
+                                               <xsd:choice minOccurs="0" maxOccurs="unbounded">
+                                                       <xsd:element name="primitive" type="flow:primitiveSpecAttributeType"
+                                                               minOccurs="0" maxOccurs="unbounded" />
+                                                       <xsd:element name="ref" type="flow:refSpecAttributeType"
+                                                               minOccurs="0" maxOccurs="unbounded" />
+                                               </xsd:choice>
+                                       </xsd:sequence>
                                </xsd:extension>
                        </xsd:complexContent>
                </xsd:complexType>
        </xsd:element>
 
+       <xsd:complexType name="specAttributeType">
+               <xsd:choice>
+                       <xsd:element name="value" minOccurs="0" maxOccurs="1">
+                               <xsd:complexType>
+                                       <xsd:choice>
+                                               <xsd:any minOccurs="1" maxOccurs="1" />
+                                       </xsd:choice>
+                               </xsd:complexType>
+                       </xsd:element>
+               </xsd:choice>
+               <xsd:attribute name="name" use="required" type="xsd:string" />
+               <xsd:attribute name="value" use="optional" type="xsd:string" />
+               <xsd:attribute name="value-ref" use="optional" type="xsd:string" />
+               <xsd:attribute name="isParameter" use="optional" type="xsd:boolean"
+                       default="false" />
+               <xsd:attribute name="isFrozen" use="optional" type="xsd:boolean"
+                       default="false" />
+               <xsd:attribute name="isHidden" use="optional" type="xsd:boolean"
+                       default="false" />
+       </xsd:complexType>
+
+       <xsd:complexType name="primitiveSpecAttributeType">
+               <xsd:complexContent>
+                       <xsd:extension base="flow:specAttributeType">
+                               <xsd:attribute name="type" default="string">
+                                       <xsd:simpleType>
+                                               <xsd:restriction base="xsd:string">
+                                                       <xsd:enumeration value="string" />
+                                                       <xsd:enumeration value="integer" />
+                                                       <xsd:enumeration value="long" />
+                                                       <xsd:enumeration value="float" />
+                                                       <xsd:enumeration value="double" />
+                                                       <xsd:enumeration value="boolean" />
+                                               </xsd:restriction>
+                                       </xsd:simpleType>
+                               </xsd:attribute>
+                       </xsd:extension>
+               </xsd:complexContent>
+       </xsd:complexType>
+
+       <xsd:complexType name="refSpecAttributeType">
+               <xsd:complexContent>
+                       <xsd:extension base="flow:specAttributeType">
+                               <xsd:choice>
+                                       <xsd:element name="choices" minOccurs="0" maxOccurs="1">
+                                               <xsd:complexType>
+                                                       <xsd:choice>
+                                                               <xsd:element name="choice" minOccurs="0" maxOccurs="unbounded"
+                                                                       type="flow:refChoiceType" />
+                                                       </xsd:choice>
+                                               </xsd:complexType>
+                                       </xsd:element>
+                               </xsd:choice>
+                               <xsd:attribute name="targetClass" use="required" type="xsd:string" />
+                       </xsd:extension>
+               </xsd:complexContent>
+       </xsd:complexType>
+
+       <xsd:complexType name="refChoiceType">
+               <xsd:attribute name="name" use="required" type="xsd:string" />
+               <xsd:attribute name="description" use="optional" type="xsd:string" />
+       </xsd:complexType>
+
+       <xsd:complexType name="argType">
+               <xsd:attribute name="name" use="required" type="xsd:string" />
+               <xsd:attribute name="value" type="xsd:string" />
+               <xsd:attribute name="ref" type="xsd:string" />
+       </xsd:complexType>
+
        <xsd:attribute name="as-flow" type="xsd:string" />
 
 </xsd:schema>
\ No newline at end of file