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.kew.docsearch;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.kuali.rice.core.api.uif.RemotableAttributeError;
20  import org.kuali.rice.kew.api.WorkflowRuntimeException;
21  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
22  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
23  import org.kuali.rice.kew.framework.document.search.AttributeFields;
24  import org.kuali.rice.kew.framework.document.search.DocumentSearchCriteriaConfiguration;
25  import org.kuali.rice.kew.framework.document.search.DocumentSearchResultSetConfiguration;
26  import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValues;
27  import org.kuali.rice.kew.doctype.DocumentTypeAttributeBo;
28  import org.kuali.rice.kew.doctype.bo.DocumentType;
29  import org.kuali.rice.kew.framework.KewFrameworkServiceLocator;
30  import org.kuali.rice.kew.framework.document.search.DocumentSearchCustomization;
31  import org.kuali.rice.kew.framework.document.search.DocumentSearchCustomizationHandlerService;
32  import org.kuali.rice.kew.rule.bo.RuleAttribute;
33  
34  import java.util.ArrayList;
35  import java.util.LinkedHashMap;
36  import java.util.List;
37  
38  /**
39   * Reference implementation of {@code DocumentSearchCustomizationMediator}.
40   *
41   * @author Kuali Rice Team (rice.collab@kuali.org)
42   */
43  public class DocumentSearchCustomizationMediatorImpl implements DocumentSearchCustomizationMediator {
44  
45      @Override
46      public DocumentSearchCriteriaConfiguration getDocumentSearchCriteriaConfiguration(DocumentType documentType) {
47  
48          List<DocumentTypeAttributeBo> searchableAttributes = documentType.getSearchableAttributes();
49  
50          // This first map is used to partition our attributes by application id.  It maps an application id to the
51          // list of searchable attribute names that are associated with that application id.  Note that 'null' is a
52          // valid key in this map for those attributes that have no application id.
53          LinkedHashMap<String, List<String>> applicationIdToAttributeNameMap = new LinkedHashMap<String, List<String>>();
54  
55          // This second map is used to map the searchable attribute name to the List of RemotableAttributeFields
56          // that are returned by invocations of it's getSearchFields method.  This is a LinkedHashMap because it
57          // preserves the order of the keys as they are entered.  This allows us to return attribute fields in the
58          // proper order as defined by the order of searchable attributes on the doc type, despite the partitioning
59          // of our attributes by application id.
60          LinkedHashMap<String, AttributeFields> orderedSearchFieldMap = new LinkedHashMap<String, AttributeFields>();
61          LinkedHashMap<String, AttributeFields> orderedResultSetFieldMap = new LinkedHashMap<String, AttributeFields>();
62  
63          for (DocumentTypeAttributeBo searchableAttribute : searchableAttributes) {
64              RuleAttribute ruleAttribute = searchableAttribute.getRuleAttribute();
65              String attributeName = ruleAttribute.getName();
66              String applicationId = ruleAttribute.getApplicationId();
67              if (!applicationIdToAttributeNameMap.containsKey(applicationId)) {
68                  applicationIdToAttributeNameMap.put(applicationId, new ArrayList<String>());
69              }
70              applicationIdToAttributeNameMap.get(applicationId).add(attributeName);
71              // reserve a spot in the field map
72              orderedSearchFieldMap.put(attributeName, null);
73          }
74  
75          for (String applicationId : applicationIdToAttributeNameMap.keySet()) {
76              DocumentSearchCustomizationHandlerService documentSearchCustomizationService = loadCustomizationService(
77                      applicationId);
78              List<String> searchableAttributeNames = applicationIdToAttributeNameMap.get(applicationId);
79              DocumentSearchCriteriaConfiguration documentSearchConfiguration = documentSearchCustomizationService.getDocumentSearchConfiguration(
80                      documentType.getName(), searchableAttributeNames);
81              mergeAttributeFields(documentSearchConfiguration.getSearchAttributeFields(), orderedSearchFieldMap);
82          }
83  
84          DocumentSearchCriteriaConfiguration.Builder configBuilder = DocumentSearchCriteriaConfiguration.Builder.create();
85          configBuilder.setSearchAttributeFields(flattenOrderedFieldMap(orderedSearchFieldMap));
86          return configBuilder.build();
87      }
88  
89      @Override
90      public List<RemotableAttributeError> validateLookupFieldParameters(DocumentType documentType,
91              DocumentSearchCriteria documentSearchCriteria) {
92  
93          List<DocumentTypeAttributeBo> searchableAttributes = documentType.getSearchableAttributes();
94          LinkedHashMap<String, List<String>> applicationIdToAttributeNameMap = new LinkedHashMap<String, List<String>>();
95  
96          for (DocumentTypeAttributeBo searchableAttribute : searchableAttributes) {
97              RuleAttribute ruleAttribute = searchableAttribute.getRuleAttribute();
98              String attributeName = ruleAttribute.getName();
99              String applicationId = ruleAttribute.getApplicationId();
100             if (!applicationIdToAttributeNameMap.containsKey(applicationId)) {
101                 applicationIdToAttributeNameMap.put(applicationId, new ArrayList<String>());
102             }
103             applicationIdToAttributeNameMap.get(applicationId).add(attributeName);
104         }
105 
106         List<RemotableAttributeError> errors = new ArrayList<RemotableAttributeError>();
107         for (String applicationId : applicationIdToAttributeNameMap.keySet()) {
108             DocumentSearchCustomizationHandlerService documentSearchCustomizationService = loadCustomizationService(applicationId);
109             List<String> searchableAttributeNames = applicationIdToAttributeNameMap.get(applicationId);
110             List<RemotableAttributeError> searchErrors = documentSearchCustomizationService.validateCriteria(
111                     documentSearchCriteria, searchableAttributeNames);
112             if (!CollectionUtils.isEmpty(searchErrors)) {
113                 errors.addAll(searchErrors);
114             }
115         }
116 
117         return errors;
118     }
119 
120     @Override
121     public DocumentSearchCriteria customizeCriteria(DocumentType documentType, DocumentSearchCriteria documentSearchCriteria) {
122         DocumentTypeAttributeBo customizerAttribute = documentType.getCustomizerAttribute();
123         if (customizerAttribute != null) {
124             DocumentSearchCustomizationHandlerService service = loadCustomizationService(customizerAttribute.getRuleAttribute().getApplicationId());
125             if (service.getEnabledCustomizations(documentType.getName(), customizerAttribute.getRuleAttribute().getName()).contains(
126                     DocumentSearchCustomization.CRITERIA)) {
127                 DocumentSearchCriteria customizedCriteria = service.customizeCriteria(documentSearchCriteria, customizerAttribute.getRuleAttribute().getName());
128                 if (customizedCriteria != null) {
129                     return customizedCriteria;
130                 }
131             }
132         }
133         return null;
134     }
135 
136     @Override
137     public DocumentSearchCriteria customizeClearCriteria(DocumentType documentType, DocumentSearchCriteria documentSearchCriteria) {
138         DocumentTypeAttributeBo customizerAttribute = documentType.getCustomizerAttribute();
139         if (customizerAttribute != null) {
140             DocumentSearchCustomizationHandlerService service = loadCustomizationService(customizerAttribute.getRuleAttribute().getApplicationId());
141             if (service.getEnabledCustomizations(documentType.getName(), customizerAttribute.getRuleAttribute().getName()).contains(
142                     DocumentSearchCustomization.CLEAR_CRITERIA)) {
143                 DocumentSearchCriteria customizedCriteria = service.customizeClearCriteria(documentSearchCriteria, customizerAttribute.getRuleAttribute().getName());
144                 if (customizedCriteria != null) {
145                     return customizedCriteria;
146                 }
147             }
148         }
149         return null;
150     }
151 
152     @Override
153     public DocumentSearchResultValues customizeResults(DocumentType documentType,
154             DocumentSearchCriteria documentSearchCriteria, DocumentSearchResults results) {
155         DocumentTypeAttributeBo customizerAttribute = documentType.getCustomizerAttribute();
156         if (customizerAttribute != null) {
157             DocumentSearchCustomizationHandlerService service = loadCustomizationService(customizerAttribute.getRuleAttribute().getApplicationId());
158             if (service.getEnabledCustomizations(documentType.getName(), customizerAttribute.getRuleAttribute().getName()).contains(
159                     DocumentSearchCustomization.RESULTS)) {
160                 DocumentSearchResultValues customizedResults = service.customizeResults(documentSearchCriteria, results.getSearchResults(), customizerAttribute.getRuleAttribute().getName());
161                 if (customizedResults != null) {
162                     return customizedResults;
163                 }
164             }
165         }
166         return null;
167     }
168 
169     @Override
170     public DocumentSearchResultSetConfiguration customizeResultSetConfiguration(DocumentType documentType,
171             DocumentSearchCriteria documentSearchCriteria) {
172         DocumentTypeAttributeBo customizerAttribute = documentType.getCustomizerAttribute();
173         if (customizerAttribute != null) {
174             DocumentSearchCustomizationHandlerService service = loadCustomizationService(customizerAttribute.getRuleAttribute().getApplicationId());
175             if (service.getEnabledCustomizations(documentType.getName(), customizerAttribute.getRuleAttribute().getName()).contains(
176                     DocumentSearchCustomization.RESULT_SET_FIELDS)) {
177                 DocumentSearchResultSetConfiguration resultSetConfiguration = service.customizeResultSetConfiguration(
178                         documentSearchCriteria, customizerAttribute.getRuleAttribute().getName());
179                 if (resultSetConfiguration != null) {
180                     return resultSetConfiguration;
181                 }
182             }
183         }
184         return null;
185     }
186 
187     protected DocumentSearchCustomizationHandlerService loadCustomizationService(String applicationId) {
188         DocumentSearchCustomizationHandlerService service = KewFrameworkServiceLocator.getDocumentSearchCustomizationHandlerService(
189                 applicationId);
190         if (service == null) {
191             throw new WorkflowRuntimeException("Failed to locate DocumentSearchCustomizationService for applicationId: " + applicationId);
192         }
193         return service;
194     }
195 
196     protected void mergeAttributeFields(List<AttributeFields> attributeFieldsList, LinkedHashMap<String, AttributeFields> orderedFieldMap) {
197         if (attributeFieldsList == null) {
198             return;
199         }
200         for (AttributeFields attributeFields : attributeFieldsList) {
201             orderedFieldMap.put(attributeFields.getAttributeName(), attributeFields);
202         }
203     }
204 
205     protected List<AttributeFields> flattenOrderedFieldMap(LinkedHashMap<String, AttributeFields> orderedFieldMap) {
206         return new ArrayList<AttributeFields>(orderedFieldMap.values());
207     }
208 
209 }