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