001 /*
002 * Copyright 2006-2012 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 */
016
017 package org.kuali.rice.kew.docsearch;
018
019 import org.apache.commons.lang.StringUtils;
020 import org.junit.Test;
021 import org.kuali.rice.core.api.uif.RemotableAttributeError;
022 import org.kuali.rice.core.api.uif.RemotableAttributeField;
023 import org.kuali.rice.kew.api.KewApiServiceLocator;
024 import org.kuali.rice.kew.api.WorkflowDocument;
025 import org.kuali.rice.kew.api.WorkflowDocumentFactory;
026 import org.kuali.rice.kew.api.document.DocumentStatus;
027 import org.kuali.rice.kew.api.document.DocumentWithContent;
028 import org.kuali.rice.kew.api.document.attribute.DocumentAttribute;
029 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeDataType;
030 import org.kuali.rice.kew.api.document.attribute.DocumentAttributeFactory;
031 import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
032 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
033 import org.kuali.rice.kew.api.document.search.DocumentSearchResult;
034 import org.kuali.rice.kew.api.document.search.DocumentSearchResults;
035 import org.kuali.rice.kew.api.extension.ExtensionDefinition;
036 import org.kuali.rice.kew.doctype.bo.DocumentType;
037 import org.kuali.rice.kew.framework.document.attribute.SearchableAttribute;
038 import org.kuali.rice.kew.framework.document.search.DocumentSearchCustomizerBase;
039 import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValue;
040 import org.kuali.rice.kew.framework.document.search.DocumentSearchResultValues;
041 import org.kuali.rice.kew.service.KEWServiceLocator;
042 import org.kuali.rice.kew.test.KEWTestCase;
043
044 import java.util.ArrayList;
045 import java.util.Collections;
046 import java.util.List;
047
048 import static org.junit.Assert.*;
049
050 /**
051 * An integration test for the DocumentSearchCustomizer class. Includes tests on various aspects of the customzations
052 * that class provides, attempting to use the high-level document search apis to exercise it.
053 *
054 * @author Kuali Rice Team (rice.collab@kuali.org)
055 */
056 public class DocumentSearchCustomizerTest extends KEWTestCase {
057
058 @Override
059 protected void loadTestData() throws Exception {
060 loadXmlFile("DocumentSearchCustomizerTest.xml");
061 }
062
063 @Test
064 public void testCustomizeCriteria() throws Exception {
065
066 String ewestfal = getPrincipalIdForName("ewestfal");
067 DocumentSearchCriteria.Builder builder = DocumentSearchCriteria.Builder.create();
068
069 // first check a full doc search, should return no results
070 DocumentSearchResults results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
071 assertTrue(results.getSearchResults().isEmpty());
072 assertFalse(results.getCriteria().getDocumentStatuses().contains(DocumentStatus.FINAL));
073
074 // now check a document search against the "DocumentSearchCustomizerTest" document type, it is configured with the
075 // CustomizeCriteria customizer
076 builder.setDocumentTypeName("DocumentSearchCustomizerTest");
077
078 results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
079 assertTrue(results.getSearchResults().isEmpty());
080 DocumentSearchCriteria resultCriteria = results.getCriteria();
081 assertTrue("Document Statuses should have contained FINAL, instead contains: " + resultCriteria
082 .getDocumentStatuses(), resultCriteria.getDocumentStatuses().contains(DocumentStatus.FINAL));
083
084 // now route an instance of the CustomizeCriteria document type to FINAL
085 WorkflowDocument document = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("ewestfal"),
086 "DocumentSearchCustomizerTest");
087 document.route("");
088 assertTrue(document.isFinal());
089
090 // now run another search, we should get back one result this time
091 results = KewApiServiceLocator.getWorkflowDocumentService().documentSearch(ewestfal, builder.build());
092 assertEquals(1, results.getSearchResults().size());
093 assertEquals(document.getDocumentId(), results.getSearchResults().get(0).getDocument().getDocumentId());
094 }
095
096 @Test
097 public void testCustomizeClearCriteria() throws Exception {
098
099 // 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.isNotBlank(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 }