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 }