<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
+ <classpathentry excluding="src/main/java/|src/main/resources/|src/test/java/|src/test/resources/" including="META-INF/" kind="src" path=""/>
<classpathentry kind="src" path="src/main/resources"/>
- <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
- <classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="src" path="src/test/java"/>
+ <classpathentry kind="src" path="src/test/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
<classpathentry kind="output" path="bin"/>
-#Tue Jan 12 18:56:33 CET 2010
+#Fri Jan 15 10:53:00 CET 2010
eclipse.preferences.version=1
pluginProject.equinox=false
pluginProject.extensions=false
+resolve.requirebundle=false
--- /dev/null
+additional.bundles = com.springsource.slf4j.api,\
+ com.springsource.slf4j.log4j,\
+ com.springsource.org.apache.log4j,\
+ com.springsource.slf4j.org.apache.commons.logging,\
+ com.springsource.org.aopalliance,\
+ com.springsource.org.aspectj.weaver,\
+ com.springsource.net.sf.cglib
+source.. = src/main/java/,\
+ src/main/resources/,\
+ src/test/java/,\
+ src/test/resources/
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;
String spec = element.getAttribute("spec");
if (StringUtils.hasText(spec))
- builder.getRawBeanDefinition().getConstructorArgumentValues()
+ builder.getBeanDefinition().getConstructorArgumentValues()
.addGenericArgumentValue(new RuntimeBeanReference(spec));
String abstrac = element.getAttribute("abstract");
for (int i = 0; i < nodeList.getLength(); i++) {
Node node = nodeList.item(i);
if (node instanceof Element) {
- if ("arg".equals(node.getLocalName()))
+ if (DomUtils.nodeNameEquals(node, "arg"))
argsElems.add((Element) node);
else
execElems.add((Element) node);
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")));
+ Object value = NamespaceUtils.parseValue(argElem,
+ parserContext, builder.getBeanDefinition(), null);
+ if (value != null)
+ args.put(argElem.getAttribute("name"), value);
else
throw new SlcException("No value defined.");
}
- builder.getRawBeanDefinition().getConstructorArgumentValues()
+ builder.getBeanDefinition().getConstructorArgumentValues()
.addGenericArgumentValue(args);
}
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)) {
+ if (DomUtils.nodeNameEquals(child, "bean")
+ || DomUtils.nodeNameEquals(child, "ref")) {
+ // Object target = parseBeanReference((Element) child,
+ // parserContext, builder);
+ executables.add(NamespaceUtils.parseBeanReference(child,
+ parserContext, builder.getBeanDefinition()));
+ } else if (DomUtils.nodeNameEquals(child, "flow")) {
throw new SlcException(
- "Nested flows are not yet supported use a standard ref to another flow.");
+ "Nested flows are not yet supported, use a standard ref to another flow.");
} else {
throw new SlcException("Unsupported child '" + name + "'");
}
}
// parse nested bean definition
- private Object parseBeanReference(Element element,
- ParserContext parserContext, BeanDefinitionBuilder builder) {
- return parserContext.getDelegate().parsePropertySubElement(element,
- builder.getBeanDefinition());
- }
+ // private Object parseBeanReference(Element element,
+ // ParserContext parserContext, BeanDefinitionBuilder builder) {
+ // return parserContext.getDelegate().parsePropertySubElement(element,
+ // builder.getBeanDefinition());
+ // }
protected boolean shouldGenerateIdAsFallback() {
return true;
registerBeanDefinitionParser("spec", new SpecBeanDefinitionParser());
registerBeanDefinitionDecoratorForAttribute("as-flow",
new AsFlowDecorator());
+ registerBeanDefinitionParser("param", new ParamDecorator());
}
}
--- /dev/null
+package org.argeo.slc.core.execution.xml;
+
+import org.argeo.slc.SlcException;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.RuntimeBeanReference;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.xml.DomUtils;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+/**
+ * Utilities to simplify common tasks when interpreting a custom namespace and
+ * converting it into bean definitions.
+ */
+public class NamespaceUtils {
+ /**
+ * Returns the value defined either: directly by the the 'value' attribute,
+ * as reference by the 'ref' attribute or as a nested bean.
+ */
+ public static Object parseValue(Element element,
+ ParserContext parserContext,
+ BeanDefinition containingBeanDefintion, String valueTagName) {
+ Object value = null;
+ if (element.hasAttribute("value")) {
+ value = element.getAttribute("value");
+ }
+
+ if (element.hasAttribute("ref")) {
+ if (value != null)
+ throw new SlcException("Multiple value definition for "
+ + element);
+ value = new RuntimeBeanReference(element.getAttribute("ref"));
+ }
+
+ Element uniqueSubElem = null;
+ if (valueTagName != null) {
+ Element valueElem = DomUtils.getChildElementByTagName(element,
+ valueTagName);
+ if (valueElem != null) {
+ uniqueSubElem = findUniqueSubElement(valueElem);
+ if (uniqueSubElem == null)
+ throw new SlcException("No subelement found under "
+ + valueElem);
+ }
+ } else {// no intermediary tag
+ uniqueSubElem = findUniqueSubElement(element);
+ }
+
+ if (uniqueSubElem != null) {
+ if (value != null)
+ throw new SlcException("Multiple value definition for "
+ + element);
+ value = parseBeanReference(uniqueSubElem, parserContext,
+ containingBeanDefintion);
+ }
+ return value;
+ }
+
+ public static Element findUniqueSubElement(Element element) {
+ NodeList childNodes = element.getChildNodes();
+
+ Element uniqueSubElem = null;
+ for (int i = 0; i < childNodes.getLength(); i++) {
+ Node node = childNodes.item(i);
+ if (node != null && node instanceof Element) {
+ if (uniqueSubElem == null)
+ uniqueSubElem = (Element) node;
+ else
+ throw new SlcException(
+ "There are more than one sub element under "
+ + element);
+ }
+ }
+ return uniqueSubElem;
+ }
+
+ public static Object parseBeanReference(Element element,
+ ParserContext parserContext, BeanDefinition beanDefinition) {
+ return parserContext.getDelegate().parsePropertySubElement(element,
+ beanDefinition);
+ }
+
+}
--- /dev/null
+package org.argeo.slc.core.execution.xml;
+
+import org.argeo.slc.core.execution.ParameterRef;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.ParserContext;
+import org.springframework.util.StringUtils;
+import org.w3c.dom.Element;
+
+public class ParamDecorator extends AbstractSingleBeanDefinitionParser {
+
+ // public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder
+ // bean,
+ // ParserContext ctx) {
+ // String paramName = ((Element) node).getAttribute("name");
+ // String propertyName = ((Element) node.getParentNode())
+ // .getAttribute("name");
+ // BeanDefinitionBuilder parameterRef = BeanDefinitionBuilder
+ // .genericBeanDefinition(ParameterRef.class);
+ // parameterRef.addPropertyReference("instantiationManager",
+ // "instantiationManager");
+ // parameterRef.addConstructorArgValue(paramName);
+ // bean.getBeanDefinition().getPropertyValues().addPropertyValue(
+ // propertyName, parameterRef.getBeanDefinition());
+ // return bean;
+ // }
+
+ @Override
+ protected void doParse(Element element, ParserContext parserContext,
+ BeanDefinitionBuilder builder) {
+ String paramName = element.getAttribute("name");
+
+ String instantationManagerRef = element
+ .getAttribute("instantiationManager");
+ if (!StringUtils.hasText(instantationManagerRef))
+ instantationManagerRef = "instantiationManager";
+ builder.addPropertyReference("instantiationManager",
+ instantationManagerRef);
+ builder.addConstructorArgValue(paramName);
+ }
+
+ @Override
+ protected Class<ParameterRef> getBeanClass(Element element) {
+ return ParameterRef.class;
+ }
+}
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.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
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
@Override
protected void doParse(Element element, ParserContext parserContext,
BeanDefinitionBuilder builder) {
- ManagedMap specAttrs = new ManagedMap();
+ ManagedMap attributes = 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);
+ addCommonProperties(child, parserContext, childBuilder);
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);
+ putInAttributes(attributes, child,
+ childBuilder.getBeanDefinition(), "primitive");
}
// Refs
.getChildElementsByTagName(element, "ref")) {
BeanDefinitionBuilder childBuilder = BeanDefinitionBuilder
.genericBeanDefinition(RefSpecAttribute.class);
- addAbstractSpecAttributeProperties(childBuilder, child);
- addValue(childBuilder, child, parserContext);
+ addCommonProperties(child, parserContext, childBuilder);
String targetClassName = child.getAttribute("targetClass");
if (StringUtils.hasText(targetClassName))
}
- String name = child.getAttribute("name");
- specAttrs.put(name, childBuilder.getBeanDefinition());
- if (log.isTraceEnabled())
- log.debug("Added spec attribute " + name);
+ putInAttributes(attributes, child,
+ childBuilder.getBeanDefinition(), "ref");
}
- builder.addPropertyValue("attributes", specAttrs);
+ builder.addPropertyValue("attributes", attributes);
}
- protected void addAbstractSpecAttributeProperties(
- BeanDefinitionBuilder specAttr, Element element) {
-
+ protected void addCommonProperties(Element element,
+ ParserContext parserContext, BeanDefinitionBuilder specAttr) {
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;
- }
+ Object value = NamespaceUtils.parseValue(element, parserContext,
+ specAttr.getBeanDefinition(), "value");
+ if (value != null)
+ specAttr.addPropertyValue("value", value);
- 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();
+ @SuppressWarnings("unchecked")
+ protected void putInAttributes(ManagedMap attributes, Element child,
+ BeanDefinition beanDefinition, String nature) {
+ String name = child.getAttribute("name");
+ attributes.put(name, beanDefinition);
+ if (log.isTraceEnabled())
+ log.debug("Added " + nature + " attribute " + name);
- 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,
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;
}
</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="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"
</xsd:complexType>
<xsd:complexType name="argType">
+ <xsd:choice minOccurs="0" maxOccurs="1">
+ <xsd:element ref="beans:bean" />
+ <xsd:element ref="beans:ref" />
+ </xsd:choice>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="value" type="xsd:string" />
<xsd:attribute name="ref" type="xsd:string" />
<xsd:attribute name="as-flow" type="xsd:string" />
+ <xsd:element name="param">
+ <xsd:complexType>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ <xsd:attribute name="instantiationManager" type="xsd:string"
+ use="optional" default="instantiationManager" />
+ </xsd:complexType>
+ </xsd:element>
+
</xsd:schema>
\ No newline at end of file
--- /dev/null
+package org.argeo.slc.core.execution.xml;
+
+import org.argeo.slc.core.execution.AbstractExecutionFlowTestCase;
+import org.argeo.slc.execution.ExecutionFlow;
+import org.springframework.context.ConfigurableApplicationContext;
+
+public class FlowNamespaceTest extends AbstractExecutionFlowTestCase {
+ public void testCanonical() throws Exception {
+ ConfigurableApplicationContext applicationContext = createApplicationContext("canonic-ns.xml");
+ ((ExecutionFlow) applicationContext.getBean("canonic-ns.001")).run();
+ ((ExecutionFlow) applicationContext.getBean("canonic-ns.002")).run();
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"\r
+ xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <bean id="canonic-ns.001" parent="canonic-ns.flowTemplate">\r
+ <description>Canonic 001</description>\r
+ <constructor-arg>\r
+ <map>\r
+ <entry key="parameterAtInstantiation" value="1" />\r
+ </map>\r
+ </constructor-arg>\r
+ </bean>\r
+</beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:p="http://www.springframework.org/schema/p"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <flow id="canonic-ns.002" parent="canonic-ns.flowTemplate">\r
+ <arg name="parameterAtInstantiation" value="2" />\r
+ <arg name="displayWithoutControl" value="102" />\r
+ <arg name="displayWithControl" value="202" />\r
+ <arg name="hide" value="202" />\r
+ <arg name="refWithoutValue">\r
+ <beans:bean id="testDataOk" p:expected="tata" p:reached="tata"\r
+ class="org.argeo.slc.core.test.BasicTestData" />\r
+ </arg>\r
+ </flow>\r
+</beans:beans>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans:beans xmlns="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <beans:import resource="classpath:org/argeo/slc/core/execution/spring.xml" />\r
+ <beans:import resource="classpath:/org/argeo/slc/core/test/spring.xml" />\r
+\r
+ <beans:import resource="canonic-ns-001.xml" />\r
+ <beans:import resource="canonic-ns-002.xml" />\r
+ <beans:import resource="tests.xml" />\r
+\r
+ <spec id="canonic-ns.spec">\r
+ <primitive name="parameterAtInstantiation" isParameter="true"\r
+ type="integer" />\r
+ <primitive name="displayWithoutControl" value="100"\r
+ isParameter="true" type="integer" isFrozen="true" />\r
+ <primitive name="displayWithControl" value="200"\r
+ isParameter="true" type="integer" />\r
+ <primitive name="hide" value="300" isParameter="true" type="integer"\r
+ isHidden="true" />\r
+ <ref name="refWithValue" targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ isParameter="true" ref="testDataNok" />\r
+ <ref name="refWithoutValue" targetClass="org.argeo.slc.core.test.BasicTestData" />\r
+ <ref name="refWithoutValueFrozen" targetClass="org.argeo.slc.core.test.BasicTestData"\r
+ isParameter="true" isFrozen="true">\r
+ <value>\r
+ <beans:bean class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="tata" />\r
+ </beans:bean>\r
+ </value>\r
+ </ref>\r
+ </spec>\r
+\r
+ <flow id="canonic-ns.flowTemplate" abstract="true" spec="canonic-ns.spec"\r
+ path="/path">\r
+ <beans:bean parent="task.echo"\r
+ p:message="Canonical: displayWithControl=@{displayWithControl}, displayWithoutControl=@{displayWithoutControl}, hide=@{hide}"\r
+ scope="execution">\r
+ <aop:scoped-proxy />\r
+ </beans:bean>\r
+ <beans:ref bean="testRun" />\r
+ </flow>\r
+\r
+ <beans:bean id="testDataOk" class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="tata" />\r
+ </beans:bean>\r
+\r
+ <beans:bean id="testDataNok" class="org.argeo.slc.core.test.BasicTestData">\r
+ <aop:scoped-proxy />\r
+ <beans:property name="expected" value="tata" />\r
+ <beans:property name="reached" value="toto" />\r
+ </beans:bean>\r
+</beans:beans>
\ No newline at end of file
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<beans xmlns="http://www.springframework.org/schema/beans"\r
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:flow="http://www.argeo.org/schema/slc-flow"\r
+ xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"\r
+ xsi:schemaLocation="\r
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd\r
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd\r
+ http://www.argeo.org/schema/slc-flow http://www.argeo.org/schema/slc-flow-0.12.xsd">\r
+\r
+ <bean id="testRun" class="org.argeo.slc.core.test.SimpleTestRun">\r
+ <property name="testDefinition">\r
+ <bean class="org.argeo.slc.core.test.BasicTestDefinition" />\r
+ </property>\r
+ <property name="testData">\r
+ <flow:param name="refWithValue" />\r
+ </property>\r
+ <!-- <property name="testData">-->\r
+ <!-- <bean parent="parameterRef">-->\r
+ <!-- <constructor-arg value="refWithValue" />-->\r
+ <!-- </bean>-->\r
+ <!-- </property>-->\r
+ <property name="testResult">\r
+ <bean parent="slcDefault.test.basicTreeTestResult" scope="execution">\r
+ <property name="attributes">\r
+ <map>\r
+ <entry key="displayWithControl" value="@{displayWithControl}" />\r
+ </map>\r
+ </property>\r
+ <aop:scoped-proxy />\r
+ </bean>\r
+ </property>\r
+ </bean>\r
+</beans>
\ No newline at end of file