1
2
3
4
5
6
7
8
9
10
11
12
13
14
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.kuali.rice.core.api.datetime.DateTimeService;
21 import org.kuali.rice.core.api.search.SearchOperator;
22 import org.kuali.rice.core.api.util.RiceKeyConstants;
23 import org.kuali.rice.core.api.util.type.TypeUtils;
24 import org.kuali.rice.core.framework.persistence.jpa.criteria.Criteria;
25 import org.kuali.rice.core.framework.persistence.jpa.criteria.QueryByCriteria;
26 import org.kuali.rice.core.framework.persistence.jpa.metadata.EntityDescriptor;
27 import org.kuali.rice.core.framework.persistence.jpa.metadata.FieldDescriptor;
28 import org.kuali.rice.core.framework.persistence.jpa.metadata.MetadataManager;
29 import org.kuali.rice.core.framework.persistence.ojb.conversion.OjbCharBooleanConversion;
30 import org.kuali.rice.kns.service.KNSServiceLocator;
31 import org.kuali.rice.krad.bo.InactivatableFromTo;
32 import org.kuali.rice.krad.bo.PersistableBusinessObject;
33 import org.kuali.rice.krad.bo.PersistableBusinessObjectExtension;
34 import org.kuali.rice.krad.dao.LookupDao;
35 import org.kuali.rice.krad.lookup.CollectionIncomplete;
36 import org.kuali.rice.krad.lookup.LookupUtils;
37 import org.kuali.rice.krad.service.DataDictionaryService;
38 import org.kuali.rice.krad.service.KRADServiceLocatorInternal;
39 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
40 import org.kuali.rice.krad.service.PersistenceStructureService;
41 import org.kuali.rice.krad.util.GlobalVariables;
42 import org.kuali.rice.krad.util.KRADConstants;
43 import org.kuali.rice.krad.util.KRADPropertyConstants;
44 import org.kuali.rice.krad.util.ObjectUtils;
45 import org.springframework.dao.DataIntegrityViolationException;
46
47 import javax.persistence.EntityManager;
48 import javax.persistence.PersistenceContext;
49 import javax.persistence.PersistenceException;
50 import java.lang.reflect.Field;
51 import java.math.BigDecimal;
52 import java.sql.Timestamp;
53 import java.text.ParseException;
54 import java.util.ArrayList;
55 import java.util.Collection;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.Map;
59
60
61
62
63 public class LookupDaoJpa implements LookupDao {
64 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(LookupDao.class);
65
66 private DateTimeService dateTimeService;
67 private PersistenceStructureService persistenceStructureService;
68 private DataDictionaryService dataDictionaryService;
69
70 @PersistenceContext
71 private EntityManager entityManager;
72
73 public Long findCountByMap(Object example, Map formProps) {
74 Criteria criteria = new Criteria(example.getClass().getName());
75
76
77 Iterator propsIter = formProps.keySet().iterator();
78 while (propsIter.hasNext()) {
79 String propertyName = (String) propsIter.next();
80 String searchValue = (String) formProps.get(propertyName);
81
82
83 if (StringUtils.isBlank(searchValue) || !(PropertyUtils.isWriteable(example, propertyName))) {
84 continue;
85 }
86
87
88 Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
89 if (propertyType == null) {
90 continue;
91 }
92 Boolean caseInsensitive = Boolean.TRUE;
93 if (KRADServiceLocatorWeb.getDataDictionaryService().isAttributeDefined(example.getClass(), propertyName)) {
94
95
96
97 caseInsensitive = !KRADServiceLocatorWeb.getDataDictionaryService().getAttributeForceUppercase(example.getClass(), propertyName);
98 }
99 if (caseInsensitive == null) {
100 caseInsensitive = Boolean.TRUE;
101 }
102
103 boolean treatWildcardsAndOperatorsAsLiteral = KNSServiceLocator.
104 getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(example.getClass(), propertyName);
105
106 if (!caseInsensitive) {
107
108 searchValue = searchValue.toUpperCase();
109 }
110 addCriteria(propertyName, searchValue, propertyType, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria);
111 }
112
113
114 return (Long) new QueryByCriteria(entityManager, criteria).toCountQuery().getSingleResult();
115 }
116
117 public Collection findCollectionBySearchHelper(Class businessObjectClass, Map formProps, boolean unbounded, boolean usePrimaryKeyValuesOnly) {
118 PersistableBusinessObject businessObject = checkBusinessObjectClass(businessObjectClass);
119 if (usePrimaryKeyValuesOnly) {
120 return executeSearch(businessObjectClass, getCollectionCriteriaFromMapUsingPrimaryKeysOnly(businessObjectClass, formProps), unbounded);
121 } else {
122 Criteria crit = getCollectionCriteriaFromMap(businessObject, formProps);
123 return executeSearch(businessObjectClass, crit, unbounded);
124 }
125 }
126
127 public Criteria getCollectionCriteriaFromMap(PersistableBusinessObject example, Map formProps) {
128 Criteria criteria = new Criteria(example.getClass().getName());
129 Iterator propsIter = formProps.keySet().iterator();
130 while (propsIter.hasNext()) {
131 String propertyName = (String) propsIter.next();
132 Boolean caseInsensitive = Boolean.TRUE;
133 if (KRADServiceLocatorWeb.getDataDictionaryService().isAttributeDefined(example.getClass(), propertyName)) {
134 caseInsensitive = !KRADServiceLocatorWeb.getDataDictionaryService().getAttributeForceUppercase(example.getClass(), propertyName);
135 }
136 if (caseInsensitive == null) {
137 caseInsensitive = Boolean.TRUE;
138 }
139 boolean treatWildcardsAndOperatorsAsLiteral = KNSServiceLocator.
140 getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(example.getClass(), propertyName);
141 if (formProps.get(propertyName) instanceof Collection) {
142 Iterator iter = ((Collection) formProps.get(propertyName)).iterator();
143 while (iter.hasNext()) {
144 String searchValue = (String) iter.next();
145 if (!caseInsensitive) {
146
147 searchValue = searchValue.toUpperCase();
148 }
149 if (!createCriteria(example, searchValue, propertyName, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria, formProps)) {
150 throw new RuntimeException("Invalid value in Collection");
151 }
152 }
153 } else {
154 String searchValue = (String) formProps.get(propertyName);
155 if (!caseInsensitive) {
156
157 searchValue = searchValue.toUpperCase();
158 }
159 if (!createCriteria(example, searchValue, propertyName, caseInsensitive, treatWildcardsAndOperatorsAsLiteral, criteria, formProps)) {
160 continue;
161 }
162 }
163 }
164 return criteria;
165 }
166
167 public Criteria getCollectionCriteriaFromMapUsingPrimaryKeysOnly(Class businessObjectClass, Map formProps) {
168 PersistableBusinessObject businessObject = checkBusinessObjectClass(businessObjectClass);
169 Criteria criteria = new Criteria(businessObjectClass.getName());
170 List pkFields = persistenceStructureService.listPrimaryKeyFieldNames(businessObjectClass);
171 Iterator pkIter = pkFields.iterator();
172 while (pkIter.hasNext()) {
173 String pkFieldName = (String) pkIter.next();
174 String pkValue = (String) formProps.get(pkFieldName);
175
176 if (StringUtils.isBlank(pkValue)) {
177 throw new RuntimeException("Missing pk value for field " + pkFieldName + " when a search based on PK values only is performed.");
178 } else {
179 for (SearchOperator op : SearchOperator.QUERY_CHARACTERS) {
180 if (pkValue.contains(op.op())) {
181 throw new RuntimeException("Value \"" + pkValue + "\" for PK field " + pkFieldName + " contains wildcard/operator characters.");
182 }
183 }
184 }
185 boolean treatWildcardsAndOperatorsAsLiteral = KNSServiceLocator.
186 getBusinessObjectDictionaryService().isLookupFieldTreatWildcardsAndOperatorsAsLiteral(businessObjectClass, pkFieldName);
187 createCriteria(businessObject, pkValue, pkFieldName, false, treatWildcardsAndOperatorsAsLiteral, criteria);
188 }
189 return criteria;
190 }
191
192 private PersistableBusinessObject checkBusinessObjectClass(Class businessObjectClass) {
193 if (businessObjectClass == null) {
194 throw new IllegalArgumentException("BusinessObject class passed to LookupDao findCollectionBySearchHelper... method was null");
195 }
196 PersistableBusinessObject businessObject = null;
197 try {
198 businessObject = (PersistableBusinessObject) businessObjectClass.newInstance();
199 } catch (IllegalAccessException e) {
200 throw new RuntimeException("LookupDao could not get instance of " + businessObjectClass.getName(), e);
201 } catch (InstantiationException e) {
202 throw new RuntimeException("LookupDao could not get instance of " + businessObjectClass.getName(), e);
203 }
204 return businessObject;
205 }
206
207 private Collection executeSearch(Class businessObjectClass, Criteria criteria, boolean unbounded) {
208 Collection<PersistableBusinessObject> searchResults = new ArrayList<PersistableBusinessObject>();
209 Long matchingResultsCount = null;
210 try {
211 Integer searchResultsLimit = LookupUtils.getSearchResultsLimit(businessObjectClass);
212 if (!unbounded && (searchResultsLimit != null)) {
213 matchingResultsCount = (Long) new QueryByCriteria(entityManager, criteria).toCountQuery().getSingleResult();
214 searchResults = new QueryByCriteria(entityManager, criteria).toQuery().setMaxResults(searchResultsLimit).getResultList();
215 } else {
216 searchResults = new QueryByCriteria(entityManager, criteria).toQuery().getResultList();
217 }
218 if ((matchingResultsCount == null) || (matchingResultsCount.intValue() <= searchResultsLimit.intValue())) {
219 matchingResultsCount = new Long(0);
220 }
221
222
223
224
225 for (PersistableBusinessObject bo : searchResults) {
226 if (bo.getExtension() != null) {
227 PersistableBusinessObjectExtension boe = bo.getExtension();
228 EntityDescriptor entity = MetadataManager.getEntityDescriptor(bo.getExtension().getClass());
229 Criteria extensionCriteria = new Criteria(boe.getClass().getName());
230 for (FieldDescriptor fieldDescriptor : entity.getPrimaryKeys()) {
231 try {
232 Field field = bo.getClass().getDeclaredField(fieldDescriptor.getName());
233 field.setAccessible(true);
234 extensionCriteria.eq(fieldDescriptor.getName(), field.get(bo));
235 } catch (Exception e) {
236 LOG.error(e.getMessage(), e);
237 }
238 }
239 try {
240 boe = (PersistableBusinessObjectExtension) new QueryByCriteria(entityManager, extensionCriteria).toQuery().getSingleResult();
241 } catch (PersistenceException e) {}
242 bo.setExtension(boe);
243 }
244 }
245
246 List bos = new ArrayList();
247 bos.addAll(searchResults);
248 searchResults = bos;
249 } catch (DataIntegrityViolationException e) {
250 throw new RuntimeException("LookupDao encountered exception during executeSearch", e);
251 }
252 return new CollectionIncomplete(searchResults, matchingResultsCount);
253 }
254
255
256
257
258
259
260
261
262
263
264
265
266 private boolean isWriteable(Object o, String p) throws IllegalArgumentException {
267 if (null == o || null == p) {
268 throw new IllegalArgumentException("Cannot check writeable status with null arguments.");
269 }
270
271 boolean b = false;
272
273
274 if (!(PropertyUtils.isWriteable(o, p))) {
275
276
277
278 if (-1 != p.indexOf('.')) {
279
280 String[] parts = p.split("\\.");
281
282
283 Class c = ObjectUtils.getPropertyType(o, parts[0], persistenceStructureService);
284
285 Object i = null;
286
287
288
289 if (Collection.class.isAssignableFrom(c)) {
290 Map<String, Class> m = persistenceStructureService.listCollectionObjectTypes(o.getClass());
291 c = m.get(parts[0]);
292 }
293
294
295 try {
296 i = c.newInstance();
297 StringBuffer sb = new StringBuffer();
298 for (int x = 1; x < parts.length; x++) {
299 sb.append(1 == x ? "" : ".").append(parts[x]);
300 }
301 b = isWriteable(i, sb.toString());
302 } catch (InstantiationException ie) {
303 LOG.info(ie);
304 } catch (IllegalAccessException iae) {
305 LOG.info(iae);
306 }
307 }
308 } else {
309 b = true;
310 }
311
312 return b;
313 }
314
315 public boolean createCriteria(Object example, String searchValue, String propertyName, Object criteria) {
316 return createCriteria(example, searchValue, propertyName, false, false, criteria);
317 }
318
319 public boolean createCriteria(Object example, String searchValue, String propertyName, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Object criteria) {
320 return createCriteria( example, searchValue, propertyName, false, false, criteria, null );
321 }
322
323 public boolean createCriteria(Object example, String searchValue, String propertyName, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Object criteria, Map searchValues) {
324
325 if (!(criteria instanceof Criteria) || StringUtils.isBlank(searchValue) || !isWriteable(example, propertyName)) {
326 return false;
327 }
328
329
330 Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
331 if (propertyType == null) {
332 return false;
333 }
334
335
336 if (example instanceof InactivatableFromTo) {
337 if (KRADPropertyConstants.ACTIVE.equals(propertyName)) {
338 addInactivateableFromToActiveCriteria(example, searchValue, (Criteria) criteria, searchValues);
339 } else if (KRADPropertyConstants.CURRENT.equals(propertyName)) {
340 addInactivateableFromToCurrentCriteria(example, searchValue, (Criteria) criteria, searchValues);
341 } else if (!KRADPropertyConstants.ACTIVE_AS_OF_DATE.equals(propertyName)) {
342 addCriteria(propertyName, searchValue, propertyType, caseInsensitive,
343 treatWildcardsAndOperatorsAsLiteral, (Criteria) criteria);
344 }
345 } else {
346 addCriteria(propertyName, searchValue, propertyType, caseInsensitive, treatWildcardsAndOperatorsAsLiteral,
347 (Criteria) criteria);
348 }
349
350 return true;
351 }
352
353
354
355
356
357 public Object findObjectByMap(Object example, Map formProps) {
358 Criteria jpaCriteria = new Criteria(example.getClass().getName());
359
360 Iterator propsIter = formProps.keySet().iterator();
361 while (propsIter.hasNext()) {
362 String propertyName = (String) propsIter.next();
363 String searchValue = "";
364 if (formProps.get(propertyName) != null) {
365 searchValue = (formProps.get(propertyName)).toString();
366 }
367
368 if (StringUtils.isNotBlank(searchValue) & PropertyUtils.isWriteable(example, propertyName)) {
369 Class propertyType = ObjectUtils.getPropertyType(example, propertyName, persistenceStructureService);
370 if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType)) {
371 if (propertyType.equals(Long.class)) {
372 jpaCriteria.eq(propertyName, new Long(searchValue));
373 } else {
374 jpaCriteria.eq(propertyName, new Integer(searchValue));
375 }
376 } else if (TypeUtils.isTemporalClass(propertyType)) {
377 jpaCriteria.eq(propertyName, parseDate(ObjectUtils.clean(searchValue)));
378 } else {
379 jpaCriteria.eq(propertyName, searchValue);
380 }
381 }
382 }
383
384 return new QueryByCriteria(entityManager, jpaCriteria).toQuery().getSingleResult();
385 }
386
387 private void addCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, boolean treatWildcardsAndOperatorsAsLiteral, Criteria criteria) {
388 String alias = "";
389 String[] keySplit = propertyName.split("\\.");
390 if (keySplit.length > 1) {
391 alias = keySplit[keySplit.length-2];
392 String variableKey = keySplit[keySplit.length-1];
393 for (int j = 0; j < keySplit.length - 1; j++) {
394 if (StringUtils.contains(keySplit[j], Criteria.JPA_ALIAS_PREFIX)) {
395 String tempKey = keySplit[j].substring(keySplit[j].indexOf('\'', keySplit[j].indexOf(Criteria.JPA_ALIAS_PREFIX)) + 1,
396 keySplit[j].lastIndexOf('\'', keySplit[j].indexOf(Criteria.JPA_ALIAS_SUFFIX)));
397 if (criteria.getAliasIndex(tempKey) == -1) {
398 criteria.join(tempKey, tempKey, false, true);
399 }
400 } else {
401 if (criteria.getAliasIndex(keySplit[j]) == -1) {
402 criteria.join(keySplit[j], keySplit[j], false, true);
403 }
404 }
405 }
406 if (!StringUtils.contains(propertyName, "__JPA_ALIAS[[")) {
407 propertyName = "__JPA_ALIAS[['" + alias + "']]__." + variableKey;
408 }
409 }
410 if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue, SearchOperator.OR.op())) {
411 addOrCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria);
412 return;
413 }
414
415 if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue, SearchOperator.AND.op())) {
416 addAndCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria);
417 return;
418 }
419
420 if (StringUtils.containsIgnoreCase(propertyValue, SearchOperator.NULL.op())) {
421 if (StringUtils.contains(propertyValue, SearchOperator.NOT.op())) {
422 criteria.notNull(propertyName);
423 }
424 else {
425 criteria.isNull(propertyName);
426 }
427 }
428 else if (TypeUtils.isStringClass(propertyType)) {
429
430
431 if (caseInsensitive) {
432
433
434 if (StringUtils.contains(propertyName, "__JPA_ALIAS[[")) {
435 propertyName = "UPPER(" + propertyName + ")";
436 } else {
437 propertyName = "UPPER(__JPA_ALIAS[[0]]__." + propertyName + ")";
438 }
439 propertyValue = propertyValue.toUpperCase();
440 }
441 if (!treatWildcardsAndOperatorsAsLiteral && StringUtils.contains(propertyValue,
442 SearchOperator.NOT.op())) {
443 addNotCriteria(propertyName, propertyValue, propertyType,
444 caseInsensitive, criteria);
445 } else if (
446 !treatWildcardsAndOperatorsAsLiteral && propertyValue != null && (
447 StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())
448 || propertyValue.startsWith(">")
449 || propertyValue.startsWith("<") ) ) {
450 addStringRangeCriteria(propertyName, propertyValue, criteria);
451 } else {
452 if (treatWildcardsAndOperatorsAsLiteral) {
453 propertyValue = StringUtils.replace(propertyValue, "*", "\\*");
454 }
455 criteria.like(propertyName, propertyValue);
456 }
457 } else if (TypeUtils.isIntegralClass(propertyType) || TypeUtils.isDecimalClass(propertyType)) {
458 addNumericRangeCriteria(propertyName, propertyValue, criteria);
459 } else if (TypeUtils.isTemporalClass(propertyType)) {
460 addDateRangeCriteria(propertyName, propertyValue, criteria);
461 } else if (TypeUtils.isBooleanClass(propertyType)) {
462 String temp = ObjectUtils.clean(propertyValue);
463 criteria.eq(propertyName, ("Y".equalsIgnoreCase(temp) || "T".equalsIgnoreCase(temp) || "1".equalsIgnoreCase(temp) || "true".equalsIgnoreCase(temp)) ? true : false);
464 } else {
465 LOG.error("not adding criterion for: " + propertyName + "," + propertyType + "," + propertyValue);
466 }
467 }
468
469
470
471
472
473
474
475
476
477
478 protected void addInactivateableFromToActiveCriteria(Object example, String activeSearchValue, Criteria criteria, Map searchValues) {
479 Timestamp activeTimestamp = LookupUtils.getActiveDateTimestampForCriteria(searchValues);
480
481 String activeBooleanStr = (String) (new OjbCharBooleanConversion()).javaToSql(activeSearchValue);
482 if (OjbCharBooleanConversion.DATABASE_BOOLEAN_TRUE_STRING_REPRESENTATION.equals(activeBooleanStr)) {
483
484 Criteria criteriaBeginDate = new Criteria(example.getClass().getName());
485 criteriaBeginDate.lte(KRADPropertyConstants.ACTIVE_FROM_DATE, activeTimestamp);
486
487 Criteria criteriaBeginDateNull = new Criteria(example.getClass().getName());
488 criteriaBeginDateNull.isNull(KRADPropertyConstants.ACTIVE_FROM_DATE);
489 criteriaBeginDate.or(criteriaBeginDateNull);
490
491 criteria.and(criteriaBeginDate);
492
493 Criteria criteriaEndDate = new Criteria(example.getClass().getName());
494 criteriaEndDate.gt(KRADPropertyConstants.ACTIVE_TO_DATE, activeTimestamp);
495
496 Criteria criteriaEndDateNull = new Criteria(example.getClass().getName());
497 criteriaEndDateNull.isNull(KRADPropertyConstants.ACTIVE_TO_DATE);
498 criteriaEndDate.or(criteriaEndDateNull);
499
500 criteria.and(criteriaEndDate);
501 }
502 else if (OjbCharBooleanConversion.DATABASE_BOOLEAN_FALSE_STRING_REPRESENTATION.equals(activeBooleanStr)) {
503
504 Criteria criteriaNonActive = new Criteria(example.getClass().getName());
505 criteriaNonActive.gt(KRADPropertyConstants.ACTIVE_FROM_DATE, activeTimestamp);
506
507 Criteria criteriaBeginDateNull = new Criteria(example.getClass().getName());
508 criteriaBeginDateNull.isNull(KRADPropertyConstants.ACTIVE_FROM_DATE);
509 criteriaNonActive.or(criteriaBeginDateNull);
510
511 Criteria criteriaEndDate = new Criteria(example.getClass().getName());
512 criteriaEndDate.lte(KRADPropertyConstants.ACTIVE_TO_DATE, activeTimestamp);
513 criteriaNonActive.or(criteriaEndDate);
514
515 criteria.and(criteriaNonActive);
516 }
517 }
518
519
520
521
522
523
524
525
526 protected void addInactivateableFromToCurrentCriteria(Object example, String currentSearchValue, Criteria criteria, Map searchValues) {
527 Timestamp activeTimestamp = LookupUtils.getActiveDateTimestampForCriteria(searchValues);
528
529 List<String> groupByFieldList = dataDictionaryService.getGroupByAttributesForEffectiveDating(example
530 .getClass());
531 if (groupByFieldList == null) {
532 return;
533 }
534
535 String alias = "c";
536
537 String jpql = " (select max(" + alias + "." + KRADPropertyConstants.ACTIVE_FROM_DATE + ") from "
538 + example.getClass().getName() + " as " + alias + " where ";
539 String activeDateDBStr = KRADServiceLocatorInternal.getDatabasePlatform().getDateSQL(dateTimeService.toDateTimeString(activeTimestamp), null);
540 jpql += alias + "." + KRADPropertyConstants.ACTIVE_FROM_DATE + " <= '" + activeDateDBStr + "'";
541
542
543 boolean firstGroupBy = true;
544 String groupByJpql = "";
545 for (String groupByField : groupByFieldList) {
546 if (!firstGroupBy) {
547 groupByJpql += ", ";
548 }
549
550 jpql += " AND " + alias + "." + groupByField + " = " + criteria.getAlias() + "." + groupByField + " ";
551 groupByJpql += alias + "." + groupByField;
552 firstGroupBy = false;
553 }
554
555 jpql += " group by " + groupByJpql + " )";
556
557 String currentBooleanStr = (String) (new OjbCharBooleanConversion()).javaToSql(currentSearchValue);
558 if (OjbCharBooleanConversion.DATABASE_BOOLEAN_TRUE_STRING_REPRESENTATION.equals(currentBooleanStr)) {
559 jpql = criteria.getAlias() + "." + KRADPropertyConstants.ACTIVE_FROM_DATE + " in " + jpql;
560 } else if (OjbCharBooleanConversion.DATABASE_BOOLEAN_FALSE_STRING_REPRESENTATION.equals(currentBooleanStr)) {
561 jpql = criteria.getAlias() + "." + KRADPropertyConstants.ACTIVE_FROM_DATE + " not in " + jpql;
562 }
563
564 criteria.rawJpql(jpql);
565 }
566
567 private void addOrCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
568 addLogicalOperatorCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria, SearchOperator.OR.op());
569 }
570
571 private void addAndCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
572 addLogicalOperatorCriteria(propertyName, propertyValue, propertyType, caseInsensitive, criteria, SearchOperator.AND.op());
573 }
574
575 private void addNotCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria) {
576 String[] splitPropVal = StringUtils.split(propertyValue, SearchOperator.NOT.op());
577
578 int strLength = splitPropVal.length;
579
580 if (strLength > 1) {
581 String expandedNot = "!" + StringUtils.join(splitPropVal, SearchOperator.AND.op() + SearchOperator.NOT.op());
582
583 addCriteria(propertyName, expandedNot, propertyType, caseInsensitive, false, criteria);
584 } else {
585
586 criteria.notLike(propertyName, splitPropVal[0]);
587 }
588 }
589
590 private void addLogicalOperatorCriteria(String propertyName, String propertyValue, Class propertyType, boolean caseInsensitive, Criteria criteria, String splitValue) {
591 String[] splitPropVal = StringUtils.split(propertyValue, splitValue);
592
593 Criteria subCriteria = new Criteria("N/A");
594 for (int i = 0; i < splitPropVal.length; i++) {
595 Criteria predicate = new Criteria("N/A");
596
597 addCriteria(propertyName, splitPropVal[i], propertyType, caseInsensitive, false, predicate);
598 if (splitValue == SearchOperator.OR.op()) {
599 subCriteria.or(predicate);
600 }
601 if (splitValue == SearchOperator.AND.op()) {
602 subCriteria.and(predicate);
603 }
604 }
605
606 criteria.and(subCriteria);
607 }
608
609 private java.sql.Date parseDate(String dateString) {
610 dateString = dateString.trim();
611 try {
612 return dateTimeService.convertToSqlDate(dateString);
613 } catch (ParseException ex) {
614 return null;
615 }
616 }
617
618 private void addDateRangeCriteria(String propertyName, String propertyValue, Criteria criteria) {
619
620 if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
621 String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
622 criteria.between(propertyName, parseDate(ObjectUtils.clean(rangeValues[0])), parseDate(ObjectUtils.clean(rangeValues[1])));
623 } else if (propertyValue.startsWith(">=")) {
624 criteria.gte(propertyName, parseDate(ObjectUtils.clean(propertyValue)));
625 } else if (propertyValue.startsWith("<=")) {
626 criteria.lte(propertyName, parseDate(ObjectUtils.clean(propertyValue)));
627 } else if (propertyValue.startsWith(">")) {
628 criteria.gt(propertyName, parseDate(ObjectUtils.clean(propertyValue)));
629 } else if (propertyValue.startsWith("<")) {
630 criteria.lt(propertyName, parseDate(ObjectUtils.clean(propertyValue)));
631 } else {
632 criteria.eq(propertyName, parseDate(ObjectUtils.clean(propertyValue)));
633 }
634 }
635
636 private BigDecimal cleanNumeric(String value) {
637 String cleanedValue = value.replaceAll("[^-0-9.]", "");
638
639 if (cleanedValue.lastIndexOf('-') > 0) {
640 if (cleanedValue.charAt(0) == '-') {
641 cleanedValue = "-" + cleanedValue.replaceAll("-", "");
642 } else {
643 cleanedValue = cleanedValue.replaceAll("-", "");
644 }
645 }
646
647 int decimalLoc = cleanedValue.lastIndexOf('.');
648 if (cleanedValue.indexOf('.') != decimalLoc) {
649 cleanedValue = cleanedValue.substring(0, decimalLoc).replaceAll("\\.", "") + cleanedValue.substring(decimalLoc);
650 }
651 try {
652 return new BigDecimal(cleanedValue);
653 } catch (NumberFormatException ex) {
654 GlobalVariables.getMessageMap().putError(KRADConstants.DOCUMENT_ERRORS, RiceKeyConstants.ERROR_CUSTOM, new String[] { "Invalid Numeric Input: " + value });
655 return null;
656 }
657 }
658
659 private void addNumericRangeCriteria(String propertyName, String propertyValue, Criteria criteria) {
660
661 if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
662 String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
663 criteria.between(propertyName, cleanNumeric(rangeValues[0]), cleanNumeric(rangeValues[1]));
664 } else if (propertyValue.startsWith(">=")) {
665 criteria.gte(propertyName, cleanNumeric(propertyValue));
666 } else if (propertyValue.startsWith("<=")) {
667 criteria.lte(propertyName, cleanNumeric(propertyValue));
668 } else if (propertyValue.startsWith(">")) {
669 criteria.gt(propertyName, cleanNumeric(propertyValue));
670 } else if (propertyValue.startsWith("<")) {
671 criteria.lt(propertyName, cleanNumeric(propertyValue));
672 } else {
673 criteria.eq(propertyName, cleanNumeric(propertyValue));
674 }
675 }
676
677 private void addStringRangeCriteria(String propertyName, String propertyValue, Criteria criteria) {
678
679 if (StringUtils.contains(propertyValue, SearchOperator.BETWEEN.op())) {
680 String[] rangeValues = StringUtils.split(propertyValue, SearchOperator.BETWEEN.op());
681 criteria.between(propertyName, rangeValues[0], rangeValues[1]);
682 } else if (propertyValue.startsWith(">=")) {
683 criteria.gte(propertyName, ObjectUtils.clean(propertyValue));
684 } else if (propertyValue.startsWith("<=")) {
685 criteria.lte(propertyName, ObjectUtils.clean(propertyValue));
686 } else if (propertyValue.startsWith(">")) {
687 criteria.gt(propertyName, ObjectUtils.clean(propertyValue));
688 } else if (propertyValue.startsWith("<")) {
689 criteria.lt(propertyName, ObjectUtils.clean(propertyValue));
690 }
691 }
692
693
694
695
696
697 public void setDateTimeService(DateTimeService dateTimeService) {
698 this.dateTimeService = dateTimeService;
699 }
700
701
702
703
704 public EntityManager getEntityManager() {
705 return this.entityManager;
706 }
707
708
709
710
711 public void setEntityManager(EntityManager entityManager) {
712 this.entityManager = entityManager;
713 }
714
715 public void setPersistenceStructureService(PersistenceStructureService persistenceStructureService) {
716 this.persistenceStructureService = persistenceStructureService;
717 }
718
719 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
720 this.dataDictionaryService = dataDictionaryService;
721 }
722
723 }