2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.slc
.core
.execution
.xml
;
18 import java
.util
.ArrayList
;
19 import java
.util
.List
;
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
;
40 /** Interprets the <flow:flow> tag */
41 public class FlowBeanDefinitionParser
extends
42 AbstractSingleBeanDefinitionParser
{
43 private Log log
= LogFactory
.getLog(FlowBeanDefinitionParser
.class);
45 /** Whether the user has already be warned on path attribute usage. */
46 private Boolean warnedAboutPathAttribute
= false;
48 @SuppressWarnings("unchecked")
50 protected void doParse(Element element
, ParserContext parserContext
,
51 BeanDefinitionBuilder builder
) {
52 String path
= element
.getAttribute("path");
53 if (StringUtils
.hasText(path
)) {
54 builder
.addPropertyValue("path", path
);
56 // warns user only once
57 if (!warnedAboutPathAttribute
)
58 log
.warn("The path=\"\" attribute is deprecated"
59 + " and will be removed in a later release."
60 + " Use <flow:flow name=\"/my/path/flowName\">.");
61 warnedAboutPathAttribute
= true;
64 String spec
= element
.getAttribute("spec");
65 if (StringUtils
.hasText(spec
))
66 builder
.getBeanDefinition().getConstructorArgumentValues()
67 .addGenericArgumentValue(new RuntimeBeanReference(spec
));
69 String abstrac
= element
.getAttribute("abstract");
70 if (StringUtils
.hasText(abstrac
))
71 builder
.setAbstract(Boolean
.parseBoolean(abstrac
));
73 String parent
= element
.getAttribute("parent");
74 if (StringUtils
.hasText(parent
))
75 builder
.setParentName(parent
);
77 builder
.getBeanDefinition().setDescription(
78 DomUtils
.getChildElementValueByTagName(element
, "description"));
80 List
<Element
> argsElems
= new ArrayList
<Element
>();
81 List
<Element
> execElems
= new ArrayList
<Element
>();
82 List
<Element
> specElems
= new ArrayList
<Element
>();
83 NodeList nodeList
= element
.getChildNodes();
84 for (int i
= 0; i
< nodeList
.getLength(); i
++) {
85 Node node
= nodeList
.item(i
);
86 if (node
instanceof Element
) {
87 if (DomUtils
.nodeNameEquals(node
, "arg"))
88 argsElems
.add((Element
) node
);
89 else if (DomUtils
.nodeNameEquals(node
, "spec"))
90 specElems
.add((Element
) node
);
91 else if (!DomUtils
.nodeNameEquals(node
, "description"))
92 execElems
.add((Element
) node
);
97 if (argsElems
.size() != 0) {
98 ManagedMap args
= new ManagedMap(argsElems
.size());
99 for (Element argElem
: argsElems
) {
100 Object value
= NamespaceUtils
.parseValue(argElem
,
101 parserContext
, builder
.getBeanDefinition(), null);
103 args
.put(argElem
.getAttribute("name"), value
);
105 throw new SlcException("No value defined.");
107 builder
.getBeanDefinition().getConstructorArgumentValues()
108 .addGenericArgumentValue(args
);
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");
124 if (execElems
.size() != 0) {
125 ManagedList executables
= new ManagedList(execElems
.size());
126 for (Element child
: execElems
) {
127 // child validity check is performed in xsd
128 executables
.add(NamespaceUtils
.parseBeanOrReference(child
,
129 parserContext
, builder
.getBeanDefinition()));
131 if (executables
.size() > 0)
132 builder
.addPropertyValue("executables", executables
);
136 @SuppressWarnings("unchecked")
138 protected Class
<?
extends ExecutionFlow
> getBeanClass(Element element
) {
139 String clss
= element
.getAttribute("class");
140 if (StringUtils
.hasText(clss
))
141 // TODO: check that it actually works
143 return (Class
<?
extends ExecutionFlow
>) getClass()
144 .getClassLoader().loadClass(clss
);
145 } catch (ClassNotFoundException e
) {
147 return (Class
<?
extends ExecutionFlow
>) Thread
148 .currentThread().getContextClassLoader()
150 } catch (ClassNotFoundException e1
) {
151 throw new SlcException("Cannot load class " + clss
, e
);
155 return DefaultExecutionFlow
.class;
158 // parse nested bean definition
159 // private Object parseBeanReference(Element element,
160 // ParserContext parserContext, BeanDefinitionBuilder builder) {
161 // return parserContext.getDelegate().parsePropertySubElement(element,
162 // builder.getBeanDefinition());
166 protected String
resolveId(Element element
,
167 AbstractBeanDefinition definition
, ParserContext parserContext
)
168 throws BeanDefinitionStoreException
{
169 String name
= element
.getAttribute("name");
170 if (StringUtils
.hasText(name
)) {
173 return super.resolveId(element
, definition
, parserContext
);
177 protected boolean shouldGenerateIdAsFallback() {