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