]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/xml/FlowBeanDefinitionParser.java
SLC Flow Spring XML format v1.2
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / xml / FlowBeanDefinitionParser.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.argeo.slc.core.execution.xml;
17
18 import java.util.ArrayList;
19 import java.util.List;
20
21 import org.apache.commons.logging.Log;
22 import org.apache.commons.logging.LogFactory;
23 import org.argeo.slc.SlcException;
24 import org.argeo.slc.core.execution.DefaultExecutionFlow;
25 import org.argeo.slc.execution.ExecutionFlow;
26 import org.springframework.beans.factory.BeanDefinitionStoreException;
27 import org.springframework.beans.factory.config.RuntimeBeanReference;
28 import org.springframework.beans.factory.support.AbstractBeanDefinition;
29 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
30 import org.springframework.beans.factory.support.ManagedList;
31 import org.springframework.beans.factory.support.ManagedMap;
32 import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
33 import org.springframework.beans.factory.xml.ParserContext;
34 import org.springframework.util.StringUtils;
35 import org.springframework.util.xml.DomUtils;
36 import org.w3c.dom.Element;
37 import org.w3c.dom.Node;
38 import org.w3c.dom.NodeList;
39
40 /** Interprets the <flow:flow> tag */
41 public class FlowBeanDefinitionParser extends
42 AbstractSingleBeanDefinitionParser {
43 private Log log = LogFactory.getLog(FlowBeanDefinitionParser.class);
44
45 @SuppressWarnings("unchecked")
46 @Override
47 protected void doParse(Element element, ParserContext parserContext,
48 BeanDefinitionBuilder builder) {
49 String path = element.getAttribute("path");
50 if (StringUtils.hasText(path))
51 log.warn("The 'path' attribute is not used anymore to build flows");
52
53 String spec = element.getAttribute("spec");
54 if (StringUtils.hasText(spec))
55 builder.getBeanDefinition().getConstructorArgumentValues()
56 .addGenericArgumentValue(new RuntimeBeanReference(spec));
57
58 String abstrac = element.getAttribute("abstract");
59 if (StringUtils.hasText(abstrac))
60 builder.setAbstract(Boolean.parseBoolean(abstrac));
61
62 String parent = element.getAttribute("parent");
63 if (StringUtils.hasText(parent))
64 builder.setParentName(parent);
65
66 builder.getBeanDefinition().setDescription(
67 DomUtils.getChildElementValueByTagName(element, "description"));
68
69 List<Element> argsElems = new ArrayList<Element>();
70 List<Element> execElems = new ArrayList<Element>();
71 List<Element> specElems = new ArrayList<Element>();
72 NodeList nodeList = element.getChildNodes();
73 for (int i = 0; i < nodeList.getLength(); i++) {
74 Node node = nodeList.item(i);
75 if (node instanceof Element) {
76 if (DomUtils.nodeNameEquals(node, "arg"))
77 argsElems.add((Element) node);
78 else if (DomUtils.nodeNameEquals(node, "spec"))
79 specElems.add((Element) node);
80 else if (!DomUtils.nodeNameEquals(node, "description"))
81 execElems.add((Element) node);
82 }
83 }
84
85 // Arguments
86 if (argsElems.size() != 0) {
87 ManagedMap args = new ManagedMap(argsElems.size());
88 for (Element argElem : argsElems) {
89 Object value = NamespaceUtils.parseValue(argElem,
90 parserContext, builder.getBeanDefinition(), null);
91 if (value != null)
92 args.put(argElem.getAttribute("name"), value);
93 else
94 throw new SlcException("No value defined.");
95 }
96 builder.getBeanDefinition().getConstructorArgumentValues()
97 .addGenericArgumentValue(args);
98 }
99
100 // Execution specs
101 if (StringUtils.hasText(spec) && specElems.size() != 0)
102 throw new SlcException("A flow cannot have multiple specs");
103 if (specElems.size() == 1) {
104 Object specObj = NamespaceUtils.parseBeanOrReference(
105 specElems.get(0), parserContext,
106 builder.getBeanDefinition());
107 builder.getBeanDefinition().getConstructorArgumentValues()
108 .addGenericArgumentValue(specObj);
109 } else if (specElems.size() > 1)
110 throw new SlcException("A flow cannot have multiple specs");
111
112 // Executables
113 if (execElems.size() != 0) {
114 ManagedList executables = new ManagedList(execElems.size());
115 for (Element child : execElems) {
116 // child validity check is performed in xsd
117 executables.add(NamespaceUtils.parseBeanOrReference(child,
118 parserContext, builder.getBeanDefinition()));
119 }
120 if (executables.size() > 0)
121 builder.addPropertyValue("executables", executables);
122 }
123 }
124
125 @SuppressWarnings("unchecked")
126 @Override
127 protected Class<? extends ExecutionFlow> getBeanClass(Element element) {
128 String clss = element.getAttribute("class");
129 if (StringUtils.hasText(clss))
130 // TODO: check that it actually works
131 try {
132 return (Class<? extends ExecutionFlow>) getClass()
133 .getClassLoader().loadClass(clss);
134 } catch (ClassNotFoundException e) {
135 try {
136 return (Class<? extends ExecutionFlow>) Thread
137 .currentThread().getContextClassLoader()
138 .loadClass(clss);
139 } catch (ClassNotFoundException e1) {
140 throw new SlcException("Cannot load class " + clss, e);
141 }
142 }
143 else
144 return DefaultExecutionFlow.class;
145 }
146
147 // parse nested bean definition
148 // private Object parseBeanReference(Element element,
149 // ParserContext parserContext, BeanDefinitionBuilder builder) {
150 // return parserContext.getDelegate().parsePropertySubElement(element,
151 // builder.getBeanDefinition());
152 // }
153
154 @Override
155 protected String resolveId(Element element,
156 AbstractBeanDefinition definition, ParserContext parserContext)
157 throws BeanDefinitionStoreException {
158 String name = element.getAttribute("name");
159 if (StringUtils.hasText(name)) {
160 return name;
161 } else {
162 return super.resolveId(element, definition, parserContext);
163 }
164 }
165
166 protected boolean shouldGenerateIdAsFallback() {
167 return true;
168 }
169
170 }