001/**
002 * Copyright 2005-2017 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 */
016package org.kuali.rice.kns.workflow.attribute;
017
018import org.kuali.rice.kew.engine.RouteContext;
019import org.kuali.rice.kns.service.KNSServiceLocator;
020import org.kuali.rice.krad.datadictionary.DocumentEntry;
021import org.kuali.rice.krad.datadictionary.RoutingTypeDefinition;
022import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
023import org.kuali.rice.krad.document.Document;
024import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
025
026import java.util.ArrayList;
027import java.util.HashMap;
028import java.util.List;
029import 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 * @deprecated Only used by KNS classes, no replacement.
082 */
083@Deprecated
084public class DataDictionaryQualifierResolver extends QualifierResolverBase {
085//    private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DataDictionaryQualifierResolver.class);
086    
087
088    /**
089     * Given the RouteContext, determines the document type of the document being routed and the current
090     * route nodes; generates a List of qualifier Map<String, String>s based on the the contents of the document.
091     * @see org.kuali.rice.kew.role.QualifierResolver#resolve(org.kuali.rice.kew.engine.RouteContext)
092     */
093    public List<Map<String, String>> resolve(RouteContext context) {
094        final String routeLevel = context.getNodeInstance().getName();
095        final DocumentEntry documentEntry = getDocumentEntry(context);
096        final RoutingTypeDefinition routingTypeDefinition = getWorkflowAttributeDefintion(documentEntry, routeLevel);
097        final Document document = getDocument(context);
098        List<Map<String, String>> qualifiers = null;
099        
100        if (document != null && routingTypeDefinition != null) {
101            qualifiers = KNSServiceLocator.getWorkflowAttributePropertyResolutionService().resolveRoutingTypeQualifiers(document, routingTypeDefinition);
102        } else {
103            qualifiers = new ArrayList<Map<String, String>>();
104            Map<String, String> basicQualifier = new HashMap<String, String>();
105            qualifiers.add(basicQualifier);
106        }
107        decorateWithCommonQualifiers(qualifiers, document, documentEntry, routeLevel);
108        return qualifiers;
109    }
110
111    /**
112     * Retrieves the data dictionary entry for the document being operated on by the given route context
113     * @param context the current route context
114     * @return the data dictionary document entry
115     */
116    protected DocumentEntry getDocumentEntry(RouteContext context) {
117        return KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(context.getDocument().getDocumentType().getName());
118    }
119
120    /**
121     * Retrieves the proper List of WorkflowAttributes for the given route level from the data dictionary
122     * document entry
123     * @param documentEntry the data dictionary document entry for the currently routed document
124     * @param routeLevelName the name of the route level
125     * @return a WorkflowAttributeDefinition if one could be found for the route level; otherwise, nothing
126     */
127    protected RoutingTypeDefinition getWorkflowAttributeDefintion(DocumentEntry documentEntry, String routeLevelName) {
128       final WorkflowAttributes workflowAttributes = documentEntry.getWorkflowAttributes();
129       if ( workflowAttributes == null ) {
130           return null;
131       }
132       final Map<String, RoutingTypeDefinition> routingTypeMap = workflowAttributes.getRoutingTypeDefinitions();
133       if (routingTypeMap.containsKey(routeLevelName)) return routingTypeMap.get(routeLevelName);
134       return null;
135    }
136    
137    /**
138     * Add common qualifiers to every Map<String, String> in the given List of Map<String, String>
139     * @param qualifiers a List of Map<String, String>s to add common qualifiers to
140     * @param document the document currently being routed
141     * @param documentEntry the data dictionary entry of the type of document currently being routed
142     * @param routeLevel the document's current route level
143     */
144    protected void decorateWithCommonQualifiers(List<Map<String, String>> qualifiers, Document document, DocumentEntry documentEntry, String routeLevel) {
145        for (Map<String, String> qualifier : qualifiers) {
146            addCommonQualifiersToMap(qualifier, document, documentEntry, routeLevel);
147        }
148    }
149    
150    /**
151     * Adds common qualifiers to a given Map<String, String>
152     * @param qualifier an Map<String, String> to add common qualifiers to
153     * @param document the document currently being routed
154     * @param documentEntry the data dictionary entry of the type of document currently being routed
155     * @param routeLevel the document's current route level
156     */
157    protected void addCommonQualifiersToMap(Map<String, String> qualifier, Document document, DocumentEntry documentEntry, String routeLevel) {
158        if ( document != null ) {
159            qualifier.put(KIM_ATTRIBUTE_DOCUMENT_NUMBER, document.getDocumentNumber());
160        }
161        if ( documentEntry != null ) {
162            qualifier.put(KIM_ATTRIBUTE_DOCUMENT_TYPE_NAME, documentEntry.getDocumentTypeName());
163        }
164        qualifier.put(KIM_ATTRIBUTE_ROUTE_LEVEL_NAME, routeLevel);
165    }
166}