--- /dev/null
+#Tue Jan 12 18:56:33 CET 2010
+eclipse.preferences.version=1
+pluginProject.equinox=false
+pluginProject.extensions=false
<name>SLC Core</name>
<description>Basic implementations of SLC Specifications</description>
<build>
+ <outputDirectory>bin</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
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) {
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;
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
}
// 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());
public void init() {
registerBeanDefinitionParser("flow", new FlowBeanDefinitionParser());
+ registerBeanDefinitionParser("spec", new SpecBeanDefinitionParser());
registerBeanDefinitionDecoratorForAttribute("as-flow",
new AsFlowDecorator());
}
--- /dev/null
+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;
+ }
+
+}
<?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