001 /*
002 * Copyright 2011 The Kuali Foundation.
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.kfs.sys.spring.datadictionary;
017
018 import java.util.ArrayList;
019 import java.util.HashMap;
020 import java.util.List;
021 import java.util.Map;
022
023 import org.apache.commons.lang.StringUtils;
024 import org.kuali.rice.kns.datadictionary.DocumentCollectionPath;
025 import org.kuali.rice.kns.datadictionary.DocumentValuePathGroup;
026 import org.kuali.rice.kns.datadictionary.RoutingAttribute;
027 import org.kuali.rice.kns.datadictionary.RoutingTypeDefinition;
028 import org.kuali.rice.kns.datadictionary.SearchingAttribute;
029 import org.kuali.rice.kns.datadictionary.SearchingTypeDefinition;
030 import org.kuali.rice.kns.datadictionary.WorkflowAttributeMetadata;
031 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
032 import org.springframework.beans.factory.xml.ParserContext;
033 import org.w3c.dom.Element;
034 import org.w3c.dom.Node;
035 import org.w3c.dom.NodeList;
036
037 public class WorkflowAttributesBeanDefinitionParser extends KualiBeanDefinitionParserBase {
038 private static final String SEARCHING_ATTRIBUTE = "searchingAttribute";
039 private static final String ROUTING_ATTRIBUTE = "routingAttribute";
040 private static final String DOCUMENT_VALUE_ATTRIBUTE = "documentValue";
041 private static final String SEARCHING_TYPES_ELEMENT = "searchingType";
042 private static final String ROUTING_TYPES_ELEMENT = "routingType";
043
044 @Override
045 protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder bean) {
046 handleAbstractAttribute(element, bean);
047
048 parseChildElements(element, bean);
049 }
050
051 protected void parseChildElements(Element workflowAttributeElement, BeanDefinitionBuilder bean) {
052 NodeList children = workflowAttributeElement.getChildNodes();
053 List<SearchingTypeDefinition> searchingAttributesMap = parseSearchableAttributes(children);
054 bean.addPropertyValue("searchingTypeDefinitions", searchingAttributesMap);
055
056 Map<String, RoutingTypeDefinition> routingTypesMap = parseRoutingTypes(children);
057 bean.addPropertyValue("routingTypeDefinitions", routingTypesMap);
058 }
059
060 protected List<SearchingTypeDefinition> parseSearchableAttributes(NodeList workflowAttributesChildren) {
061 List<SearchingTypeDefinition> searchingAttributesMap = new ArrayList<SearchingTypeDefinition>();
062 for (int i = 0; i < workflowAttributesChildren.getLength(); i++) {
063 Node workflowAttributesChild = workflowAttributesChildren.item(i);
064 if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) {
065 if (((Element) workflowAttributesChild).getLocalName().equals(SEARCHING_TYPES_ELEMENT)) {
066
067 SearchingTypeDefinition searchingTypeDefinition = parseSearchingTypes(workflowAttributesChild.getChildNodes());
068
069 searchingAttributesMap.add(searchingTypeDefinition);
070 }
071 }
072 }
073 return searchingAttributesMap;
074 }
075
076 protected List<Element> extractWorkflowAttributeElements(NodeList nodes, String attributeElementName) {
077 List<Element> results = new ArrayList<Element>();
078
079 for (int i = 0; i < nodes.getLength(); i++) {
080 Node node = nodes.item(i);
081 if (node.getNodeType() == Node.ELEMENT_NODE) {
082 if (StringUtils.isEmpty(attributeElementName) || ((Element) node).getLocalName().equals(attributeElementName)) {
083 results.add((Element) node);
084 }
085 }
086 }
087 return results;
088 }
089
090 protected SearchingTypeDefinition parseSearchingTypes(NodeList workflowAttributesChildren) {
091 SearchingTypeDefinition searchingTypeDefinition = new SearchingTypeDefinition();
092
093 for (int i = 0; i < workflowAttributesChildren.getLength(); i++) {
094 Node workflowAttributesChild = workflowAttributesChildren.item(i);
095 if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) {
096 if (((Element) workflowAttributesChild).getLocalName().equals(SEARCHING_ATTRIBUTE)){
097 searchingTypeDefinition.setSearchingAttribute((SearchingAttribute)parseAttributeDefinition((Element) workflowAttributesChild));
098 }else if(((Element) workflowAttributesChild).getLocalName().equals(DOCUMENT_VALUE_ATTRIBUTE)){
099 if(searchingTypeDefinition.getDocumentValues() == null){
100 searchingTypeDefinition.setDocumentValues(new ArrayList<String>());
101 }
102 searchingTypeDefinition.getDocumentValues().addAll(parseDocumentValueAttributeDefinition((Element) workflowAttributesChild));
103 }
104 }
105 }
106
107 return searchingTypeDefinition;
108 }
109 protected WorkflowAttributeMetadata parseAttributeDefinition(Element workflowAttributeDefinitionElement) {
110 WorkflowAttributeMetadata workflowAttributeMetadata = null;
111 if(workflowAttributeDefinitionElement.getLocalName().equals(SEARCHING_ATTRIBUTE)){
112 return parseSearchingAttribute(workflowAttributeDefinitionElement);
113 }else if(workflowAttributeDefinitionElement.getLocalName().equals(ROUTING_ATTRIBUTE)){
114 return parseRoutingAttribute(workflowAttributeDefinitionElement);
115 }
116 return workflowAttributeMetadata;
117 }
118
119
120 protected WorkflowAttributeMetadata parseSearchingAttribute(Element workflowAttributeDefinitionElement) {
121 SearchingAttribute workflowAttributeMetadata = new SearchingAttribute();
122
123 String businessObjectClassName = workflowAttributeDefinitionElement.getAttribute("businessObjectClassName");
124 if (StringUtils.isNotBlank(businessObjectClassName)) {
125 try {
126 Class.forName(businessObjectClassName);
127 workflowAttributeMetadata.setBusinessObjectClassName(businessObjectClassName);
128 }
129 catch (ClassNotFoundException e) {
130 throw new RuntimeException("Unable to find class of name " + businessObjectClassName + " when parsing workflowAttribute");
131 }
132 }
133 String attributeName = workflowAttributeDefinitionElement.getAttribute("attributeName");
134 if (StringUtils.isNotBlank(attributeName)) {
135 workflowAttributeMetadata.setAttributeName(attributeName);
136 }
137
138 return workflowAttributeMetadata;
139 }
140
141 protected WorkflowAttributeMetadata parseRoutingAttribute(Element workflowAttributeDefinitionElement) {
142 RoutingAttribute workflowAttributeMetadata = new RoutingAttribute();
143
144 String attributeName = workflowAttributeDefinitionElement.getAttribute("qualificationAttributeName");
145 if (StringUtils.isNotBlank(attributeName)) {
146 workflowAttributeMetadata.setQualificationAttributeName(attributeName);
147 }
148
149 return workflowAttributeMetadata;
150 }
151
152 protected List<String> parseDocumentValueAttributeDefinition(Element workflowAttributeDefinitionElement) {
153
154 List<String>paths = new ArrayList<String>();
155 paths.add(workflowAttributeDefinitionElement.getAttribute("path"));
156
157 return paths;
158 }
159 protected Map<String, RoutingTypeDefinition> parseRoutingTypes(NodeList workflowAttributesChildren) {
160 Map<String, RoutingTypeDefinition> routingTypesMap = new HashMap<String, RoutingTypeDefinition>();
161
162 for (int i = 0; i < workflowAttributesChildren.getLength(); i++) {
163 Node workflowAttributesChild = workflowAttributesChildren.item(i);
164 if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) {
165 if (((Element) workflowAttributesChild).getLocalName().equals(ROUTING_TYPES_ELEMENT)) {
166 RoutingTypeDefinition routingTypeDefinition = new RoutingTypeDefinition();
167 Element routingTypeElement = (Element) workflowAttributesChild;
168
169 String name = routingTypeElement.getAttribute("nodeName");
170
171 List<RoutingAttribute> routingAttributes = new ArrayList<RoutingAttribute>();
172 List<DocumentValuePathGroup> documentValuePathGroups = new ArrayList<DocumentValuePathGroup>();
173 List<Element> workflowAttributeList = extractWorkflowAttributeElements(routingTypeElement.getChildNodes(), "");
174 for (int j = 0; j < workflowAttributeList.size(); j++) {
175 Element workflowAttributeDefinitionElement = (Element) workflowAttributeList.get(j);
176 if(workflowAttributeDefinitionElement.getLocalName().equals("routingAttributes")){
177 List<Element> routingAttributeList = extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "routingAttribute");
178 for(Element routingAttribute:routingAttributeList){
179 routingAttributes.add((RoutingAttribute)parseAttributeDefinition(routingAttribute));
180 }
181 }
182 else if(workflowAttributeDefinitionElement.getLocalName().equals("documentValuePathGroup")){
183 documentValuePathGroups.add(parseDocumentValuesPathGroup(workflowAttributeDefinitionElement));
184 }
185 }
186 routingTypeDefinition.setDocumentValuePathGroups(documentValuePathGroups);
187 routingTypeDefinition.setRoutingAttributes(routingAttributes);
188 routingTypesMap.put(name, routingTypeDefinition);
189 }
190 }
191 }
192
193 return routingTypesMap;
194 }
195
196 protected DocumentCollectionPath parseDocumentCollectionPath(Element workflowAttributeDefinitionElement) {
197 DocumentCollectionPath documentCollectionPath = new DocumentCollectionPath();
198 for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentCollectionPath")){
199 documentCollectionPath.setNestedCollection(parseDocumentCollectionPath(element));
200 }
201 List<String>paths = new ArrayList<String>();
202 for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentValue")){
203 paths.addAll(parseDocumentValueAttributeDefinition(element));
204 }
205 documentCollectionPath.setDocumentValues(paths);
206
207 String collectionName = workflowAttributeDefinitionElement.getAttribute("path");
208 documentCollectionPath.setCollectionPath(collectionName);
209
210 return documentCollectionPath;
211 }
212 protected DocumentValuePathGroup parseDocumentValuesPathGroup(Element workflowAttributeDefinitionElement) {
213 DocumentValuePathGroup documentValuePathGroup = new DocumentValuePathGroup();
214
215 List<Element> documentCollectionPathElements = extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentCollectionPath");
216 if( documentCollectionPathElements.size() > 0){
217 documentValuePathGroup.setDocumentCollectionPath(parseDocumentCollectionPath(documentCollectionPathElements.get(0)));
218 }
219 List<String>paths = new ArrayList<String>();
220 for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentValue")){
221 paths.addAll(parseDocumentValueAttributeDefinition(element));
222 }
223 documentValuePathGroup.setDocumentValues(paths);
224
225 return documentValuePathGroup;
226 }
227
228 @Override
229 protected String getBaseBeanTypeParent(Element element) {
230 return "WorkflowAttributes";
231 }
232
233 }