Coverage Report - org.kuali.rice.krad.dao.impl.LookupDaoOjb
 
Classes in this File Line Coverage Branch Coverage Complexity
LookupDaoOjb
0%
0/310
0%
0/206
6.36
 
 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.krad.dao.impl;
 17  
 
 18  
 import org.apache.commons.beanutils.PropertyUtils;
 19  
 import org.apache.commons.lang.StringUtils;
 20  
 import org.apache.ojb.broker.query.Criteria;
 21  
 import org.apache.ojb.broker.query.Query;
 22  
 import org.apache.ojb.broker.query.QueryByCriteria;
 23  
 import org.apache.ojb.broker.query.QueryFactory;
 24  
 import org.kuali.rice.core.api.datetime.DateTimeService;
 25  
 import org.kuali.rice.core.api.search.SearchOperator;
 26  
 import org.kuali.rice.core.api.util.RiceKeyConstants;
 27  
 import org.kuali.rice.core.api.util.type.TypeUtils;
 28  
 import org.kuali.rice.core.framework.persistence.ojb.conversion.OjbCharBooleanConversion;
 29  
 import org.kuali.rice.core.framework.persistence.ojb.dao.PlatformAwareDaoBaseOjb;
 30  
 import org.kuali.rice.krad.bo.BusinessObject;
 31  
 import org.kuali.rice.krad.bo.InactivatableFromTo;
 32  
 import org.kuali.rice.krad.dao.LookupDao;
 33  
 import org.kuali.rice.krad.lookup.CollectionIncomplete;
 34  
 import org.kuali.rice.krad.lookup.LookupUtils;
 35  
 import org.kuali.rice.krad.service.DataDictionaryService;
 36  
 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
 37  
 import org.kuali.rice.krad.service.PersistenceStructureService;
 38  
 import org.kuali.rice.krad.util.GlobalVariables;
 39  
 import org.kuali.rice.krad.util.KRADConstants;
 40  
 import org.kuali.rice.krad.util.KRADPropertyConstants;
 41  
 import org.kuali.rice.krad.util.ObjectUtils;
 42  
 import org.springframework.dao.DataIntegrityViolationException;
 43  
 import org.springmodules.orm.ojb.OjbOperationException;
 44  
 
 45  
 import java.math.BigDecimal;
 46  
 import java.sql.Timestamp;
 47  
 import java.text.ParseException;
 48  
 import java.util.ArrayList;
 49  
 import java.util.Collection;
 50  
 import java.util.Iterator;
 51  
 import java.util.List;
 52  
 import java.util.Map;
 53  
 
 54  
 /**
 55  
  * OJB implementation of the LookupDao interface
 56  
  */
 57  0
 public class LookupDaoOjb extends PlatformAwareDaoBaseOjb implements LookupDao {
 58  0
     private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupDaoOjb.class);
 59  
     private DateTimeService dateTimeService;
 60  
     private PersistenceStructureService persistenceStructureService;
 61  
     private DataDictionaryService dataDictionaryService;
 62  
 
 63  
     public Collection findCollectionBySearchHelper(Class businessObjectClass, Map formProps, boolean unbounded, boolean usePrimaryKeyValuesOnly) {
 64  0
         BusinessObject businessObject = checkBusinessObjectClass(businessObjectClass);
 65  0
         if (usePrimaryKeyValuesOnly) {
 66  0
                 return executeSearch(businessObjectClass, getCollectionCriteriaFromMapUsingPrimaryKeysOnly(businessObjectClass, formProps), unbounded);
 67  
         }
 68  
         
 69  0
                 Criteria crit = getCollectionCriteriaFromMap(businessObject, formProps);
 70  0
                 return executeSearch(businessObjectClass, crit, unbounded);
 71  
         }
 72  
 
 73  
     /**
 74  
      * Builds up criteria object based on the object and map.
 75  
      */
 76  
     public Criteria getCollectionCriteriaFromMap(BusinessObject example, Map formProps) {
 77  0
         Criteria criteria = new Criteria();
 78  0
         Iterator propsIter = formProps.keySet().iterator();
 79  0
         while (propsIter.hasNext()) {
 80  0
             String propertyName = (String) propsIter.next();
 81  0
             Boolean caseInsensitive = Boolean.TRUE;
 82  0
                 if ( KRADServiceLocatorWeb.getDataDictionaryService().isAttributeDefined( example.getClass(), propertyName )) {
 83  
                         // If forceUppercase is true, both the database value and the user entry should be converted to Uppercase -- so change the caseInsensitive to false since we don't need to 
 84  
                         // worry about the values not matching.  However, if forceUppercase is false, make sure to do a caseInsensitive search because the database value and user entry 
 85  
                         // could be mixed case.  Thus, caseInsensitive will be the opposite of forceUppercase. 
 86  0
                         caseInsensitive = !KRADServiceLocatorWeb.getDataDictionaryService().getAttributeForceUppercase( example.getClass(), propertyName );
 87  
                 }
 88  0
                 if ( caseInsensitive == null ) { caseInsensitive = Boolean.TRUE; }
 89  0
                 boolean treatWildcardsAndOperatorsAsLiteral = KRADServiceLocatorWeb
 90  
                                 .getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(example.getClass(), propertyName);
 91  
                 
 92  0
             if (formProps.get(propertyName) instanceof Collection) {
 93  0
                 Iterator iter = ((Collection) formProps.get(propertyName)).iterator();
 94  0
                 while (iter.hasNext()) {
 95  0
                     String searchValue = (String) iter.next();
 96  0
                             if (!caseInsensitive) { 
 97  
                                     // Verify that the searchValue is uppercased if caseInsensitive is false 
 98  0
                                     searchValue = searchValue.toUpperCase(); 
 99  
                             }
 100  0
                     if (!createCriteria(example, searchValue, propertyName, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria, formProps )) {
 101  0
                         throw new RuntimeException("Invalid value in Collection");
 102  
                     }
 103  0
                 }
 104  0
             }
 105  
             else {
 106  0
                 String searchValue = (String) formProps.get(propertyName);
 107  0
                         if (!caseInsensitive) { 
 108  
                                 // Verify that the searchValue is uppercased if caseInsensitive is false 
 109  0
                                 searchValue = searchValue.toUpperCase(); 
 110  
                         }
 111  0
                 if (!createCriteria(example, searchValue, propertyName, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria, formProps)) {
 112  0
                     continue;
 113  
                 }
 114  
             }
 115  0
         }
 116  0
         return criteria;
 117  
     }
 118  
     
 119  
     public Criteria getCollectionCriteriaFromMapUsingPrimaryKeysOnly(Class businessObjectClass, Map formProps) {
 120  0
         BusinessObject businessObject = checkBusinessObjectClass(businessObjectClass);
 121  0
         Criteria criteria = new Criteria();
 122  0
         List pkFields = KRADServiceLocatorWeb.getDataObjectMetaDataService().listPrimaryKeyFieldNames(businessObjectClass);
 123  0
         Iterator pkIter = pkFields.iterator();
 124  0
         while (pkIter.hasNext()) {
 125  0
             String pkFieldName = (String) pkIter.next();
 126  0
             String pkValue = (String) formProps.get(pkFieldName);
 127  
 
 128  0
             if (StringUtils.isBlank(pkValue)) {
 129  0
                 throw new RuntimeException("Missing pk value for field " + pkFieldName + " when a search based on PK values only is performed.");
 130  
             }
 131  
             else {
 132  0
                 for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
 133  0
                     if (pkValue.contains(op.op())) {
 134  0
                         throw new RuntimeException("Value \"" + pkValue + "\" for PK field " + pkFieldName + " contains wildcard/operator characters.");
 135  
                     }
 136  
                 }
 137  
             }
 138  0
             boolean treatWildcardsAndOperatorsAsLiteral = KRADServiceLocatorWeb.
 139  
                             getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(businessObjectClass, pkFieldName);
 140  0
             createCriteria(businessObject, pkValue, pkFieldName, false, treatWildcardsAndOperatorsAsLiteral, criteria);
 141  0
         }
 142  0
         return criteria;
 143  
     }
 144  
     
 145  
     private BusinessObject checkBusinessObjectClass(Class businessObjectClass) {
 146  0
         if (businessObjectClass == null) {
 147  0
             throw new IllegalArgumentException("BusinessObject class passed to LookupDaoOjb findCollectionBySearchHelper... method was null");
 148  
         }
 149  0
         BusinessObject businessObject = null;
 150  
         try {
 151  0
             businessObject = (BusinessObject) businessObjectClass.newInstance();
 152  
         }
 153  0
         catch (IllegalAccessException e) {
 154  0
             throw new RuntimeException("LookupDaoOjb could not get instance of " + businessObjectClass.getName(), e);
 155  
         }
 156  0
         catch (InstantiationException e) {
 157  0
             throw new RuntimeException("LookupDaoOjb could not get instance of " + businessObjectClass.getName(), e);
 158  0
         }
 159  0
         return businessObject;
 160  
     }
 161  
 
 162  
     private Collection executeSearch(Class businessObjectClass, Criteria criteria, boolean unbounded) {
 163  0
             Collection searchResults = new ArrayList();
 164  0
             Long matchingResultsCount = null;
 165  
             try {
 166  0
                     Integer searchResultsLimit = org.kuali.rice.kns.lookup.LookupUtils
 167  
                     .getSearchResultsLimit(businessObjectClass);
 168  
                     // A negative number in searchResultsLimit means the search results should be unlimited.
 169  0
             if (!unbounded && (searchResultsLimit != null) && searchResultsLimit >= 0) {
 170  0
                             matchingResultsCount = new Long(getPersistenceBrokerTemplate().getCount(QueryFactory.newQuery(businessObjectClass, criteria)));
 171  0
                             org.kuali.rice.kns.lookup.LookupUtils
 172  
                         .applySearchResultsLimit(businessObjectClass, criteria, getDbPlatform());
 173  
                     }
 174  0
                     if ((matchingResultsCount == null) || (matchingResultsCount.intValue() <= searchResultsLimit.intValue())) {
 175  0
                             matchingResultsCount = new Long(0);
 176  
                     }
 177  0
                     searchResults = getPersistenceBrokerTemplate().getCollectionByQuery(QueryFactory.newQuery(businessObjectClass, criteria));
 178  
                     // populate Person objects in business objects
 179  0
                     List bos = new ArrayList();
 180  0
                     bos.addAll(searchResults);
 181  0
                     searchResults = bos;
 182  
             }
 183  0
             catch (OjbOperationException e) {
 184  0
                     throw new RuntimeException("LookupDaoOjb encountered exception during executeSearch", e);
 185  
             }
 186  0
             catch (DataIntegrityViolationException e) {
 187  0
                     throw new RuntimeException("LookupDaoOjb encountered exception during executeSearch", e);
 188  0
             }
 189  0
             return new CollectionIncomplete(searchResults, matchingResultsCount);
 190  
     }
 191  
 
 192  
     public boolean createCriteria(Object example, String searchValue, String propertyName, Object criteria) {
 193  0
             return createCriteria( example, searchValue, propertyName, false, false, criteria );
 194  
     }
 195  
     
 196  
     public boolean createCriteria(Object example, String searchValue, String propertyName, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Object criteria) {
 197  0
             return createCriteria( example, searchValue, propertyName, false, false, criteria, null );
 198  
     }
 199  
 
 200  
     public boolean createCriteria(Object example, String searchValue, String propertyName, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Object criteria, Map searchValues) {
 201  
         // if searchValue is empty and the key is not a valid property ignore
 202  0
         if (!(criteria instanceof Criteria) || StringUtils.isBlank(searchValue) || !ObjectUtils.isWriteable(example, propertyName, persistenceStructureService)) {
 203  0
             return false;
 204  
         }
 205  
 
 206  
         // get property type which is used to determine type of criteria
 207  0
         Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
 208  0
         if (propertyType == null) {
 209  0
             return false;
 210  
         }
 211  
 
 212  
                 // build criteria
 213  0
                 if (example instanceof InactivatableFromTo) {
 214  0
                         if (KRADPropertyConstants.ACTIVE.equals(propertyName)) {
 215  0
                                 addInactivateableFromToActiveCriteria(example, searchValue, (Criteria) criteria, searchValues);
 216  0
                         } else if (KRADPropertyConstants.CURRENT.equals(propertyName)) {
 217  0
                                 addInactivateableFromToCurrentCriteria(example, searchValue, (Criteria) criteria, searchValues);
 218  0
                         } else if (!KRADPropertyConstants.ACTIVE_AS_OF_DATE.equals(propertyName)) {
 219  0
                                 addCriteria(propertyName, searchValue, propertyType, caseInsensitive,
 220  
                                                 treatWildcardsAndOperatorsAsLiteral, (Criteria) criteria);
 221  
                         }
 222  
                 } else {
 223  0
                         addCriteria(propertyName, searchValue, propertyType, caseInsensitive, treatWildcardsAndOperatorsAsLiteral,
 224  
                                         (Criteria) criteria);
 225  
                 }
 226  
         
 227  0
         return true;
 228  
     }
 229  
 
 230  
     /**
 231  
      * Find count of records meeting criteria based on the object and map.
 232  
      */
 233  
     public Long findCountByMap(Object example, Map formProps) {
 234  0
         Criteria criteria = new Criteria();
 235  
         // iterate through the parameter map for key values search criteria
 236  0
         Iterator propsIter = formProps.keySet().iterator();
 237  0
         while (propsIter.hasNext()) {
 238  0
             String propertyName = (String) propsIter.next();
 239  0
             String searchValue = (String) formProps.get(propertyName);
 240  
 
 241  
             // if searchValue is empty and the key is not a valid property ignore
 242  0
             if (StringUtils.isBlank(searchValue) || !(PropertyUtils.isWriteable(example, propertyName))) {
 243  0
                 continue;
 244  
             }
 245  
 
 246  
             // get property type which is used to determine type of criteria
 247  0
             Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
 248  0
             if (propertyType == null) {
 249  0
                 continue;
 250  
             }
 251  0
                 Boolean caseInsensitive = Boolean.TRUE;
 252  0
                 if ( KRADServiceLocatorWeb.getDataDictionaryService().isAttributeDefined( example.getClass(), propertyName )) {
 253  0
                         caseInsensitive = !KRADServiceLocatorWeb.getDataDictionaryService().getAttributeForceUppercase( example.getClass(), propertyName );
 254  
                 }
 255  0
                 if ( caseInsensitive == null ) { caseInsensitive = Boolean.TRUE; }
 256  
 
 257  0
                 boolean treatWildcardsAndOperatorsAsLiteral = KRADServiceLocatorWeb
 258  
                                         .getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(example.getClass(), propertyName);
 259  
                 
 260  0
                     if (!caseInsensitive) { 
 261  
                             // Verify that the searchValue is uppercased if caseInsensitive is false 
 262  0
                             searchValue = searchValue.toUpperCase(); 
 263  
                     }
 264  
                 
 265  
             // build criteria
 266  0
             addCriteria(propertyName, searchValue, propertyType, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria);
 267  0
         }
 268  
 
 269  
         // execute query and return result list
 270  0
         Query query = QueryFactory.newQuery(example.getClass(), criteria);
 271  
 
 272  0
         return new Long(getPersistenceBrokerTemplate().getCount(query));
 273  
     }
 274  
 
 275  
     /**
 276  
      * @see org.kuali.rice.krad.dao.LookupDao#findObjectByMap(java.lang.Object, java.util.Map)
 277  
      */
 278  
     @Override
 279  
     public <T extends Object> T findObjectByMap(T example, Map<String, String> formProps) {
 280  0
             if ( persistenceStructureService.isPersistable(example.getClass())) {
 281  0
                     Criteria criteria = new Criteria();
 282  
         
 283  
                     // iterate through the parameter map for search criteria
 284  0
             for (Map.Entry<String, String> formProp : formProps.entrySet()) {
 285  
 
 286  0
                             String propertyName = formProp.getKey();
 287  0
                             String searchValue = "";
 288  0
                             if (formProp.getValue() != null) {
 289  0
                                     searchValue = formProp.getValue();
 290  
                             }
 291  
         
 292  0
                             if (StringUtils.isNotBlank(searchValue) & PropertyUtils.isWriteable(example, propertyName)) {
 293  0
                                     Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
 294  0
                                     if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) ) {
 295  0
                                             criteria.addEqualTo(propertyName, cleanNumeric(searchValue));
 296  0
                                     } else if (TypeUtils.isTemporalClass(propertyType)) {
 297  0
                                             criteria.addEqualTo(propertyName, parseDate( ObjectUtils.clean(searchValue) ) );
 298  
                                     } else {
 299  0
                                             criteria.addEqualTo(propertyName, searchValue);
 300  
                                     }
 301  
                             }
 302  0
                     }
 303  
         
 304  
                     // execute query and return result list
 305  0
                     Query query = QueryFactory.newQuery(example.getClass(), criteria);
 306  0
                     return (T)getPersistenceBrokerTemplate().getObjectByQuery(query);
 307  
             }
 308  0
             return null;
 309  
     }
 310  
 
 311  
 
 312  
     /**
 313  
      * Adds to the criteria object based on the property type and any query characters given.
 314  
      */
 315  
     private void addCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Criteria criteria) {
 316  0
         if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue, SearchOperator.OR.op())) {
 317  0
             addOrCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria);
 318  0
             return;
 319  
         }
 320  
 
 321  0
         if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue, SearchOperator.AND.op())) {
 322  0
             addAndCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria);
 323  0
             return;
 324  
         }
 325  
 
 326  0
         if (StringUtils.equalsIgnoreCase(propertyValue, SearchOperator.NULL.op()) || StringUtils.equalsIgnoreCase(propertyValue, SearchOperator.NOT_NULL.op())) {
 327  0
                 if (StringUtils.contains(propertyValue, SearchOperator.NOT.op())) {
 328  0
                         criteria.addColumnNotNull(propertyName);
 329  
                 }
 330  
                 else {
 331  0
                         criteria.addColumnIsNull(propertyName);
 332  
                 }
 333  
         }
 334  0
         else if (TypeUtils.isStringClass(propertyType)) {
 335  
                 // KULRICE-85 : made string searches case insensitive - used new DBPlatform function to force strings to upper case
 336  0
                 if ( caseInsensitive ) {
 337  0
                         propertyName = getDbPlatform().getUpperCaseFunction() + "(" + propertyName + ")";
 338  0
                         propertyValue = propertyValue.toUpperCase();
 339  
                 }
 340  0
             if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue, SearchOperator.NOT.op())) {
 341  0
                 addNotCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria);
 342  0
             } else if (
 343  
                             !treatWildcardsAndOperatorsAsLiteral && propertyValue != null && (
 344  
                                             StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())
 345  
                                             || propertyValue.startsWith(">")
 346  
                                             || propertyValue.startsWith("<") ) ) {
 347  0
                 addStringRangeCriteria(propertyName, propertyValue, criteria);
 348  
             } else {
 349  0
                     if (treatWildcardsAndOperatorsAsLiteral) {
 350  0
                             propertyValue = StringUtils.replace(propertyValue, "*", "\\*");
 351  
                     }
 352  0
                     criteria.addLike(propertyName, propertyValue);
 353  
             }
 354  0
         } else if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType) ) {
 355  0
             addNumericRangeCriteria(propertyName, propertyValue, treatWildcardsAndOperatorsAsLiteral, criteria);
 356  0
         } else if (TypeUtils.isTemporalClass(propertyType)) {
 357  0
             addDateRangeCriteria(propertyName, propertyValue, treatWildcardsAndOperatorsAsLiteral, criteria);
 358  0
         } else if (TypeUtils.isBooleanClass(propertyType)) {
 359  0
             criteria.addEqualTo(propertyName, ObjectUtils.clean(propertyValue));
 360  
         } else {
 361  0
             LOG.error("not adding criterion for: " + propertyName + "," + propertyType + "," + propertyValue);
 362  
         }
 363  0
     }
 364  
     
 365  
     /**
 366  
      * Translates criteria for active status to criteria on the active from and to fields
 367  
      * 
 368  
      * @param example - business object being queried on
 369  
      * @param activeSearchValue - value for the active search field, should convert to boolean
 370  
      * @param criteria - Criteria object being built
 371  
      * @param searchValues - Map containing all search keys and values
 372  
      */
 373  
     protected void addInactivateableFromToActiveCriteria(Object example, String activeSearchValue, Criteria criteria, Map searchValues) {
 374  0
                 Timestamp activeTimestamp = LookupUtils.getActiveDateTimestampForCriteria(searchValues);
 375  
                 
 376  0
             String activeBooleanStr = (String) (new OjbCharBooleanConversion()).javaToSql(activeSearchValue);
 377  0
             if (OjbCharBooleanConversion.DATABASE_BOOLEAN_TRUE_STRING_REPRESENTATION.equals(activeBooleanStr)) {
 378  
                     // (active from date <= date or active from date is null) and (date < active to date or active to date is null)
 379  0
                     Criteria criteriaBeginDate = new Criteria();
 380  0
                     criteriaBeginDate.addLessOrEqualThan(KRADPropertyConstants.ACTIVE_FROM_DATE, activeTimestamp);
 381  
                     
 382  0
                     Criteria criteriaBeginDateNull = new Criteria();
 383  0
                     criteriaBeginDateNull.addIsNull(KRADPropertyConstants.ACTIVE_FROM_DATE);
 384  0
                     criteriaBeginDate.addOrCriteria(criteriaBeginDateNull);
 385  
                     
 386  0
                     criteria.addAndCriteria(criteriaBeginDate);
 387  
                     
 388  0
                     Criteria criteriaEndDate = new Criteria();
 389  0
                     criteriaEndDate.addGreaterThan(KRADPropertyConstants.ACTIVE_TO_DATE, activeTimestamp);
 390  
             
 391  0
                     Criteria criteriaEndDateNull = new Criteria();
 392  0
                     criteriaEndDateNull.addIsNull(KRADPropertyConstants.ACTIVE_TO_DATE);
 393  0
                     criteriaEndDate.addOrCriteria(criteriaEndDateNull);
 394  
                     
 395  0
                     criteria.addAndCriteria(criteriaEndDate);
 396  0
             }
 397  0
             else if (OjbCharBooleanConversion.DATABASE_BOOLEAN_FALSE_STRING_REPRESENTATION.equals(activeBooleanStr)) {
 398  
                     // (date < active from date) or (active from date is null) or (date >= active to date) 
 399  0
                     Criteria criteriaNonActive = new Criteria();
 400  0
                     criteriaNonActive.addGreaterThan(KRADPropertyConstants.ACTIVE_FROM_DATE, activeTimestamp);
 401  
                     
 402  0
                     Criteria criteriaEndDate = new Criteria();
 403  0
                     criteriaEndDate.addLessOrEqualThan(KRADPropertyConstants.ACTIVE_TO_DATE, activeTimestamp);
 404  0
                     criteriaNonActive.addOrCriteria(criteriaEndDate);
 405  
                     
 406  0
                     criteria.addAndCriteria(criteriaNonActive);
 407  
             }
 408  0
     }
 409  
     
 410  
     /**
 411  
      * Translates criteria for current status to criteria on the active from field
 412  
      * 
 413  
      * @param example - business object being queried on
 414  
      * @param currentSearchValue - value for the current search field, should convert to boolean
 415  
      * @param criteria - Criteria object being built
 416  
      */
 417  
         protected void addInactivateableFromToCurrentCriteria(Object example, String currentSearchValue, Criteria criteria, Map searchValues) {
 418  0
                 Criteria maxBeginDateCriteria = new Criteria();
 419  
                 
 420  0
                 Timestamp activeTimestamp = LookupUtils.getActiveDateTimestampForCriteria(searchValues);
 421  
                 
 422  0
                 maxBeginDateCriteria.addLessOrEqualThan(KRADPropertyConstants.ACTIVE_FROM_DATE, activeTimestamp);
 423  
 
 424  0
                 List<String> groupByFieldList = dataDictionaryService.getGroupByAttributesForEffectiveDating(example
 425  
                                 .getClass());
 426  0
                 if (groupByFieldList == null) {
 427  0
                         return;
 428  
                 }
 429  
 
 430  
                 // join back to main query with the group by fields
 431  0
                 String[] groupBy = new String[groupByFieldList.size()];
 432  0
                 for (int i = 0; i < groupByFieldList.size(); i++) {
 433  0
                         String groupByField = groupByFieldList.get(i);
 434  0
                         groupBy[i] = groupByField;
 435  
 
 436  0
                         maxBeginDateCriteria.addEqualToField(groupByField, Criteria.PARENT_QUERY_PREFIX + groupByField);
 437  
                 }
 438  
 
 439  0
                 String[] columns = new String[1];
 440  0
                 columns[0] = "max(" + KRADPropertyConstants.ACTIVE_FROM_DATE + ")";
 441  
 
 442  0
                 QueryByCriteria query = QueryFactory.newReportQuery(example.getClass(), columns, maxBeginDateCriteria, true);
 443  0
                 query.addGroupBy(groupBy);
 444  
 
 445  0
                 String currentBooleanStr = (String) (new OjbCharBooleanConversion()).javaToSql(currentSearchValue);
 446  0
                 if (OjbCharBooleanConversion.DATABASE_BOOLEAN_TRUE_STRING_REPRESENTATION.equals(currentBooleanStr)) {
 447  0
                         criteria.addIn(KRADPropertyConstants.ACTIVE_FROM_DATE, query);
 448  0
                 } else if (OjbCharBooleanConversion.DATABASE_BOOLEAN_FALSE_STRING_REPRESENTATION.equals(currentBooleanStr)) {
 449  0
                         criteria.addNotIn(KRADPropertyConstants.ACTIVE_FROM_DATE, query);
 450  
                 }
 451  0
         }
 452  
 
 453  
     /**
 454  
      * @param propertyName
 455  
      * @param propertyValue
 456  
      * @param propertyType
 457  
      * @param criteria
 458  
      */
 459  
     private void addOrCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
 460  0
         addLogicalOperatorCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria, SearchOperator.OR.op());
 461  0
     }
 462  
        
 463  
     /**
 464  
      * @param propertyName
 465  
      * @param propertyValue
 466  
      * @param propertyType
 467  
      * @param criteria
 468  
      */
 469  
     private void addAndCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
 470  0
         addLogicalOperatorCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria, SearchOperator.AND.op());
 471  0
     }
 472  
 
 473  
     private void addNotCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
 474  
 
 475  0
         String[] splitPropVal = StringUtils.split(propertyValue, SearchOperator.NOT.op());
 476  
 
 477  0
         int strLength = splitPropVal.length;
 478  
         // if more than one NOT operator assume an implicit and (i.e. !a!b = !a&!b)
 479  0
         if (strLength > 1) {
 480  0
             String expandedNot = SearchOperator.NOT + StringUtils.join(splitPropVal, SearchOperator.AND.op() + SearchOperator.NOT.op());
 481  
             // we know that since this method was called, treatWildcardsAndOperatorsAsLiteral must be false
 482  0
             addCriteria(propertyName, expandedNot, propertyType, caseInsensitive, false, criteria);
 483  0
         }
 484  
         else {
 485  
             // only one so add a not like
 486  0
             criteria.addNotLike(propertyName, splitPropVal[0]);
 487  
         }
 488  0
     }
 489  
 
 490  
     /**
 491  
      * Builds a sub criteria object joined with an 'AND' or 'OR' (depending on splitValue) using the split values of propertyValue. Then joins back the
 492  
      * sub criteria to the main criteria using an 'AND'.
 493  
      */
 494  
     private void addLogicalOperatorCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria, String splitValue) {
 495  0
         String[] splitPropVal = StringUtils.split(propertyValue, splitValue);
 496  
 
 497  0
         Criteria subCriteria = new Criteria();
 498  0
         for (int i = 0; i < splitPropVal.length; i++) {
 499  0
                 Criteria predicate = new Criteria();
 500  
 
 501  0
             addCriteria(propertyName, splitPropVal[i], propertyType, caseInsensitive, false, predicate);
 502  0
             if (splitValue.equals(SearchOperator.OR.op())) {
 503  0
                     subCriteria.addOrCriteria(predicate);
 504  
             }
 505  0
             if (splitValue.equals(SearchOperator.AND.op())) {
 506  0
                     subCriteria.addAndCriteria(predicate);
 507  
             }
 508  
         }
 509  
 
 510  0
         criteria.addAndCriteria(subCriteria);
 511  0
     }
 512  
     
 513  
     private java.sql.Date parseDate(String dateString) {
 514  0
                 dateString = dateString.trim();
 515  
                 try {
 516  0
                         return dateTimeService.convertToSqlDate(dateString);
 517  0
                 } catch (ParseException ex) {
 518  0
                         return null;
 519  
                 }
 520  
         }
 521  
 
 522  
     /**
 523  
          * Adds to the criteria object based on query characters given
 524  
          */
 525  
     private void addDateRangeCriteria(String propertyName, String propertyValue, boolean treatWildcardsAndOperatorsAsLiteral, Criteria criteria) {
 526  
 
 527  0
         if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
 528  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 529  0
                         throw new RuntimeException("Wildcards and operators are not allowed on this date field: " + propertyName);
 530  0
             String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
 531  0
             criteria.addBetween(propertyName, parseDate( ObjectUtils.clean(rangeValues[0] ) ), parseDate( ObjectUtils.clean(rangeValues[1] ) ) );
 532  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN_EQUAL.op())) {
 533  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 534  0
                         throw new RuntimeException("Wildcards and operators are not allowed on this date field: " + propertyName);
 535  0
             criteria.addGreaterOrEqualThan(propertyName, parseDate( ObjectUtils.clean(propertyValue) ) );
 536  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN_EQUAL.op())) {
 537  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 538  0
                         throw new RuntimeException("Wildcards and operators are not allowed on this date field: " + propertyName);
 539  0
             criteria.addLessOrEqualThan(propertyName, parseDate( ObjectUtils.clean(propertyValue) ) );
 540  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN.op())) {
 541  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 542  0
                         throw new RuntimeException("Wildcards and operators are not allowed on this date field: " + propertyName);
 543  0
             criteria.addGreaterThan(propertyName, parseDate( ObjectUtils.clean(propertyValue) ) );
 544  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN.op())) {
 545  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 546  0
                         throw new RuntimeException("Wildcards and operators are not allowed on this date field: " + propertyName);
 547  0
             criteria.addLessThan(propertyName, parseDate( ObjectUtils.clean(propertyValue) ) );
 548  
         } else {
 549  0
             criteria.addEqualTo(propertyName, parseDate( ObjectUtils.clean(propertyValue) ) );
 550  
         }
 551  0
     }
 552  
 
 553  
     private BigDecimal cleanNumeric( String value ) {
 554  0
         String cleanedValue = value.replaceAll( "[^-0-9.]", "" );
 555  
         // ensure only one "minus" at the beginning, if any
 556  0
         if ( cleanedValue.lastIndexOf( '-' ) > 0 ) {
 557  0
             if ( cleanedValue.charAt( 0 ) == '-' ) {
 558  0
                 cleanedValue = "-" + cleanedValue.replaceAll( "-", "" );
 559  
             } else {
 560  0
                 cleanedValue = cleanedValue.replaceAll( "-", "" );
 561  
             }
 562  
         }
 563  
         // ensure only one decimal in the string
 564  0
         int decimalLoc = cleanedValue.lastIndexOf( '.' );
 565  0
         if ( cleanedValue.indexOf( '.' ) != decimalLoc ) {
 566  0
             cleanedValue = cleanedValue.substring( 0, decimalLoc ).replaceAll( "\\.", "" ) + cleanedValue.substring( decimalLoc );
 567  
         }
 568  
         try {
 569  0
             return new BigDecimal( cleanedValue );
 570  0
         } catch ( NumberFormatException ex ) {
 571  0
             GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_CUSTOM, new String[] { "Invalid Numeric Input: " + value });
 572  0
             return null;
 573  
         }
 574  
     }
 575  
 
 576  
     /**
 577  
      * Adds to the criteria object based on query characters given
 578  
      */
 579  
     private void addNumericRangeCriteria(String propertyName, String propertyValue, boolean treatWildcardsAndOperatorsAsLiteral, Criteria criteria) {
 580  
 
 581  0
         if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
 582  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 583  0
                         throw new RuntimeException("Cannot use wildcards and operators on numeric field " + propertyName);
 584  0
             String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
 585  0
             criteria.addBetween(propertyName, cleanNumeric( rangeValues[0] ), cleanNumeric( rangeValues[1] ));
 586  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN_EQUAL.op())) {
 587  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 588  0
                         throw new RuntimeException("Cannot use wildcards and operators on numeric field " + propertyName);
 589  0
             criteria.addGreaterOrEqualThan(propertyName, cleanNumeric(propertyValue));
 590  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN_EQUAL.op())) {
 591  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 592  0
                         throw new RuntimeException("Cannot use wildcards and operators on numeric field " + propertyName);
 593  0
             criteria.addLessOrEqualThan(propertyName, cleanNumeric(propertyValue));
 594  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN.op())) {
 595  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 596  0
                         throw new RuntimeException("Cannot use wildcards and operators on numeric field " + propertyName);
 597  0
             criteria.addGreaterThan(propertyName, cleanNumeric( propertyValue ) );
 598  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN.op())) {
 599  0
                 if (treatWildcardsAndOperatorsAsLiteral)
 600  0
                         throw new RuntimeException("Cannot use wildcards and operators on numeric field " + propertyName);
 601  0
             criteria.addLessThan(propertyName, cleanNumeric(propertyValue));
 602  
         } else {
 603  0
             criteria.addEqualTo(propertyName, cleanNumeric(propertyValue));
 604  
         }
 605  0
     }
 606  
 
 607  
     /**
 608  
      * Adds to the criteria object based on query characters given
 609  
      */
 610  
     private void addStringRangeCriteria(String propertyName, String propertyValue, Criteria criteria) {
 611  
 
 612  0
         if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
 613  0
             String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
 614  0
             criteria.addBetween(propertyName, rangeValues[0], rangeValues[1]);
 615  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN_EQUAL.op())) {
 616  0
             criteria.addGreaterOrEqualThan(propertyName, ObjectUtils.clean(propertyValue));
 617  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN_EQUAL.op())) {
 618  0
             criteria.addLessOrEqualThan(propertyName, ObjectUtils.clean(propertyValue));
 619  0
         } else if (propertyValue.startsWith(SearchOperator.GREATER_THAN.op())) {
 620  0
             criteria.addGreaterThan(propertyName, ObjectUtils.clean(propertyValue));
 621  0
         } else if (propertyValue.startsWith(SearchOperator.LESS_THAN.op())) {
 622  0
             criteria.addLessThan(propertyName, ObjectUtils.clean(propertyValue));
 623  
         } else {
 624  0
                 criteria.addEqualTo(propertyName, ObjectUtils.clean(propertyValue));
 625  
         }
 626  0
     }
 627  
 
 628  
         public void setDateTimeService(DateTimeService dateTimeService) {
 629  0
                 this.dateTimeService = dateTimeService;
 630  0
         }
 631  
 
 632  
     public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
 633  0
         this.persistenceStructureService = persistenceStructureService;
 634  0
     }
 635  
 
 636  
     public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
 637  0
         this.dataDictionaryService = dataDictionaryService;
 638  0
     }
 639  
 }