Coverage Report - org.kuali.rice.kew.docsearch.DocumentSearchInternalUtils
 
Classes in this File Line Coverage Branch Coverage Complexity
DocumentSearchInternalUtils
0%
0/115
0%
0/44
3
DocumentSearchInternalUtils$SearchableAttributeConfiguration
0%
0/8
N/A
3
 
 1  
 /**
 2  
  * Copyright 2005-2011 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  
 package org.kuali.rice.kew.docsearch;
 17  
 
 18  
 import org.apache.commons.lang.StringUtils;
 19  
 import org.apache.log4j.Logger;
 20  
 import org.codehaus.jackson.map.ObjectMapper;
 21  
 import org.codehaus.jackson.map.annotate.JsonSerialize;
 22  
 import org.joda.time.DateTime;
 23  
 import org.joda.time.MutableDateTime;
 24  
 import org.kuali.rice.core.api.CoreApiServiceLocator;
 25  
 import org.kuali.rice.core.api.reflect.ObjectDefinition;
 26  
 import org.kuali.rice.core.api.search.SearchOperator;
 27  
 import org.kuali.rice.core.api.uif.AttributeLookupSettings;
 28  
 import org.kuali.rice.core.api.uif.DataType;
 29  
 import org.kuali.rice.core.api.uif.RemotableAttributeField;
 30  
 import org.kuali.rice.core.api.util.ClassLoaderUtils;
 31  
 import org.kuali.rice.core.api.util.RiceConstants;
 32  
 import org.kuali.rice.core.framework.resourceloader.ObjectDefinitionResolver;
 33  
 import org.kuali.rice.kew.api.document.search.DocumentSearchCriteria;
 34  
 
 35  
 import java.io.IOException;
 36  
 import java.sql.Date;
 37  
 import java.sql.Timestamp;
 38  
 import java.text.ParseException;
 39  
 import java.util.ArrayList;
 40  
 import java.util.EnumSet;
 41  
 import java.util.List;
 42  
 
 43  
 /**
 44  
  * Defines various utilities for internal use in the reference implementation of the document search functionality.
 45  
  *
 46  
  * @author Kuali Rice Team (rice.collab@kuali.org)
 47  
  */
 48  0
 public class DocumentSearchInternalUtils {
 49  
 
 50  0
     private static final Logger LOG = Logger.getLogger(DocumentSearchInternalUtils.class);
 51  
 
 52  
     private static final boolean CASE_SENSITIVE_DEFAULT = false;
 53  
 
 54  
     private static final String STRING_ATTRIBUTE_TABLE_NAME = "KREW_DOC_HDR_EXT_T";
 55  
     private static final String DATE_TIME_ATTRIBUTE_TABLE_NAME = "KREW_DOC_HDR_EXT_DT_T";
 56  
     private static final String DECIMAL_ATTRIBUTE_TABLE_NAME = "KREW_DOC_HDR_EXT_FLT_T";
 57  
     private static final String INTEGER_ATTRIBUTE_TABLE_NAME = "KREW_DOC_HDR_EXT_LONG_T";
 58  
 
 59  0
     private static final List<SearchableAttributeConfiguration> CONFIGURATIONS =
 60  
             new ArrayList<SearchableAttributeConfiguration>();
 61  0
     public static final List<Class<? extends SearchableAttributeValue>> SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST =
 62  
             new ArrayList<Class<? extends SearchableAttributeValue>>();
 63  
     static {
 64  0
         SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST.add(SearchableAttributeStringValue.class);
 65  0
         SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST.add(SearchableAttributeFloatValue.class);
 66  0
         SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST.add(SearchableAttributeLongValue.class);
 67  0
         SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST.add(SearchableAttributeDateTimeValue.class);
 68  
     }
 69  
 
 70  
     static {
 71  
 
 72  0
         CONFIGURATIONS.add(new SearchableAttributeConfiguration(
 73  
                 STRING_ATTRIBUTE_TABLE_NAME,
 74  
                 EnumSet.of(DataType.BOOLEAN, DataType.STRING, DataType.MARKUP),
 75  
                 String.class));
 76  
 
 77  0
         CONFIGURATIONS.add(new SearchableAttributeConfiguration(
 78  
                 DATE_TIME_ATTRIBUTE_TABLE_NAME,
 79  
                 EnumSet.of(DataType.DATE, DataType.TRUNCATED_DATE),
 80  
                 Timestamp.class));
 81  
 
 82  0
         CONFIGURATIONS.add(new SearchableAttributeConfiguration(
 83  
                 DECIMAL_ATTRIBUTE_TABLE_NAME,
 84  
                 EnumSet.of(DataType.FLOAT, DataType.DOUBLE),
 85  
                 Float.TYPE));
 86  
 
 87  0
         CONFIGURATIONS.add(new SearchableAttributeConfiguration(
 88  
                 INTEGER_ATTRIBUTE_TABLE_NAME,
 89  
                 EnumSet.of(DataType.INTEGER, DataType.LONG),
 90  
                 Long.TYPE));
 91  
 
 92  0
     }
 93  
 
 94  
     public static boolean isLookupCaseSensitive(RemotableAttributeField remotableAttributeField) {
 95  0
         if (remotableAttributeField == null) {
 96  0
             throw new IllegalArgumentException("remotableAttributeField was null");
 97  
         }
 98  0
         AttributeLookupSettings lookupSettings = remotableAttributeField.getAttributeLookupSettings();
 99  0
         if (lookupSettings != null) {
 100  0
             if (lookupSettings.isCaseSensitive() != null) {
 101  0
                 return lookupSettings.isCaseSensitive().booleanValue();
 102  
             }
 103  
         }
 104  0
         return CASE_SENSITIVE_DEFAULT;
 105  
     }
 106  
 
 107  
     public static String getAttributeTableName(RemotableAttributeField attributeField) {
 108  0
         return getConfigurationForField(attributeField).getTableName();
 109  
     }
 110  
 
 111  
     public static Class<?> getDataTypeClass(RemotableAttributeField attributeField) {
 112  0
         return getConfigurationForField(attributeField).getDataTypeClass();
 113  
     }
 114  
 
 115  
     private static SearchableAttributeConfiguration getConfigurationForField(RemotableAttributeField attributeField) {
 116  0
         for (SearchableAttributeConfiguration configuration : CONFIGURATIONS) {
 117  0
             DataType dataType = attributeField.getDataType();
 118  0
             if (dataType == null) {
 119  0
                 dataType = DataType.STRING;
 120  
             }
 121  0
             if (configuration.getSupportedDataTypes().contains(dataType))  {
 122  0
                 return configuration;
 123  
             }
 124  0
         }
 125  0
         throw new IllegalArgumentException("Failed to determine proper searchable attribute configuration for given data type of '" + attributeField.getDataType() + "'");
 126  
     }
 127  
 
 128  
     public static List<SearchableAttributeValue> getSearchableAttributeValueObjectTypes() {
 129  0
         List<SearchableAttributeValue> searchableAttributeValueClasses = new ArrayList<SearchableAttributeValue>();
 130  0
         for (Class<? extends SearchableAttributeValue> searchAttributeValueClass : SEARCHABLE_ATTRIBUTE_BASE_CLASS_LIST) {
 131  0
             ObjectDefinition objDef = new ObjectDefinition(searchAttributeValueClass);
 132  0
             SearchableAttributeValue attributeValue = (SearchableAttributeValue) ObjectDefinitionResolver.createObject(
 133  
                     objDef, ClassLoaderUtils.getDefaultClassLoader(), false);
 134  0
             searchableAttributeValueClasses.add(attributeValue);
 135  0
         }
 136  0
         return searchableAttributeValueClasses;
 137  
     }
 138  
 
 139  
     public static SearchableAttributeValue getSearchableAttributeValueByDataTypeString(String dataType) {
 140  0
         SearchableAttributeValue returnableValue = null;
 141  0
         if (StringUtils.isBlank(dataType)) {
 142  0
             return returnableValue;
 143  
         }
 144  0
         for (SearchableAttributeValue attValue : getSearchableAttributeValueObjectTypes())
 145  
         {
 146  0
             if (dataType.equalsIgnoreCase(attValue.getAttributeDataType()))
 147  
             {
 148  0
                 if (returnableValue != null)
 149  
                 {
 150  0
                     String errorMsg = "Found two SearchableAttributeValue objects with same data type string ('" + dataType + "' while ignoring case):  " + returnableValue.getClass().getName() + " and " + attValue.getClass().getName();
 151  0
                     LOG.error("getSearchableAttributeValueByDataTypeString() " + errorMsg);
 152  0
                     throw new RuntimeException(errorMsg);
 153  
                 }
 154  0
                 LOG.debug("getSearchableAttributeValueByDataTypeString() SearchableAttributeValue class name is " + attValue.getClass().getName() + "... ojbConcreteClassName is " + attValue.getOjbConcreteClass());
 155  0
                 ObjectDefinition objDef = new ObjectDefinition(attValue.getClass());
 156  0
                 returnableValue = (SearchableAttributeValue) ObjectDefinitionResolver.createObject(objDef, ClassLoaderUtils.getDefaultClassLoader(), false);
 157  0
             }
 158  
         }
 159  0
         return returnableValue;
 160  
     }
 161  
 
 162  
     public static String getDisplayValueWithDateOnly(DateTime value) {
 163  0
         return getDisplayValueWithDateOnly(new Timestamp(value.getMillis()));
 164  
     }
 165  
 
 166  
     public static String getDisplayValueWithDateOnly(Timestamp value) {
 167  0
         return RiceConstants.getDefaultDateFormat().format(new Date(value.getTime()));
 168  
     }
 169  
 
 170  
     public static DateTime getLowerDateTimeBound(String dateRange) throws ParseException {
 171  0
         Range range = parseRange(dateRange);
 172  0
         if (range == null) {
 173  0
             throw new IllegalArgumentException("Failed to parse date range from given string: " + dateRange);
 174  
         }
 175  0
         if (range.getLowerBoundValue() != null) {
 176  0
             java.util.Date lowerRangeDate = CoreApiServiceLocator.getDateTimeService().convertToDate(range.getLowerBoundValue());
 177  0
             MutableDateTime dateTime = new MutableDateTime(lowerRangeDate);
 178  0
             dateTime.setMillisOfDay(0);
 179  0
             return dateTime.toDateTime();
 180  
         }
 181  0
         return null;
 182  
     }
 183  
 
 184  
     public static DateTime getUpperDateTimeBound(String dateRange) throws ParseException {
 185  0
         Range range = parseRange(dateRange);
 186  0
         if (range == null) {
 187  0
             throw new IllegalArgumentException("Failed to parse date range from given string: " + dateRange);
 188  
         }
 189  0
         if (range.getUpperBoundValue() != null) {
 190  0
             java.util.Date upperRangeDate = CoreApiServiceLocator.getDateTimeService().convertToDate(range.getUpperBoundValue());
 191  0
             MutableDateTime dateTime = new MutableDateTime(upperRangeDate);
 192  
             // set it to the last millisecond of the day
 193  0
             dateTime.setMillisOfDay((24 * 60 * 60 * 1000) - 1);
 194  0
             return dateTime.toDateTime();
 195  
         }
 196  0
         return null;
 197  
     }
 198  
 
 199  
     public static Range parseRange(String rangeString) {
 200  0
         if (StringUtils.isBlank(rangeString)) {
 201  0
             throw new IllegalArgumentException("rangeString was null or blank");
 202  
         }
 203  0
         Range range = new Range();
 204  0
         rangeString = rangeString.trim();
 205  0
         if (rangeString.startsWith(SearchOperator.LESS_THAN_EQUAL.op())) {
 206  0
             rangeString = StringUtils.remove(rangeString, SearchOperator.LESS_THAN_EQUAL.op()).trim();
 207  0
             range.setUpperBoundValue(rangeString);
 208  0
             range.setUpperBoundInclusive(true);
 209  0
         } else if (rangeString.startsWith(SearchOperator.LESS_THAN.op())) {
 210  0
             rangeString = StringUtils.remove(rangeString, SearchOperator.LESS_THAN.op()).trim();
 211  0
             range.setUpperBoundValue(rangeString);
 212  0
             range.setUpperBoundInclusive(false);
 213  0
         } else if (rangeString.startsWith(SearchOperator.GREATER_THAN_EQUAL.op())) {
 214  0
             rangeString = StringUtils.remove(rangeString, SearchOperator.GREATER_THAN_EQUAL.op()).trim();
 215  0
             range.setLowerBoundValue(rangeString);
 216  0
             range.setLowerBoundInclusive(true);
 217  0
         } else if (rangeString.startsWith(SearchOperator.GREATER_THAN.op())) {
 218  0
             rangeString = StringUtils.remove(rangeString, SearchOperator.GREATER_THAN.op()).trim();
 219  0
             range.setLowerBoundValue(rangeString);
 220  0
             range.setLowerBoundInclusive(false);
 221  0
         } else if (rangeString.contains(SearchOperator.BETWEEN_EXCLUSIVE_UPPER.op())) {
 222  0
             String[] rangeBounds = StringUtils.split(rangeString, SearchOperator.BETWEEN_EXCLUSIVE_UPPER.op());
 223  0
             range.setLowerBoundValue(rangeBounds[0]);
 224  0
             range.setLowerBoundInclusive(true);
 225  0
             range.setUpperBoundValue(rangeBounds[1]);
 226  0
             range.setUpperBoundInclusive(false);
 227  0
         } else if (rangeString.contains(SearchOperator.BETWEEN.op())) {
 228  0
             String[] rangeBounds = StringUtils.split(rangeString, SearchOperator.BETWEEN.op());
 229  0
             range.setLowerBoundValue(rangeBounds[0]);
 230  0
             range.setLowerBoundInclusive(true);
 231  0
             range.setUpperBoundValue(rangeBounds[1]);
 232  0
             range.setUpperBoundInclusive(true);
 233  0
         } else {
 234  
             // if it has no range specification, return null
 235  0
             return null;
 236  
         }
 237  0
         return range;
 238  
     }
 239  
 
 240  0
     public static class SearchableAttributeConfiguration {
 241  
 
 242  
         private final String tableName;
 243  
         private final EnumSet<DataType> supportedDataTypes;
 244  
         private final Class<?> dataTypeClass;
 245  
 
 246  
         public SearchableAttributeConfiguration(String tableName,
 247  
                 EnumSet<DataType> supportedDataTypes,
 248  0
                 Class<?> dataTypeClass) {
 249  0
             this.tableName = tableName;
 250  0
             this.supportedDataTypes = supportedDataTypes;
 251  0
             this.dataTypeClass = dataTypeClass;
 252  0
         }
 253  
 
 254  
         public String getTableName() {
 255  0
             return tableName;
 256  
         }
 257  
 
 258  
         public EnumSet<DataType> getSupportedDataTypes() {
 259  0
             return supportedDataTypes;
 260  
         }
 261  
 
 262  
         public Class<?> getDataTypeClass() {
 263  0
             return dataTypeClass;
 264  
         }
 265  
 
 266  
     }
 267  
 
 268  
     /**
 269  
      * Unmarshals a DocumentSearchCriteria from JSON string
 270  
      * @param string the JSON
 271  
      * @return unmarshalled DocumentSearchCriteria
 272  
      * @throws IOException
 273  
      */
 274  
     public static DocumentSearchCriteria unmarshalDocumentSearchCriteria(String string) throws IOException {
 275  0
         ObjectMapper jsonMapper = new ObjectMapper();
 276  0
         jsonMapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
 277  0
         DocumentSearchCriteria.Builder builder = (DocumentSearchCriteria.Builder) jsonMapper.readValue(string, DocumentSearchCriteria.Builder.class); // see JacksonRiceModule for details of unmarshalling
 278  
         // fix up the Joda DateTimes
 279  0
         builder.normalizeDateTimes();
 280  
         // build() it
 281  0
         return builder.build();
 282  
     }
 283  
 
 284  
     /**
 285  
      * Marshals a DocumentSearchCriteria to JSON string
 286  
      * @param criteria the criteria
 287  
      * @return a JSON string
 288  
      * @throws IOException
 289  
      */
 290  
     public static String marshalDocumentSearchCriteria(DocumentSearchCriteria criteria) throws IOException {
 291  0
         ObjectMapper jsonMapper = new ObjectMapper();
 292  0
         jsonMapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
 293  
         // Jackson XC support not included by Rice, so no auto-magic JAXB-compatibility
 294  
         // AnnotationIntrospector introspector = new JaxbAnnotationIntrospector();
 295  
         // // make deserializer use JAXB annotations (only)
 296  
         // mapper.getDeserializationConfig().setAnnotationIntrospector(introspector);
 297  
         // // make serializer use JAXB annotations (only)
 298  
         // mapper.getSerializationConfig().setAnnotationIntrospector(introspector);
 299  0
         return jsonMapper.writeValueAsString(criteria);
 300  
     }
 301  
 }