Coverage Report - org.kuali.rice.kew.docsearch.DocSearchUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
DocSearchUtils
0%
0/167
0%
0/92
5.462
 
 1  
 /*
 2  
  * Copyright 2005-2007 The Kuali Foundation
 3  
  *
 4  
  *
 5  
  * Licensed under the Educational Community License, Version 2.0 (the "License");
 6  
  * you may not use this file except in compliance with the License.
 7  
  * You may obtain a copy of the License at
 8  
  *
 9  
  * http://www.opensource.org/licenses/ecl2.php
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.kuali.rice.kew.docsearch;
 18  
 
 19  
 import java.sql.Date;
 20  
 import java.sql.Timestamp;
 21  
 import java.util.ArrayList;
 22  
 import java.util.Arrays;
 23  
 import java.util.HashMap;
 24  
 import java.util.Iterator;
 25  
 import java.util.List;
 26  
 import java.util.Map;
 27  
 import java.util.StringTokenizer;
 28  
 
 29  
 import org.apache.commons.lang.StringUtils;
 30  
 import org.kuali.rice.core.api.exception.RiceRuntimeException;
 31  
 import org.kuali.rice.core.api.reflect.ObjectDefinition;
 32  
 import org.kuali.rice.core.api.reflect.ObjectDefinition;
 33  
 import org.kuali.rice.core.framework.resourceloader.ObjectDefinitionResolver;
 34  
 import org.kuali.rice.core.util.ClassLoaderUtils;
 35  
 import org.kuali.rice.core.util.RiceConstants;
 36  
 import org.kuali.rice.kew.docsearch.web.SearchAttributeFormContainer;
 37  
 import org.kuali.rice.kew.doctype.bo.DocumentType;
 38  
 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
 39  
 import org.kuali.rice.kew.exception.WorkflowRuntimeException;
 40  
 import org.kuali.rice.kew.service.KEWServiceLocator;
 41  
 import org.kuali.rice.kew.user.UserUtils;
 42  
 import org.kuali.rice.kns.UserSession;
 43  
 import org.kuali.rice.kns.util.GlobalVariables;
 44  
 import org.kuali.rice.kns.web.ui.Field;
 45  
 import org.kuali.rice.kns.web.ui.Row;
 46  
 
 47  
 
 48  
 /**
 49  
  * Various static utility methods for helping with Searcha.
 50  
  *
 51  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 52  
  */
 53  
 public final class DocSearchUtils {
 54  
 
 55  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocSearchUtils.class);
 56  
 
 57  0
     private DocSearchUtils() {
 58  0
             throw new UnsupportedOperationException("do not call");
 59  
     }
 60  
     
 61  
     public static List<SearchableAttributeValue> getSearchableAttributeValueObjectTypes() {
 62  0
         List<SearchableAttributeValue> searchableAttributeValueClasses = new ArrayList<SearchableAttributeValue>();
 63  0
         for (Object aSEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST : SearchableAttribute.SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST)
 64  
         {
 65  0
             Class searchAttributeValueClass = (Class) aSEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST;
 66  0
             ObjectDefinition objDef = new ObjectDefinition(searchAttributeValueClass);
 67  0
             SearchableAttributeValue attributeValue = (SearchableAttributeValue) ObjectDefinitionResolver.createObject(objDef, ClassLoaderUtils.getDefaultClassLoader(), false);
 68  0
             searchableAttributeValueClasses.add(attributeValue);
 69  0
         }
 70  0
         return searchableAttributeValueClasses;
 71  
     }
 72  
 
 73  
     public static SearchableAttributeValue getSearchableAttributeValueByDataTypeString(String dataType) {
 74  0
         SearchableAttributeValue returnableValue = null;
 75  0
         if (StringUtils.isBlank(dataType)) {
 76  0
             return returnableValue;
 77  
         }
 78  0
         for (SearchableAttributeValue attValue : getSearchableAttributeValueObjectTypes())
 79  
         {
 80  0
             if (dataType.equalsIgnoreCase(attValue.getAttributeDataType()))
 81  
             {
 82  0
                 if (returnableValue != null)
 83  
                 {
 84  0
                     String errorMsg = "Found two SearchableAttributeValue objects with same data type string ('" + dataType + "' while ignoring case):  " + returnableValue.getClass().getName() + " and " + attValue.getClass().getName();
 85  0
                     LOG.error("getSearchableAttributeValueByDataTypeString() " + errorMsg);
 86  0
                     throw new RuntimeException(errorMsg);
 87  
                 }
 88  0
                 LOG.debug("getSearchableAttributeValueByDataTypeString() SearchableAttributeValue class name is " + attValue.getClass().getName() + "... ojbConcreteClassName is " + attValue.getOjbConcreteClass());
 89  0
                 ObjectDefinition objDef = new ObjectDefinition(attValue.getClass());
 90  0
                 returnableValue = (SearchableAttributeValue) ObjectDefinitionResolver.createObject(objDef, ClassLoaderUtils.getDefaultClassLoader(), false);
 91  0
             }
 92  
         }
 93  0
         return returnableValue;
 94  
     }
 95  
 
 96  
 
 97  
     public static String getDisplayValueWithDateOnly(Timestamp value) {
 98  0
         return RiceConstants.getDefaultDateFormat().format(new Date(value.getTime()));
 99  
     }
 100  
 
 101  
     public static String getDisplayValueWithDateTime(Timestamp value) {
 102  0
         return RiceConstants.getDefaultDateAndTimeFormat().format(new Date(value.getTime()));
 103  
     }
 104  
 
 105  
 
 106  
 
 107  
     private static final String CURRENT_USER_PREFIX = "CURRENT_USER.";
 108  
 
 109  
     /**
 110  
      * Build List of searchable attributes from saved searchable attributes string
 111  
      *
 112  
      * @param searchableAttributeString
 113  
      *            String representation of searchable attributes
 114  
      * @param documentTypeName document type name
 115  
      * @return searchable attributes list
 116  
      */
 117  
     public static List<SearchAttributeCriteriaComponent> buildSearchableAttributesFromString(String searchableAttributeString, String documentTypeName) {
 118  0
         List<SearchAttributeCriteriaComponent> searchableAttributes = new ArrayList<SearchAttributeCriteriaComponent>();
 119  0
         Map<String, SearchAttributeCriteriaComponent> criteriaComponentsByKey = new HashMap<String, SearchAttributeCriteriaComponent>();
 120  
 
 121  0
         DocumentType docType = getDocumentType(documentTypeName);
 122  
 
 123  0
         if (docType != null) {
 124  
 
 125  0
             for (SearchableAttribute searchableAttribute : docType.getSearchableAttributes()) {
 126  
                     //KFSMI-1466 - DocumentSearchContext
 127  0
                 for (Row row : searchableAttribute.getSearchingRows(
 128  
                                 DocSearchUtils.getDocumentSearchContext("", docType.getName(), ""))) {
 129  0
                     for (org.kuali.rice.kns.web.ui.Field field : row.getFields()) {
 130  0
                         if (field instanceof Field) {
 131  0
                             SearchableAttributeValue searchableAttributeValue = DocSearchUtils.getSearchableAttributeValueByDataTypeString(field.getFieldDataType());
 132  0
                             SearchAttributeCriteriaComponent sacc = new SearchAttributeCriteriaComponent(field.getPropertyName(), null, field.getPropertyName(), searchableAttributeValue);
 133  0
                             sacc.setRangeSearch(field.isMemberOfRange());
 134  0
                             sacc.setSearchInclusive(field.isInclusive());
 135  0
                             sacc.setSearchable(field.isIndexedForSearch());
 136  0
                             sacc.setLookupableFieldType(field.getFieldType());
 137  0
                             sacc.setCanHoldMultipleValues(Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType()));
 138  0
                             criteriaComponentsByKey.put(field.getPropertyName(), sacc);
 139  0
                         } else {
 140  0
                             throw new RiceRuntimeException("Fields must be of type org.kuali.rice.kew.docsearch.Field");
 141  
                         }
 142  
                     }
 143  
                 }
 144  
             }
 145  
         }
 146  
 
 147  0
         Map<String, List<String>> checkForMultiValueSearchableAttributes = new HashMap<String, List<String>>();
 148  0
         if ((searchableAttributeString != null) && (searchableAttributeString.trim().length() > 0)) {
 149  0
             StringTokenizer tokenizer = new StringTokenizer(searchableAttributeString, ",");
 150  0
             while (tokenizer.hasMoreTokens()) {
 151  0
                 String searchableAttribute = tokenizer.nextToken();
 152  0
                 int index = searchableAttribute.indexOf(":");
 153  0
                 if (index != -1) {
 154  0
                     String key = searchableAttribute.substring(0, index);
 155  
                     // String savedKey = key;
 156  
                     // if (key.indexOf(SearchableAttribute.RANGE_LOWER_BOUND_PROPERTY_PREFIX) == 0) {
 157  
                     // savedKey = key.substring(SearchableAttribute.RANGE_LOWER_BOUND_PROPERTY_PREFIX.length());
 158  
                     // } else if (key.indexOf(SearchableAttribute.RANGE_UPPER_BOUND_PROPERTY_PREFIX) == 0) {
 159  
                     // savedKey = key.substring(SearchableAttribute.RANGE_UPPER_BOUND_PROPERTY_PREFIX.length());
 160  
                     // }
 161  0
                     String value = searchableAttribute.substring(index + 1);
 162  0
                     if (value.startsWith(CURRENT_USER_PREFIX)) {
 163  0
                         String idType = value.substring(CURRENT_USER_PREFIX.length());
 164  0
                         UserSession session = GlobalVariables.getUserSession();
 165  0
                         String idValue = UserUtils.getIdValue(idType, session.getPerson());
 166  0
                         if (!StringUtils.isBlank(idValue)) {
 167  0
                             value = idValue;
 168  
                         }
 169  
                     }
 170  0
                     SearchAttributeCriteriaComponent critComponent = criteriaComponentsByKey.get(key);
 171  0
                     if (critComponent == null) {
 172  
                         // here we potentially have a change to the searchable attributes dealing with naming or ranges... so
 173  
                         // we just ignore the values
 174  0
                         continue;
 175  
                     }
 176  0
                     if (critComponent.getSearchableAttributeValue() == null) {
 177  0
                         String errorMsg = "Cannot find SearchableAttributeValue for given key '" + key + "'";
 178  0
                         LOG.error("buildSearchableAttributesFromString() " + errorMsg);
 179  0
                         throw new RuntimeException(errorMsg);
 180  
                     }
 181  0
                     if (critComponent.isCanHoldMultipleValues()) {
 182  
                         // should be multivalue
 183  0
                         if (checkForMultiValueSearchableAttributes.containsKey(key)) {
 184  0
                             List<String> keyList = checkForMultiValueSearchableAttributes.get(key);
 185  0
                             keyList.add(value);
 186  0
                             checkForMultiValueSearchableAttributes.put(key, keyList);
 187  0
                         } else {
 188  0
                             List<String> tempList = new ArrayList<String>();
 189  0
                             tempList.add(value);
 190  
                             // tempList.addAll(Arrays.asList(new String[]{value}));
 191  0
                             checkForMultiValueSearchableAttributes.put(key, tempList);
 192  0
                             searchableAttributes.add(critComponent);
 193  0
                         }
 194  
                     } else {
 195  
                         // should be single value
 196  0
                         if (checkForMultiValueSearchableAttributes.containsKey(key)) {
 197  
                             // attempting to use multiple values in a field that does not support it
 198  0
                             String error = "Attempting to add multiple values to a search attribute (key: '" + key + "') that does not suppor them";
 199  0
                             LOG.error("buildSearchableAttributesFromString() " + error);
 200  
                             // we don't blow chunks here in case an attribute has been altered from multi-value to
 201  
                             // non-multi-value
 202  
                         }
 203  0
                         critComponent.setValue(value);
 204  0
                         searchableAttributes.add(critComponent);
 205  
                     }
 206  
 
 207  
                 }
 208  0
             }
 209  0
             for (SearchAttributeCriteriaComponent criteriaComponent : searchableAttributes)
 210  
             {
 211  0
                 if (criteriaComponent.isCanHoldMultipleValues())
 212  
                 {
 213  0
                     List<String> values = checkForMultiValueSearchableAttributes.get(criteriaComponent.getFormKey());
 214  0
                     criteriaComponent.setValue(null);
 215  0
                     criteriaComponent.setValues(values);
 216  0
                 }
 217  
             }
 218  
         }
 219  
 
 220  0
         return searchableAttributes;
 221  
     }
 222  
 
 223  
     /**
 224  
      * This method takes the given <code>propertyFields</code> parameter and populates the {@link DocSearchCriteriaDTO}
 225  
      * object search attributes based on the document type name set on the <code>criteria</code> object.<br>
 226  
      * <br>
 227  
      * This is identical to calling {@link #addSearchableAttributesToCriteria(DocSearchCriteriaDTO, List, String, boolean)}
 228  
      * with a boolean value of false for the <code>setAttributesStrictly</code> parameter.
 229  
      *
 230  
      * @param criteria -
 231  
      *            The object that needs a list of {@link SearchAttributeCriteriaComponent} objects set up based on the
 232  
      *            document type name and <code>propertyFields</code> parameter
 233  
      * @param propertyFields -
 234  
      *            The list of {@link SearchAttributeFormContainer} objects that need to be converted to
 235  
      *            {@link SearchAttributeCriteriaComponent} objects and set on the <code>criteria</code> parameter
 236  
      * @param searchAttributesString -
 237  
      *            A potential string that must be parsed to use to set attributes on the <code>criteria</code> object
 238  
      */
 239  
     public static void addSearchableAttributesToCriteria(DocSearchCriteriaDTO criteria, List propertyFields, String searchAttributesString) {
 240  0
         addSearchableAttributesToCriteria(criteria, propertyFields, searchAttributesString, false);
 241  0
     }
 242  
 
 243  
     /**
 244  
      * This method takes the given <code>propertyFields</code> parameter and populates the {@link DocSearchCriteriaDTO}
 245  
      * object search attributes based on the document type name set on the <code>criteria</code> object.<br>
 246  
      * <br>
 247  
      * This is identical to calling {@link #addSearchableAttributesToCriteria(DocSearchCriteriaDTO, List, String, boolean)}
 248  
      * with a null value for the <code>searchAttributesString</code> parameter.
 249  
      *
 250  
      * @param criteria -
 251  
      *            The object that needs a list of {@link SearchAttributeCriteriaComponent} objects set up based on the
 252  
      *            document type name and <code>propertyFields</code> parameter
 253  
      * @param propertyFields -
 254  
      *            The list of {@link SearchAttributeFormContainer} objects that need to be converted to
 255  
      *            {@link SearchAttributeCriteriaComponent} objects and set on the <code>criteria</code> parameter
 256  
      * @param setAttributesStrictly -
 257  
      *            A boolean to specify whether to explicitly throw an error when a given value from
 258  
      *            <code>propertyFields</code> does not match a search attribute on the specified document type. If set to
 259  
      *            true an error with be thrown. If set to false the mismatch will be ignored.
 260  
      */
 261  
     public static void addSearchableAttributesToCriteria(DocSearchCriteriaDTO criteria, List propertyFields, boolean setAttributesStrictly) {
 262  0
         addSearchableAttributesToCriteria(criteria, propertyFields, null, setAttributesStrictly);
 263  0
     }
 264  
 
 265  
     /**
 266  
      * This method takes the given <code>propertyFields</code> parameter and populates the {@link DocSearchCriteriaDTO}
 267  
      * object search attributes based on the document type name set on the <code>criteria</code> object.
 268  
      *
 269  
      * @param criteria -
 270  
      *            The object that needs a list of {@link SearchAttributeCriteriaComponent} objects set up based on the
 271  
      *            document type name and <code>propertyFields</code> parameter
 272  
      * @param propertyFields -
 273  
      *            The list of {@link SearchAttributeFormContainer} objects that need to be converted to
 274  
      *            {@link SearchAttributeCriteriaComponent} objects and set on the <code>criteria</code> parameter
 275  
      * @param searchAttributesString -
 276  
      *            A potential string that must be parsed to use to set attributes on the <code>criteria</code> object
 277  
      * @param setAttributesStrictly -
 278  
      *            A boolean to specify whether to explicitly throw an error when a given value from
 279  
      *            <code>propertyFields</code> does not match a search attribute on the specified document type. If set to
 280  
      *            true an error with be thrown. If set to false the mismatch will be ignored.
 281  
      */
 282  
     public static void addSearchableAttributesToCriteria(DocSearchCriteriaDTO criteria, List propertyFields, String searchAttributesString, boolean setAttributesStrictly) {
 283  0
         if (criteria != null) {
 284  0
             DocumentType docType = getDocumentType(criteria.getDocTypeFullName());
 285  0
             if (docType == null) {
 286  0
                 return;
 287  
             }
 288  0
             criteria.getSearchableAttributes().clear();
 289  0
             Map<String, SearchAttributeCriteriaComponent> urlParameterSearchAttributesByFormKey = new HashMap<String, SearchAttributeCriteriaComponent>();
 290  0
             if (!StringUtils.isBlank(searchAttributesString)) {
 291  0
                 List<SearchAttributeCriteriaComponent> components = buildSearchableAttributesFromString(searchAttributesString, docType.getName());
 292  0
                 for (SearchAttributeCriteriaComponent component : components) {
 293  0
                     urlParameterSearchAttributesByFormKey.put(component.getFormKey(), component);
 294  0
                     criteria.addSearchableAttribute(component);
 295  
                 }
 296  
 //                docSearchForm.setSearchableAttributes(null);
 297  
             }
 298  0
             if (!propertyFields.isEmpty()) {
 299  0
                 Map<String, SearchAttributeCriteriaComponent> criteriaComponentsByFormKey = new HashMap<String, SearchAttributeCriteriaComponent>();
 300  0
                 for (SearchableAttribute searchableAttribute : docType.getSearchableAttributes()) {
 301  
                         //KFSMI-1466 - DocumentSearchContext
 302  0
                     for (Row row : searchableAttribute.getSearchingRows(
 303  
                                     DocSearchUtils.getDocumentSearchContext("", docType.getName(), ""))) {
 304  0
                         for (org.kuali.rice.kns.web.ui.Field field : row.getFields()) {
 305  0
                             if (field instanceof Field) {
 306  0
                                 SearchableAttributeValue searchableAttributeValue = DocSearchUtils.getSearchableAttributeValueByDataTypeString(field.getFieldDataType());
 307  0
                                 SearchAttributeCriteriaComponent sacc = new SearchAttributeCriteriaComponent(field.getPropertyName(), null, field.getPropertyName(), searchableAttributeValue);
 308  0
                                 sacc.setRangeSearch(field.isMemberOfRange());
 309  0
                                 sacc.setSearchInclusive(field.isInclusive());
 310  0
                                 sacc.setLookupableFieldType(field.getFieldType());
 311  0
                                 sacc.setSearchable(field.isIndexedForSearch());
 312  0
                                 sacc.setCanHoldMultipleValues(Field.MULTI_VALUE_FIELD_TYPES.contains(field.getFieldType()));
 313  0
                                 criteriaComponentsByFormKey.put(field.getPropertyName(), sacc);
 314  0
                             } else {
 315  0
                                 throw new RiceRuntimeException("Fields must be of type org.kuali.rice.kew.docsearch.Field");
 316  
                             }
 317  
                         }
 318  
                     }
 319  
                 }
 320  0
                 for (Iterator iterator = propertyFields.iterator(); iterator.hasNext();) {
 321  0
                     SearchAttributeFormContainer propertyField = (SearchAttributeFormContainer) iterator.next();
 322  0
                     SearchAttributeCriteriaComponent sacc = criteriaComponentsByFormKey.get(propertyField.getKey());
 323  0
                     if (sacc != null) {
 324  0
                         if (sacc.getSearchableAttributeValue() == null) {
 325  0
                             String errorMsg = "Searchable attribute with form field key " + sacc.getFormKey() + " does not have a valid SearchableAttributeValue";
 326  0
                             LOG.error("addSearchableAttributesToCriteria() " + errorMsg);
 327  0
                             throw new RuntimeException(errorMsg);
 328  
                         }
 329  
                         // if the url parameter has already set up the search attribute change the propertyField
 330  0
                         if (urlParameterSearchAttributesByFormKey.containsKey(sacc.getFormKey())) {
 331  0
                             setupPropertyField(urlParameterSearchAttributesByFormKey.get(sacc.getFormKey()), propertyFields);
 332  
                         } else {
 333  
                             //if ((Field.CHECKBOX_YES_NO.equals(sacc.getLookupableFieldType())) && (!propertyField.isValueSet())) {
 334  
                                 // value was not set on the form so we must use the alternate value which for checkbox is the
 335  
                                 // 'unchecked' value
 336  
                             //    sacc.setValue(propertyField.getAlternateValue());
 337  
                             //} else
 338  0
                             if (Field.MULTI_VALUE_FIELD_TYPES.contains(sacc.getLookupableFieldType())) {
 339  
                                 // set the multivalue lookup indicator
 340  0
                                 sacc.setCanHoldMultipleValues(true);
 341  0
                                 if (propertyField.getValues() == null) {
 342  0
                                     sacc.setValues(new ArrayList<String>());
 343  
                                 } else {
 344  0
                                     sacc.setValues(Arrays.asList(propertyField.getValues()));
 345  
                                 }
 346  
                             } else {
 347  0
                                 sacc.setValue(propertyField.getValue());
 348  
                             }
 349  0
                             criteria.addSearchableAttribute(sacc);
 350  
                         }
 351  
                     } else {
 352  0
                         if (setAttributesStrictly) {
 353  0
                             String message = "Cannot find matching search attribute with key '" + propertyField.getKey() + "' on document type '" + docType.getName() + "'";
 354  0
                             LOG.error(message);
 355  0
                             throw new WorkflowRuntimeException(message);
 356  
                         }
 357  
                     }
 358  0
                 }
 359  
             }
 360  
         }
 361  0
     }
 362  
 
 363  
     public static void setupPropertyField(SearchAttributeCriteriaComponent searchableAttribute, List propertyFields) {
 364  0
         SearchAttributeFormContainer propertyField = getPropertyField(searchableAttribute.getFormKey(), propertyFields);
 365  0
         if (propertyField != null) {
 366  0
             propertyField.setValue(searchableAttribute.getValue());
 367  0
             if (searchableAttribute.getValues() != null) {
 368  0
                 propertyField.setValues(searchableAttribute.getValues().toArray(new String[searchableAttribute.getValues().size()]));
 369  
             }
 370  
         }
 371  0
     }
 372  
 
 373  
     public static SearchAttributeFormContainer getPropertyField(String key, List propertyFields) {
 374  0
         if (StringUtils.isBlank(key)) {
 375  0
             return null;
 376  
         }
 377  0
         for (Iterator iter = propertyFields.iterator(); iter.hasNext();) {
 378  0
             SearchAttributeFormContainer container = (SearchAttributeFormContainer) iter.next();
 379  0
             if (key.equals(container.getKey())) {
 380  0
                 return container;
 381  
             }
 382  0
         }
 383  0
         return null;
 384  
     }
 385  
 
 386  
     private static DocumentType getDocumentType(String docTypeName) {
 387  0
         if ((docTypeName != null && !"".equals(docTypeName))) {
 388  0
             return ((DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE)).findByName(docTypeName);
 389  
         }
 390  0
         return null;
 391  
     }
 392  
 
 393  
     public static DocumentSearchContext getDocumentSearchContext(String documentId, String documentTypeName, String documentContent){
 394  0
             DocumentSearchContext documentSearchContext = new DocumentSearchContext();
 395  0
             documentSearchContext.setDocumentId(documentId);
 396  0
             documentSearchContext.setDocumentTypeName(documentTypeName);
 397  0
             documentSearchContext.setDocumentContent(documentContent);
 398  0
             return documentSearchContext;
 399  
     }
 400  
 }