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 }