View Javadoc

1   /**
2    * Copyright 2005-2013 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.krad.workflow.attribute;
17  
18  import org.kuali.rice.kew.engine.RouteContext;
19  import org.kuali.rice.krad.datadictionary.DocumentEntry;
20  import org.kuali.rice.krad.datadictionary.RoutingTypeDefinition;
21  import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
22  import org.kuali.rice.krad.document.Document;
23  import org.kuali.rice.krad.service.KRADServiceLocatorInternal;
24  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
25  
26  import java.util.ArrayList;
27  import java.util.HashMap;
28  import java.util.List;
29  import java.util.Map;
30  
31  /**
32   * QualifierResolver which uses Data Dictionary defined workflow attributes to gather a collection
33   * of qualifiers to use to determine the responsibility for a document at a given workflow route node.
34   * 
35   * WorkflowAttributes can be defined in the data dictionary like so (this has been abbreviated):
36   * 
37   * <!-- Exported Workflow Attributes -->
38   *   <bean id="DisbursementVoucherDocument-workflowAttributes" parent="DisbursementVoucherDocument-workflowAttributes-parentBean"/>
39   *
40   *   <bean id="DisbursementVoucherDocument-workflowAttributes-parentBean" abstract="true" parent="WorkflowAttributes">
41   *       <property name="routingTypeDefinitions">
42   *           <map>
43   *               <!-- no qualifiers for purchasing node -->
44   *               <entry key="Account" value-ref="RoutingType-AccountingDocument-Account-sourceOnly"/>
45   *               <entry key="AccountingOrganizationHierarchy" value-ref="RoutingType-AccountingDocument-OrganizationHierarchy-sourceOnly"/>
46   *               <entry key="Campus" value-ref="DisbursementVoucherDocument-RoutingType-Campus"/>
47   *               <!-- no qualifiers for tax review -->
48   *               <!-- no qualifiers for travel review -->
49   *               <entry key="PaymentMethod" value-ref="DisbursementVoucherDocument-RoutingType-PaymentMethod"/>
50   *               <entry key="Award" value-ref="RoutingType-AccountingDocument-Award"/>
51   *           </map>
52   *       </property>
53   *   </bean>
54   * 
55   *   <bean id="DisbursementVoucherDocument-RoutingType-PaymentMethod" class="org.kuali.rice.krad.datadictionary.RoutingTypeDefinition">
56   *       <property name="routingAttributes">
57   *           <list>
58   *               <bean class="org.kuali.rice.krad.datadictionary.RoutingAttribute">
59   *                   <property name="qualificationAttributeName" value="disbVchrPaymentMethodCode"/>
60   *               </bean>
61   *           </list>
62   *       </property>
63   *       <property name="documentValuePathGroups">
64   *           <list>
65   *               <bean class="org.kuali.rice.krad.datadictionary.DocumentValuePathGroup">
66   *                   <property name="documentValues">
67   *                       <list>
68   *                           <value>disbVchrPaymentMethodCode</value>
69   *                       </list>
70   *                   </property>
71   *               </bean>
72   *           </list>
73   *       </property>
74   *   </bean> 
75   * 
76   * At the PaymentMethod node of the document, the DisbursementVoucherDocument-RoutingType-PaymentMethod RoutingTypeDefinition will be
77   * consulted; it will pull values from the document (in this case, document.disbVchrPaymentMethodCode) and populate those
78   * into the role qualifier Map<String, String>, with the key being the qualificationAttributeName and the value being the value of the property
79   * listed in the documentValuePathGroups in the document.
80   */
81  public class DataDictionaryQualifierResolver extends QualifierResolverBase {
82  //    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DataDictionaryQualifierResolver.class);
83      
84  
85      /**
86       * Given the RouteContext, determines the document type of the document being routed and the current
87       * route nodes; generates a List of qualifier Map<String, String>s based on the the contents of the document.
88       * @see org.kuali.rice.kew.role.QualifierResolver#resolve(org.kuali.rice.kew.engine.RouteContext)
89       */
90      public List<Map<String, String>> resolve(RouteContext context) {
91          final String routeLevel = context.getNodeInstance().getName();
92          final DocumentEntry documentEntry = getDocumentEntry(context);
93          final RoutingTypeDefinition routingTypeDefinition = getWorkflowAttributeDefintion(documentEntry, routeLevel);
94          final Document document = getDocument(context);
95          List<Map<String, String>> qualifiers = null;
96          
97          if (document != null && routingTypeDefinition != null) {
98              qualifiers = KRADServiceLocatorInternal.getWorkflowAttributePropertyResolutionService().resolveRoutingTypeQualifiers(document, routingTypeDefinition);
99          } 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 }