]> git.argeo.org Git - gpl/argeo-slc.git/blob - FlowBeanDefinitionParser.java
7d2ab49a1285176902ba1b5521f2ba120ff27aa5
[gpl/argeo-slc.git] / FlowBeanDefinitionParser.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
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 /** Whether the user has already be warned on path attribute usage. */
46 private Boolean warnedAboutPathAttribute = false;
47
48 @Override
49 protected void doParse(Element element, ParserContext parserContext,
50 BeanDefinitionBuilder builder) {
51 String path = element.getAttribute("path");
52 if (StringUtils.hasText(path)) {
53 builder.addPropertyValue("path", path);
54
55 // warns user only once
56 if (!warnedAboutPathAttribute)
57 log.warn("The path=\"\" attribute is deprecated"
58 + " and will be removed in a later release."
59 + " Use <flow:flow name=\"/my/path/flowName\">.");
60 warnedAboutPathAttribute = true;
61 }
62
63 String spec = element.getAttribute("spec");
64 if (StringUtils.hasText(spec))
65 builder.getBeanDefinition().getConstructorArgumentValues()
66 .addGenericArgumentValue(new RuntimeBeanReference(spec));
67
68 String abstrac = element.getAttribute("abstract");
69 if (StringUtils.hasText(abstrac))
70 builder.setAbstract(Boolean.parseBoolean(abstrac));
71
72 String parent = element.getAttribute("parent");
73 if (StringUtils.hasText(parent))
74 builder.setParentName(parent);
75
76 builder.getBeanDefinition().setDescription(
77 DomUtils.getChildElementValueByTagName(element, "description"));
78
79 List<Element> argsElems = new ArrayList<Element>();
80 List<Element> execElems = new ArrayList<Element>();
81 List<Element> specElems = new ArrayList<Element>();
82 NodeList nodeList = element.getChildNodes();
83 for (int i = 0; i < nodeList.getLength(); i++) {
84 Node node = nodeList.item(i);
85 if (node instanceof Element) {
86 if (DomUtils.nodeNameEquals(node, "arg"))
87 argsElems.add((Element) node);
88 else if (DomUtils.nodeNameEquals(node, "spec"))
89 specElems.add((Element) node);
90 else if (!DomUtils.nodeNameEquals(node, "description"))
91 execElems.add((Element) node);
92 }
93 }
94
95 // Arguments
96 if (argsElems.size() != 0) {
97 ManagedMap<String, Object> args = new ManagedMap<String, Object>(
98 argsElems.size());
99 for (Element argElem : argsElems) {
100 Object value = NamespaceUtils.parseValue(argElem,
101 parserContext, builder.getBeanDefinition(), null);
102 if (value != null)
103 args.put(argElem.getAttribute("name"), value);
104 else
105 throw new SlcException("No value defined.");
106 }
107 builder.getBeanDefinition().getConstructorArgumentValues()
108 .addGenericArgumentValue(args);
109 }
110
111 // Execution specs
112 if (StringUtils.hasText(spec) && specElems.size() != 0)
113 throw new SlcException("A flow cannot have multiple specs");
114 if (specElems.size() == 1) {
115 Object specObj = NamespaceUtils.parseBeanOrReference(
116 specElems.get(0), parserContext,
117 builder.getBeanDefinition());
118 builder.getBeanDefinition().getConstructorArgumentValues()
119 .addGenericArgumentValue(specObj);
120 } else if (specElems.size() > 1)
121 throw new SlcException("A flow cannot have multiple specs");
122
123 // Executables
124 if (execElems.size() != 0) {
125 ManagedList<Object> executables = new ManagedList<Object>(
126 execElems.size());
127 for (Element child : execElems) {
128 // child validity check is performed in xsd
129 executables.add(NamespaceUtils.parseBeanOrReference(child,
130 parserContext, builder.getBeanDefinition()));
131 }
132 if (executables.size() > 0)
133 builder.addPropertyValue("executables", executables);
134 }
135 }
136
137 @SuppressWarnings("unchecked")
138 @Override
139 protected Class<? extends ExecutionFlow> getBeanClass(Element element) {
140 String clss = element.getAttribute("class");
141 if (StringUtils.hasText(clss))
142 // TODO: check that it actually works
143 try {
144 return (Class<? extends ExecutionFlow>) getClass()
145 .getClassLoader().loadClass(clss);
146 } catch (ClassNotFoundException e) {
147 try {
148 return (Class<? extends ExecutionFlow>) Thread
149 .currentThread().getContextClassLoader()
150 .loadClass(clss);
151 } catch (ClassNotFoundException e1) {
152 throw new SlcException("Cannot load class " + clss, e);
153 }
154 }
155 else
156 return DefaultExecutionFlow.class;
157 }
158
159 // parse nested bean definition
160 // private Object parseBeanReference(Element element,
161 // ParserContext parserContext, BeanDefinitionBuilder builder) {
162 // return parserContext.getDelegate().parsePropertySubElement(element,
163 // builder.getBeanDefinition());
164 // }
165
166 @Override
167 protected String resolveId(Element element,
168 AbstractBeanDefinition definition, ParserContext parserContext)
169 throws BeanDefinitionStoreException {
170 String name = element.getAttribute("name");
171 if (StringUtils.hasText(name)) {
172 return name;
173 } else {
174 return super.resolveId(element, definition, parserContext);
175 }
176 }
177
178 protected boolean shouldGenerateIdAsFallback() {
179 return true;
180 }
181
182 }