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