/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.sys.spring.datadictionary; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.rice.krad.datadictionary.DocumentCollectionPath; import org.kuali.rice.krad.datadictionary.DocumentValuePathGroup; import org.kuali.rice.krad.datadictionary.RoutingAttribute; import org.kuali.rice.krad.datadictionary.RoutingTypeDefinition; import org.kuali.rice.krad.datadictionary.SearchingAttribute; import org.kuali.rice.krad.datadictionary.SearchingTypeDefinition; import org.kuali.rice.krad.datadictionary.WorkflowAttributeMetadata; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class WorkflowAttributesBeanDefinitionParser extends KualiBeanDefinitionParserBase { private static final String SEARCHING_ATTRIBUTE = "searchingAttribute"; private static final String ROUTING_ATTRIBUTE = "routingAttribute"; private static final String DOCUMENT_VALUE_ATTRIBUTE = "documentValue"; private static final String SEARCHING_TYPES_ELEMENT = "searchingType"; private static final String ROUTING_TYPES_ELEMENT = "routingType"; @Override protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder bean) { handleAbstractAttribute(element, bean); parseChildElements(element, bean); } protected void parseChildElements(Element workflowAttributeElement, BeanDefinitionBuilder bean) { NodeList children = workflowAttributeElement.getChildNodes(); List<SearchingTypeDefinition> searchingAttributesMap = parseSearchableAttributes(children); bean.addPropertyValue("searchingTypeDefinitions", searchingAttributesMap); Map<String, RoutingTypeDefinition> routingTypesMap = parseRoutingTypes(children); bean.addPropertyValue("routingTypeDefinitions", routingTypesMap); } protected List<SearchingTypeDefinition> parseSearchableAttributes(NodeList workflowAttributesChildren) { List<SearchingTypeDefinition> searchingAttributesMap = new ArrayList<SearchingTypeDefinition>(); for (int i = 0; i < workflowAttributesChildren.getLength(); i++) { Node workflowAttributesChild = workflowAttributesChildren.item(i); if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) { if (((Element) workflowAttributesChild).getLocalName().equals(SEARCHING_TYPES_ELEMENT)) { SearchingTypeDefinition searchingTypeDefinition = parseSearchingTypes(workflowAttributesChild.getChildNodes()); searchingAttributesMap.add(searchingTypeDefinition); } } } return searchingAttributesMap; } protected List<Element> extractWorkflowAttributeElements(NodeList nodes, String attributeElementName) { List<Element> results = new ArrayList<Element>(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { if (StringUtils.isEmpty(attributeElementName) || ((Element) node).getLocalName().equals(attributeElementName)) { results.add((Element) node); } } } return results; } protected SearchingTypeDefinition parseSearchingTypes(NodeList workflowAttributesChildren) { SearchingTypeDefinition searchingTypeDefinition = new SearchingTypeDefinition(); for (int i = 0; i < workflowAttributesChildren.getLength(); i++) { Node workflowAttributesChild = workflowAttributesChildren.item(i); if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) { if (((Element) workflowAttributesChild).getLocalName().equals(SEARCHING_ATTRIBUTE)){ searchingTypeDefinition.setSearchingAttribute((SearchingAttribute)parseAttributeDefinition((Element) workflowAttributesChild)); }else if(((Element) workflowAttributesChild).getLocalName().equals(DOCUMENT_VALUE_ATTRIBUTE)){ if(searchingTypeDefinition.getDocumentValues() == null){ searchingTypeDefinition.setDocumentValues(new ArrayList<String>()); } searchingTypeDefinition.getDocumentValues().addAll(parseDocumentValueAttributeDefinition((Element) workflowAttributesChild)); } } } return searchingTypeDefinition; } protected WorkflowAttributeMetadata parseAttributeDefinition(Element workflowAttributeDefinitionElement) { WorkflowAttributeMetadata workflowAttributeMetadata = null; if(workflowAttributeDefinitionElement.getLocalName().equals(SEARCHING_ATTRIBUTE)){ return parseSearchingAttribute(workflowAttributeDefinitionElement); }else if(workflowAttributeDefinitionElement.getLocalName().equals(ROUTING_ATTRIBUTE)){ return parseRoutingAttribute(workflowAttributeDefinitionElement); } return workflowAttributeMetadata; } protected WorkflowAttributeMetadata parseSearchingAttribute(Element workflowAttributeDefinitionElement) { SearchingAttribute workflowAttributeMetadata = new SearchingAttribute(); String businessObjectClassName = workflowAttributeDefinitionElement.getAttribute("businessObjectClassName"); if (StringUtils.isNotBlank(businessObjectClassName)) { try { Class.forName(businessObjectClassName); workflowAttributeMetadata.setBusinessObjectClassName(businessObjectClassName); } catch (ClassNotFoundException e) { throw new RuntimeException("Unable to find class of name " + businessObjectClassName + " when parsing workflowAttribute"); } } String attributeName = workflowAttributeDefinitionElement.getAttribute("attributeName"); if (StringUtils.isNotBlank(attributeName)) { workflowAttributeMetadata.setAttributeName(attributeName); } return workflowAttributeMetadata; } protected WorkflowAttributeMetadata parseRoutingAttribute(Element workflowAttributeDefinitionElement) { RoutingAttribute workflowAttributeMetadata = new RoutingAttribute(); String attributeName = workflowAttributeDefinitionElement.getAttribute("qualificationAttributeName"); if (StringUtils.isNotBlank(attributeName)) { workflowAttributeMetadata.setQualificationAttributeName(attributeName); } return workflowAttributeMetadata; } protected List<String> parseDocumentValueAttributeDefinition(Element workflowAttributeDefinitionElement) { List<String>paths = new ArrayList<String>(); paths.add(workflowAttributeDefinitionElement.getAttribute("path")); return paths; } protected Map<String, RoutingTypeDefinition> parseRoutingTypes(NodeList workflowAttributesChildren) { Map<String, RoutingTypeDefinition> routingTypesMap = new HashMap<String, RoutingTypeDefinition>(); for (int i = 0; i < workflowAttributesChildren.getLength(); i++) { Node workflowAttributesChild = workflowAttributesChildren.item(i); if (workflowAttributesChild.getNodeType() == Node.ELEMENT_NODE) { if (((Element) workflowAttributesChild).getLocalName().equals(ROUTING_TYPES_ELEMENT)) { RoutingTypeDefinition routingTypeDefinition = new RoutingTypeDefinition(); Element routingTypeElement = (Element) workflowAttributesChild; String name = routingTypeElement.getAttribute("nodeName"); List<RoutingAttribute> routingAttributes = new ArrayList<RoutingAttribute>(); List<DocumentValuePathGroup> documentValuePathGroups = new ArrayList<DocumentValuePathGroup>(); List<Element> workflowAttributeList = extractWorkflowAttributeElements(routingTypeElement.getChildNodes(), ""); for (int j = 0; j < workflowAttributeList.size(); j++) { Element workflowAttributeDefinitionElement = (Element) workflowAttributeList.get(j); if(workflowAttributeDefinitionElement.getLocalName().equals("routingAttributes")){ List<Element> routingAttributeList = extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "routingAttribute"); for(Element routingAttribute:routingAttributeList){ routingAttributes.add((RoutingAttribute)parseAttributeDefinition(routingAttribute)); } } else if(workflowAttributeDefinitionElement.getLocalName().equals("documentValuePathGroup")){ documentValuePathGroups.add(parseDocumentValuesPathGroup(workflowAttributeDefinitionElement)); } } routingTypeDefinition.setDocumentValuePathGroups(documentValuePathGroups); routingTypeDefinition.setRoutingAttributes(routingAttributes); routingTypesMap.put(name, routingTypeDefinition); } } } return routingTypesMap; } protected DocumentCollectionPath parseDocumentCollectionPath(Element workflowAttributeDefinitionElement) { DocumentCollectionPath documentCollectionPath = new DocumentCollectionPath(); for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentCollectionPath")){ documentCollectionPath.setNestedCollection(parseDocumentCollectionPath(element)); } List<String>paths = new ArrayList<String>(); for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentValue")){ paths.addAll(parseDocumentValueAttributeDefinition(element)); } documentCollectionPath.setDocumentValues(paths); String collectionName = workflowAttributeDefinitionElement.getAttribute("path"); documentCollectionPath.setCollectionPath(collectionName); return documentCollectionPath; } protected DocumentValuePathGroup parseDocumentValuesPathGroup(Element workflowAttributeDefinitionElement) { DocumentValuePathGroup documentValuePathGroup = new DocumentValuePathGroup(); List<Element> documentCollectionPathElements = extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentCollectionPath"); if( documentCollectionPathElements.size() > 0){ documentValuePathGroup.setDocumentCollectionPath(parseDocumentCollectionPath(documentCollectionPathElements.get(0))); } List<String>paths = new ArrayList<String>(); for(Element element:extractWorkflowAttributeElements(workflowAttributeDefinitionElement.getChildNodes(), "documentValue")){ paths.addAll(parseDocumentValueAttributeDefinition(element)); } documentValuePathGroup.setDocumentValues(paths); return documentValuePathGroup; } @Override protected String getBaseBeanTypeParent(Element element) { return "WorkflowAttributes"; } }