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 }