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