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