View Javadoc

1   /*
2    * Copyright 2006-2012 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  
17  package org.kuali.rice.kew.docsearch;
18  
19  import org.apache.cxf.common.util.StringUtils;
20  import org.junit.Test;
21  import org.kuali.rice.core.api.uif.RemotableAttributeError;
22  import org.kuali.rice.core.api.uif.RemotableAttributeField;
23  import org.kuali.rice.kew.api.KewApiServiceLocator;
24  import org.kuali.rice.kew.api.WorkflowDocument;
25  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
26  import org.kuali.rice.kew.api.document.DocumentStatus;
27  import org.kuali.rice.kew.api.document.DocumentWithContent;
28  import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
29  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDataType;
30  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
31  import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
32  import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
33  import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
34  import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
35  import org.kuali.rice.kew.api.extension.ExtensionDefinition;
36  import org.kuali.rice.kew.doctype.bo.DocumentType;
37  import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
38  import org.kuali.rice.kew.framework.document.search.DocumentSearchCustomizerBase;
39  import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValue;
40  import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValues;
41  import org.kuali.rice.kew.service.KEWServiceLocator;
42  import org.kuali.rice.kew.test.KEWTestCase;
43  
44  import java.util.ArrayList;
45  import java.util.Collections;
46  import java.util.List;
47  
48  import static org.junit.Assert.*;
49  
50  /**
51   * An integration test for the DocumentSearchCustomizer class.  Includes tests on various aspects of the customzations
52   * that class provides, attempting to use the high-level document search apis to exercise it.
53   *
54   * @author Kuali Rice Team (rice.collab@kuali.org)
55   */
56  public class DocumentSearchCustomizerTest extends KEWTestCase {
57  
58      @Override
59  	protected void loadTestData() throws Exception {
60      	loadXmlFile("DocumentSearchCustomizerTest.xml");
61      }
62  
63      @Test
64      public void testCustomizeCriteria() throws Exception {
65  
66          String ewestfal = getPrincipalIdForName("ewestfal");
67          DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
68  
69          // first check a full doc search, should return no results
70          DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
71          assertTrue(results.getSearchResults().isEmpty());
72          assertFalse(results.getCriteria().getDocumentStatuses().contains(DocumentStatus.FINAL));
73  
74          // now check a document search against the "DocumentSearchCustomizerTest" document type, it is configured with the
75          // CustomizeCriteria customizer
76          builder.setDocumentTypeName("DocumentSearchCustomizerTest");
77  
78          results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
79          assertTrue(results.getSearchResults().isEmpty());
80          DocumentSearchCriteria resultCriteria = results.getCriteria();
81          assertTrue("Document Statuses should have contained FINAL, instead contains: " + resultCriteria
82                  .getDocumentStatuses(), resultCriteria.getDocumentStatuses().contains(DocumentStatus.FINAL));
83  
84          // now route an instance of the CustomizeCriteria document type to FINAL
85          WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
86                  "DocumentSearchCustomizerTest");
87          document.route("");
88          assertTrue(document.isFinal());
89  
90          // now run another search, we should get back one result this time
91          results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
92          assertEquals(1, results.getSearchResults().size());
93          assertEquals(document.getDocumentId(), results.getSearchResults().get(0).getDocument().getDocumentId());
94      }
95  
96      @Test
97      public void testCustomizeClearCriteria() throws Exception {
98  
99          // grab a couple of document types, the first is the TestDocumentType which has no DocumentSearchCustomizer
100         // configured on it, the second in our Document Type for this integration test which is configured with the
101         // Customizer
102 
103         DocumentType testDocumentType = KEWServiceLocator.getDocumentTypeService().findByName("TestDocumentType");
104         assertNotNull(testDocumentType);
105         DocumentType customizedDocumentType = KEWServiceLocator.getDocumentTypeService().findByName("DocumentSearchCustomizerTest");
106         assertNotNull(customizedDocumentType);
107 
108         // first set document id and application document id on a criteria and clear it using the TestDocumentType, it
109         // should clear out both
110 
111         DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
112         builder.setDocumentId("12345");
113         builder.setApplicationDocumentId("54321");
114         DocumentSearchCriteria clearedCriteria = KEWServiceLocator.getDocumentSearchService().clearCriteria(testDocumentType, builder.build());
115         assertNull(clearedCriteria.getDocumentId());
116         assertNull(clearedCriteria.getApplicationDocumentId());
117 
118         // now clear the same criteria with the customized document type, it should clear out the document id but
119         // preserve the application document id
120 
121         clearedCriteria = KEWServiceLocator.getDocumentSearchService().clearCriteria(customizedDocumentType, builder.build());
122         assertNull(clearedCriteria.getDocumentId());
123         assertEquals("54321", clearedCriteria.getApplicationDocumentId());
124     }
125 
126     @Test
127     public void testCustomizeResults() throws Exception {
128 
129         // route an instance of the CustomizeCriteria document type to FINAL
130 
131         String ewestfal = getPrincipalIdForName("ewestfal");
132         WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
133                 "DocumentSearchCustomizerTest");
134         document.route("");
135         assertTrue(document.isFinal());
136 
137         // check that the document attributes get indexed properly
138 
139         List<String> attributeValues = KewApiServiceLocator.getWorkflowDocumentService().getSearchableAttributeStringValuesByKey(document.getDocumentId(), "myAttribute");
140         assertEquals(1, attributeValues.size());
141         assertEquals("myValue", attributeValues.get(0));
142         attributeValues = KewApiServiceLocator.getWorkflowDocumentService().getSearchableAttributeStringValuesByKey(document.getDocumentId(), "myMultiValuedAttribute");
143         assertEquals(2, attributeValues.size());
144         assertTrue(attributeValues.contains("value1"));
145         assertTrue(attributeValues.contains("value2"));
146 
147         DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
148         DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
149         assertEquals(1, results.getSearchResults().size());
150         DocumentSearchResult result = results.getSearchResults().get(0);
151 
152         // TODO - the below assertions really should work, but they currently don't.  Currently, unless you pass the
153         // specific document type as one of the criteria the document attributes are not returned with the search
154         // There should at least be an option on the search api to enable the returning of document attributes from
155         // the search API - see https://jira.kuali.org/browse/KULRICE-6764
156         /*assertEquals(1, result.getDocumentAttributes().size());
157         DocumentAttribute attribute = result.getDocumentAttributes().get(0);
158         assertEquals("myAttribute", attribute.getName());
159         assertEquals("myValue", attribute.getValue());
160         assertEquals(DocumentAttributeDataType.STRING, attribute.getDataType());*/
161 
162         // now do a document search targeting the specific customizer document type, the result should be customized
163         // and the "myAttribute" attribute should have a customized value of "myCustomizedValue", also the
164         // "myMultiValuedAttribute" should now only have a single value of "value0"
165         
166         builder.setDocumentTypeName("DocumentSearchCustomizerTest");
167         results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
168         assertEquals(1, results.getSearchResults().size());
169         result = results.getSearchResults().get(0);
170         assertEquals(3, result.getDocumentAttributes().size());
171         for (DocumentAttribute attribute : result.getDocumentAttributes()) {
172             if (attribute.getName().equals("myAttribute")) {
173                 assertEquals("myAttribute", attribute.getName());
174                 assertEquals("myCustomizedValue", attribute.getValue());
175                 assertEquals(DocumentAttributeDataType.STRING, attribute.getDataType());
176             } else if (attribute.getName().equals("myMultiValuedAttribute")) {
177                 assertEquals("myMultiValuedAttribute", attribute.getName());
178                 assertEquals("value0", attribute.getValue());
179                 assertEquals(DocumentAttributeDataType.STRING, attribute.getDataType());
180             } else if (attribute.getName().equals("criteriaUserId")) {
181                 assertEquals("criteriaUserId", attribute.getName());
182                 assertEquals(ewestfal, attribute.getValue());
183             }else {
184                 fail("Encountered an attribute name which i didn't understand: " + attribute.getName());
185             }
186         }
187     }
188 
189     /**
190      * An implementation of a DocumentSearchCustomizer which does some simple customizations to allow us to test that
191      * the customizer is functioning properly.
192      */
193     public static final class Customizer extends DocumentSearchCustomizerBase {
194 
195         @Override
196         public DocumentSearchCriteria customizeCriteria(DocumentSearchCriteria documentSearchCriteria) {
197             DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create(documentSearchCriteria);
198             builder.setDocumentStatuses(Collections.singletonList(DocumentStatus.FINAL));
199             return builder.build();
200         }
201         @Override
202         public boolean isCustomizeCriteriaEnabled(String documentTypeName) {
203             return true;
204         }
205 
206         @Override
207         public DocumentSearchCriteria customizeClearCriteria(DocumentSearchCriteria documentSearchCriteria) {
208             // preserver applicationDocumentId on clear, but clear out everything else
209             DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
210             builder.setApplicationDocumentId(documentSearchCriteria.getApplicationDocumentId());
211             return builder.build();
212         }
213         @Override
214         public boolean isCustomizeClearCriteriaEnabled(String documentTypeName) {
215             return true;
216         }
217 
218         @Override
219         public DocumentSearchResultValues customizeResults(DocumentSearchCriteria documentSearchCriteria,
220                 List<DocumentSearchResult> defaultResults) {
221             if (defaultResults.size() == 1) {
222                 assertEquals(1, defaultResults.size());
223                 DocumentSearchResultValues.Builder valuesBuilder = DocumentSearchResultValues.Builder.create();
224 
225                 DocumentSearchResultValue.Builder resultValueBuilder = DocumentSearchResultValue.Builder.create(defaultResults.get(0).getDocument().getDocumentId());
226                 resultValueBuilder.getDocumentAttributes().add(DocumentAttributeFactory.loadContractIntoBuilder(DocumentAttributeFactory.createStringAttribute("myAttribute", "myCustomizedValue")));
227                 resultValueBuilder.getDocumentAttributes().add(DocumentAttributeFactory.loadContractIntoBuilder(DocumentAttributeFactory.createStringAttribute("myMultiValuedAttribute", "value0")));
228 
229                 // Return if principal id was foudn in criteria
230                 if(!StringUtils.isEmpty(documentSearchCriteria.getDocSearchUserId())) {
231                      resultValueBuilder.getDocumentAttributes().add(DocumentAttributeFactory.loadContractIntoBuilder(DocumentAttributeFactory.createStringAttribute("criteriaUserId", documentSearchCriteria.getDocSearchUserId())));
232                 }
233 
234                 valuesBuilder.getResultValues().add(resultValueBuilder);
235                 return valuesBuilder.build();
236             } else {
237                 return null;
238             }
239         }
240         @Override
241         public boolean isCustomizeResultsEnabled(String documentTypeName) {
242             return true;
243         }
244         
245     }
246 
247     public static final class CustomSearchAttribute implements SearchableAttribute {
248         @Override
249         public String generateSearchContent(ExtensionDefinition extensionDefinition,
250                 String documentTypeName,
251                 WorkflowAttributeDefinition attributeDefinition) {
252             return null;
253         }
254         @Override
255         public List<DocumentAttribute> extractDocumentAttributes(ExtensionDefinition extensionDefinition,
256                 DocumentWithContent documentWithContent) {
257             List<DocumentAttribute> attributes = new ArrayList<DocumentAttribute>();
258             attributes.add(DocumentAttributeFactory.createStringAttribute("myAttribute", "myValue"));
259             attributes.add(DocumentAttributeFactory.createStringAttribute("myMultiValuedAttribute", "value1"));
260             attributes.add(DocumentAttributeFactory.createStringAttribute("myMultiValuedAttribute", "value2"));
261             attributes.add(DocumentAttributeFactory.createStringAttribute("criteriaUserId", "blank"));
262             return attributes;
263         }
264         @Override
265         public List<RemotableAttributeField> getSearchFields(ExtensionDefinition extensionDefinition,
266                 String documentTypeName) {
267             List<RemotableAttributeField> searchFields = new ArrayList<RemotableAttributeField>();
268             RemotableAttributeField.Builder builder = RemotableAttributeField.Builder.create("myAttribute");
269             searchFields.add(builder.build());
270             builder = RemotableAttributeField.Builder.create("myMultiValuedAttribute");
271             searchFields.add(builder.build());
272             builder = RemotableAttributeField.Builder.create("criteriaUserId");
273             searchFields.add(builder.build());
274             return searchFields;
275         }
276         @Override
277         public List<RemotableAttributeError> validateDocumentAttributeCriteria(ExtensionDefinition extensionDefinition,
278                 DocumentSearchCriteria documentSearchCriteria) {
279             return null;
280         }
281     }
282 
283 }