001 /** 002 * Copyright 2005-2013 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.rice.kns.workflow.attribute; 017 018 import org.kuali.rice.kew.engine.RouteContext; 019 import org.kuali.rice.kns.service.KNSServiceLocator; 020 import org.kuali.rice.krad.datadictionary.DocumentEntry; 021 import org.kuali.rice.krad.datadictionary.RoutingTypeDefinition; 022 import org.kuali.rice.krad.datadictionary.WorkflowAttributes; 023 import org.kuali.rice.krad.document.Document; 024 import org.kuali.rice.krad.service.KRADServiceLocatorWeb; 025 026 import java.util.ArrayList; 027 import java.util.HashMap; 028 import java.util.List; 029 import java.util.Map; 030 031 /** 032 * QualifierResolver which uses Data Dictionary defined workflow attributes to gather a collection 033 * of qualifiers to use to determine the responsibility for a document at a given workflow route node. 034 * 035 * WorkflowAttributes can be defined in the data dictionary like so (this has been abbreviated): 036 * 037 * <!-- Exported Workflow Attributes --> 038 * <bean id="DisbursementVoucherDocument-workflowAttributes" parent="DisbursementVoucherDocument-workflowAttributes-parentBean"/> 039 * 040 * <bean id="DisbursementVoucherDocument-workflowAttributes-parentBean" abstract="true" parent="WorkflowAttributes"> 041 * <property name="routingTypeDefinitions"> 042 * <map> 043 * <!-- no qualifiers for purchasing node --> 044 * <entry key="Account" value-ref="RoutingType-AccountingDocument-Account-sourceOnly"/> 045 * <entry key="AccountingOrganizationHierarchy" value-ref="RoutingType-AccountingDocument-OrganizationHierarchy-sourceOnly"/> 046 * <entry key="Campus" value-ref="DisbursementVoucherDocument-RoutingType-Campus"/> 047 * <!-- no qualifiers for tax review --> 048 * <!-- no qualifiers for travel review --> 049 * <entry key="PaymentMethod" value-ref="DisbursementVoucherDocument-RoutingType-PaymentMethod"/> 050 * <entry key="Award" value-ref="RoutingType-AccountingDocument-Award"/> 051 * </map> 052 * </property> 053 * </bean> 054 * 055 * <bean id="DisbursementVoucherDocument-RoutingType-PaymentMethod" class="org.kuali.rice.krad.datadictionary.RoutingTypeDefinition"> 056 * <property name="routingAttributes"> 057 * <list> 058 * <bean class="org.kuali.rice.krad.datadictionary.RoutingAttribute"> 059 * <property name="qualificationAttributeName" value="disbVchrPaymentMethodCode"/> 060 * </bean> 061 * </list> 062 * </property> 063 * <property name="documentValuePathGroups"> 064 * <list> 065 * <bean class="org.kuali.rice.krad.datadictionary.DocumentValuePathGroup"> 066 * <property name="documentValues"> 067 * <list> 068 * <value>disbVchrPaymentMethodCode</value> 069 * </list> 070 * </property> 071 * </bean> 072 * </list> 073 * </property> 074 * </bean> 075 * 076 * At the PaymentMethod node of the document, the DisbursementVoucherDocument-RoutingType-PaymentMethod RoutingTypeDefinition will be 077 * consulted; it will pull values from the document (in this case, document.disbVchrPaymentMethodCode) and populate those 078 * into the role qualifier Map<String, String>, with the key being the qualificationAttributeName and the value being the value of the property 079 * listed in the documentValuePathGroups in the document. 080 */ 081 public class DataDictionaryQualifierResolver extends QualifierResolverBase { 082 // private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DataDictionaryQualifierResolver.class); 083 084 085 /** 086 * Given the RouteContext, determines the document type of the document being routed and the current 087 * route nodes; generates a List of qualifier Map<String, String>s based on the the contents of the document. 088 * @see org.kuali.rice.kew.role.QualifierResolver#resolve(org.kuali.rice.kew.engine.RouteContext) 089 */ 090 public List<Map<String, String>> resolve(RouteContext context) { 091 final String routeLevel = context.getNodeInstance().getName(); 092 final DocumentEntry documentEntry = getDocumentEntry(context); 093 final RoutingTypeDefinition routingTypeDefinition = getWorkflowAttributeDefintion(documentEntry, routeLevel); 094 final Document document = getDocument(context); 095 List<Map<String, String>> qualifiers = null; 096 097 if (document != null && routingTypeDefinition != null) { 098 qualifiers = KNSServiceLocator.getWorkflowAttributePropertyResolutionService().resolveRoutingTypeQualifiers(document, routingTypeDefinition); 099 } else { 100 qualifiers = new ArrayList<Map<String, String>>(); 101 Map<String, String> basicQualifier = new HashMap<String, String>(); 102 qualifiers.add(basicQualifier); 103 } 104 decorateWithCommonQualifiers(qualifiers, document, documentEntry, routeLevel); 105 return qualifiers; 106 } 107 108 /** 109 * Retrieves the data dictionary entry for the document being operated on by the given route context 110 * @param context the current route context 111 * @return the data dictionary document entry 112 */ 113 protected DocumentEntry getDocumentEntry(RouteContext context) { 114 return KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(context.getDocument().getDocumentType().getName()); 115 } 116 117 /** 118 * Retrieves the proper List of WorkflowAttributes for the given route level from the data dictionary 119 * document entry 120 * @param documentEntry the data dictionary document entry for the currently routed document 121 * @param routeLevelName the name of the route level 122 * @return a WorkflowAttributeDefinition if one could be found for the route level; otherwise, nothing 123 */ 124 protected RoutingTypeDefinition getWorkflowAttributeDefintion(DocumentEntry documentEntry, String routeLevelName) { 125 final WorkflowAttributes workflowAttributes = documentEntry.getWorkflowAttributes(); 126 if ( workflowAttributes == null ) { 127 return null; 128 } 129 final Map<String, RoutingTypeDefinition> routingTypeMap = workflowAttributes.getRoutingTypeDefinitions(); 130 if (routingTypeMap.containsKey(routeLevelName)) return routingTypeMap.get(routeLevelName); 131 return null; 132 } 133 134 /** 135 * Add common qualifiers to every Map<String, String> in the given List of Map<String, String> 136 * @param qualifiers a List of Map<String, String>s to add common qualifiers to 137 * @param document the document currently being routed 138 * @param documentEntry the data dictionary entry of the type of document currently being routed 139 * @param routeLevel the document's current route level 140 */ 141 protected void decorateWithCommonQualifiers(List<Map<String, String>> qualifiers, Document document, DocumentEntry documentEntry, String routeLevel) { 142 for (Map<String, String> qualifier : qualifiers) { 143 addCommonQualifiersToMap(qualifier, document, documentEntry, routeLevel); 144 } 145 } 146 147 /** 148 * Adds common qualifiers to a given Map<String, String> 149 * @param qualifier an Map<String, String> to add common qualifiers to 150 * @param document the document currently being routed 151 * @param documentEntry the data dictionary entry of the type of document currently being routed 152 * @param routeLevel the document's current route level 153 */ 154 protected void addCommonQualifiersToMap(Map<String, String> qualifier, Document document, DocumentEntry documentEntry, String routeLevel) { 155 if ( document != null ) { 156 qualifier.put(KIM_ATTRIBUTE_DOCUMENT_NUMBER, document.getDocumentNumber()); 157 } 158 if ( documentEntry != null ) { 159 qualifier.put(KIM_ATTRIBUTE_DOCUMENT_TYPE_NAME, documentEntry.getDocumentTypeName()); 160 } 161 qualifier.put(KIM_ATTRIBUTE_ROUTE_LEVEL_NAME, routeLevel); 162 } 163 }