1 // license-header java merge-point
2 //
3 // Attention: Generated code! Do not modify by hand!
4 // Generated by: hibernate/HibernateSearch.vsl in andromda-spring-cartridge.
5 //
6 package fr.ifremer.quadrige3.core.dao;
7
8 /*-
9 * #%L
10 * Quadrige3 Core :: Client API
11 * %%
12 * Copyright (C) 2017 - 2024 Ifremer
13 * %%
14 * This program is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Affero General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU Affero General Public License
25 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 * #L%
27 */
28 import java.util.ArrayList;
29 import java.util.Collection;
30 import java.util.Collections;
31 import java.util.Comparator;
32 import java.util.HashMap;
33 import java.util.LinkedHashSet;
34 import java.util.List;
35 import java.util.Map;
36 import java.util.Set;
37 import org.apache.commons.lang3.StringUtils;
38 import org.hibernate.Criteria;
39 import org.hibernate.FetchMode;
40 import org.hibernate.HibernateException;
41 import org.hibernate.Session;
42 import org.hibernate.criterion.Conjunction;
43 import org.hibernate.criterion.CriteriaSpecification;
44 import org.hibernate.criterion.Criterion;
45 import org.hibernate.criterion.Disjunction;
46 import org.hibernate.criterion.MatchMode;
47 import org.hibernate.criterion.Order;
48 import org.hibernate.criterion.Restrictions;
49 import org.hibernate.criterion.SimpleExpression;
50
51 /**
52 * Implements a generic search mechanism based on the Hibernate Criteria API. The
53 * <code>CriteriaSearch</code> allows adding parameters which function as where clause. The
54 * parameters are analyzed whether they should be considered or not. This depends both on the actual
55 * value of the parameter and on the configuration.<br>
56 * The <code>CriteriaSearch</code> is expected to be a general solution for a basic search with
57 * parameters connected by logical <b>and</b>. This search does <b>not</b> provide grouping.
58 *
59 * @author Stefan Reichert
60 * @author Peter Friese
61 * @author Chad Brandon
62 * @see Criteria
63 * @see Restrictions
64 */
65 public class CriteriaSearch
66 {
67 private CriteriaSearchConfiguration configuration;
68 private Criteria rootCriteria;
69 private Map<String, Criteria> childCriteriaMap;
70 private List<CriteriaSearchParameter> orderList;
71 private Class resultType;
72
73 private static final class ParameterComparator
74 implements Comparator
75 {
76 public int compare(final Object object1, final Object object2)
77 {
78 final CriteriaSearchParameter parameter1 = (CriteriaSearchParameter)object1;
79 final CriteriaSearchParameter parameter2 = (CriteriaSearchParameter)object2;
80
81 final int relevance1 = parameter1.getOrderRelevance();
82 final int relevance2 = parameter2.getOrderRelevance();
83 int result = 0;
84 if (relevance1 > relevance2)
85 {
86 result = 1;
87 }
88 else if (relevance1 < relevance2)
89 {
90 result = -1;
91 }
92 return result;
93 }
94 }
95
96 /**
97 * Exposes the root criteria to subclasses.
98 * @return rootCriteria
99 */
100 protected Criteria getRootCriteria()
101 {
102 return this.rootCriteria;
103 }
104
105 /**
106 * Constructor for CriteriaSearch. Creates a <code>CriteriaSearch</code> with a default
107 * <code>CriteriaSearchConfiguration</code>.
108 *
109 * @param session The Hibernate session.
110 * @param resultTypeIn The <code>Class</code> of the result.
111 */
112 public CriteriaSearch(Session session, Class resultTypeIn)
113 {
114 this.configuration = new CriteriaSearchConfiguration();
115 this.resultType = resultTypeIn;
116 this.rootCriteria = session.createCriteria(this.resultType);
117 this.childCriteriaMap = new HashMap<String, Criteria>();
118 this.orderList = new ArrayList<CriteriaSearchParameter>();
119 }
120
121 /**
122 * Executes a <code>HibernateQuery</code> using the currently defined
123 * <code>CriteriaSearchParameter</code>s, and returns a java.util.Set
124 * containing the query results.
125 *
126 * @return result The result of the query.
127 * @throws HibernateException
128 */
129 public Set executeAsSet()
130 throws HibernateException
131 {
132 return new LinkedHashSet(this.executeAsList());
133 }
134
135 /**
136 * Executes a <code>HibernateQuery</code> using the currently defined
137 * <code>CriteriaSearchParameter</code>s, and returns a java.util.List
138 * containing the query results.
139 *
140 * @return result The result of the query as a List
141 * @throws HibernateException
142 */
143 public List executeAsList()
144 throws HibernateException
145 {
146 // add ordering
147 if (this.orderList.size() > 0)
148 {
149 Collections.sort(this.orderList, new ParameterComparator());
150 for (final CriteriaSearchParameter parameter : this.orderList)
151 {
152 int direction = parameter.getOrderDirection();
153 if (direction == SearchParameter.ORDER_ASC)
154 {
155 this.getParameterCriteria(parameter).addOrder(Order.asc(this.getParameterName(parameter)));
156 }
157 else
158 {
159 this.getParameterCriteria(parameter).addOrder(Order.desc(this.getParameterName(parameter)));
160 }
161 }
162 }
163
164 // set the first result if configured
165 if (this.configuration.getFirstResult() != null)
166 {
167 this.rootCriteria.setFirstResult(this.configuration.getFirstResult().intValue());
168 }
169
170 // set the fetch size if configured
171 if (this.configuration.getFetchSize() != null)
172 {
173 this.rootCriteria.setFetchSize(this.configuration.getFetchSize().intValue());
174 }
175
176 // limit the maximum result if configured
177 if (this.configuration.getMaximumResultSize() != null)
178 {
179 this.rootCriteria.setMaxResults(this.configuration.getMaximumResultSize().intValue());
180 }
181 this.rootCriteria.setCacheable(true);
182 return this.rootCriteria.list();
183 }
184
185 /**
186 * Adds a <code>CriteriaSearchParameter</code> to this search. The parameter is connected to
187 * the search by logical <b>and</b>. It is not considered if the value is <code>null</code>.
188 * If the value is not <code>null</code> it is compared using the
189 * <code>CriteriaSearchParameter.EQUALS_COMPARATOR</code>.
190 *
191 * @param parameterValue The value of the parameter.
192 * @param parameterPattern The pattern of the parameter (dot-separated path e.g. person.address.street).
193 * @throws HibernateException
194 */
195 public void addParameter(Object parameterValue, String parameterPattern)
196 throws HibernateException
197 {
198 addParameter(new CriteriaSearchParameter(parameterValue, parameterPattern));
199 }
200
201 /**
202 * Adds a <code>CriteriaSearchParameter</code> to this search. The parameter is connected to
203 * the search by logical <b>and</b>. It is not considered if the value is <code>null</code> or
204 * if the <code>String</code> empty. If the value is not <code>null</code> it is compared
205 * using the <code>CriteriaSearchParameter.LIKE_COMPARATOR</code>.
206 *
207 * @param parameterValue The value of the parameter.
208 * @param parameterPattern The pattern of the parameter (dot-separated path e.g. person.address.street).
209 * @throws HibernateException
210 */
211 public void addParameter(String parameterValue, String parameterPattern)
212 throws HibernateException
213 {
214 addParameter(new CriteriaSearchParameter(parameterValue, parameterPattern));
215 }
216
217 /**
218 * Adds a <code>CriteriaSearchParameter</code> to this search. The parameter is connected to
219 * the search by logical <b>and</b>.
220 *
221 * @param parameter The <code>CriteriaSearchParameter</code> to add.
222 * @throws HibernateException
223 */
224 public void addParameter(CriteriaSearchParameter parameter)
225 throws HibernateException
226 {
227 if (considerParameter(parameter))
228 {
229 final Criteria parameterCriteria = this.getParameterCriteria(parameter);
230 final String parameterName = this.getParameterName(parameter);
231
232 // check the type parameter value to add
233 if(parameter.getParameterValue() instanceof Object[])
234 {
235 addExpression(
236 parameterCriteria,
237 parameterName,
238 (Object[])parameter.getParameterValue(),
239 parameter.getComparator(),
240 parameter.getMatchMode());
241 }
242 else
243 {
244 addExpression(
245 parameterCriteria,
246 parameterName,
247 parameter.getParameterValue(),
248 parameter.getComparator(),
249 parameter.getMatchMode());
250 }
251 }
252 // if the parameter is to be ordered, add it to the order list
253 if (parameter.getOrderDirection() != SearchParameter.ORDER_UNSET)
254 {
255 this.orderList.add(parameter);
256 }
257 }
258
259 /**
260 * Retrieves the appropriate criteria object for the given <code>parameter</code>.
261 *
262 * @param parameter the parameter for which to retrieve the criteria.
263 * @return the retrieved criteria.
264 */
265 private Criteria getParameterCriteria(final CriteriaSearchParameter parameter)
266 throws HibernateException
267 {
268 String[] path = CriteriaSearchParameter.PATTERN.split(parameter.getParameterPattern());
269 Criteria parameterCriteria = this.rootCriteria;
270
271 Criteria childEntityCriteria;
272 if (path.length > 1)
273 {
274 // We have a parameter affecting an attribute of an inner childEntity object so we need
275 // to traverse to get the right criteria object
276 childEntityCriteria = this.rootCriteria;
277 // Evaluating the proper criteria object for the defined parameter
278 Class type = this.resultType;
279 for (int index = 0; index < (path.length - 1); index++)
280 {
281 final String childEntityName = path[index];
282 final Collection embeddedValues = CriteriaSearchProperties.getEmbeddedValues(type);
283 if (embeddedValues != null && embeddedValues.contains(childEntityName))
284 {
285 // - use the rest of the path as the parameter name
286 final int number = path.length - index;
287 final String[] restOfPath = new String[path.length - index];
288 System.arraycopy(path, index, restOfPath, 0, number);
289 break;
290 }
291 type = CriteriaSearchProperties.getNavigableAssociationEndType(type, childEntityName);
292 childEntityCriteria = locateCriteria(childEntityName, childEntityCriteria);
293 }
294 if (childEntityCriteria != null)
295 {
296 // We now have the right criteria object
297 parameterCriteria = childEntityCriteria;
298 }
299 }
300 return parameterCriteria;
301 }
302
303 /**
304 * Retrieves the appropriate nested parameter name for the given <code>parameter</code>.
305 *
306 * @param parameter the parameter for which to retrieve the parameter name.
307 * @return the parameter name.
308 */
309 private String getParameterName(final CriteriaSearchParameter parameter)
310 {
311 // parsing the pattern of the parameter
312 String[] path = CriteriaSearchParameter.PATTERN.split(parameter.getParameterPattern());
313 String parameterName = path[path.length - 1];
314 if (path.length > 1)
315 {
316 // We have a parameter affecting an attribute of an inner childEntity object so we need
317 // to traverse to get the correct parameter name
318 // Evaluating the proper criteria object for the defined parameter
319 Class type = this.resultType;
320 for (int index = 0; index < (path.length - 1); index++)
321 {
322 final String childEntityName = path[index];
323 final Collection embeddedValues = CriteriaSearchProperties.getEmbeddedValues(type);
324 if (embeddedValues != null && embeddedValues.contains(childEntityName))
325 {
326 // - use the rest of the path as the parameter name
327 final int number = path.length - index;
328 final String[] restOfPath = new String[path.length - index];
329 System.arraycopy(path, index, restOfPath, 0, number);
330 parameterName = StringUtils.join(restOfPath, ".");
331 break;
332 }
333 type = CriteriaSearchProperties.getNavigableAssociationEndType(type, childEntityName);
334 }
335 }
336 return parameterName;
337 }
338
339 /**
340 * Decides whether a paramter is considered as a criteria for a search depending on the type and
341 * value of the <code>parameterValue</code> and <code>searchIfIsNull</code>. A
342 * <code>parameterValue</code> of the type <code>String</code> is considered
343 * <code>null</code> if being a <code>NullPointer</code> or empty.
344 *
345 * @param parameter The parameter to check.
346 */
347 private boolean considerParameter(CriteriaSearchParameter parameter)
348 {
349 if (parameter.getParameterValue() instanceof String)
350 {
351 String stringParameterValue = (String) parameter.getParameterValue();
352 return (parameter.isSearchIfNull()
353 || (stringParameterValue != null && stringParameterValue.length() > 0));
354 }
355 if (parameter.getParameterValue() instanceof Object[])
356 {
357 Object[] parameterValues = (Object[]) parameter.getParameterValue();
358 return (parameter.isSearchIfNull()
359 || (parameterValues != null && parameterValues.length > 0));
360 }
361 final int comparator = parameter.getComparator();
362 return (parameter.isSearchIfNull() ||
363 SearchParameter.NOT_NULL_COMPARATOR == comparator ||
364 SearchParameter.NULL_COMPARATOR == comparator ||
365 SearchParameter.EMPTY_COMPARATOR == comparator ||
366 SearchParameter.NOT_EMPTY_COMPARATOR == comparator) ||
367 (parameter.getParameterValue() != null);
368 }
369
370 /**
371 * Adds an <code>Restrictions</code> to a <code>Criteria</code>.
372 *
373 * @param criteria
374 * @param parameterName
375 * @param parameterValue
376 * @param comparator
377 * @param matchMode
378 */
379 private void addExpression(
380 Criteria criteria,
381 String parameterName,
382 Object parameterValue,
383 int comparator,
384 MatchMode matchMode)
385 {
386 switch (comparator)
387 {
388 case SearchParameter.NOT_NULL_COMPARATOR:
389 {
390 criteria.add(Restrictions.isNotNull(parameterName));
391 break;
392 }
393 case SearchParameter.NULL_COMPARATOR:
394 {
395 criteria.add(Restrictions.isNull(parameterName));
396 break;
397 }
398 case SearchParameter.EMPTY_COMPARATOR:
399 {
400 criteria.add(Restrictions.isEmpty(parameterName));
401 break;
402 }
403 case SearchParameter.NOT_EMPTY_COMPARATOR:
404 {
405 criteria.add(Restrictions.isNotEmpty(parameterName));
406 break;
407 }
408 default:
409 {
410 if (parameterValue != null)
411 {
412 switch (comparator)
413 {
414 case SearchParameter.LIKE_COMPARATOR:
415 {
416 if ((matchMode != null) && (parameterValue instanceof String))
417 {
418 criteria.add(Restrictions.like(
419 parameterName,
420 (String)parameterValue,
421 matchMode));
422 }
423 else
424 {
425 criteria.add(Restrictions.like(parameterName, parameterValue));
426 }
427 break;
428 }
429 case SearchParameter.NOT_LIKE_COMPARATOR:
430 {
431 SimpleExpression expression;
432 if ((matchMode != null) && (parameterValue instanceof String))
433 {
434 expression = Restrictions.like(
435 parameterName,
436 (String)parameterValue,
437 matchMode);
438 }
439 else
440 {
441 expression = Restrictions.like(parameterName, parameterValue);
442 }
443 criteria.add(Restrictions.not(expression));
444 break;
445 }
446 case SearchParameter.INSENSITIVE_LIKE_COMPARATOR:
447 {
448 if ((matchMode != null) && (parameterValue instanceof String))
449 {
450 criteria.add(Restrictions.ilike(
451 parameterName,
452 (String)parameterValue,
453 matchMode));
454 }
455 else
456 {
457 criteria.add(Restrictions.ilike(parameterName, parameterValue));
458 }
459 break;
460 }
461 case SearchParameter.NOT_INSENSITIVE_LIKE_COMPARATOR:
462 {
463 Criterion criterion;
464 if ((matchMode != null) && (parameterValue instanceof String))
465 {
466 criterion = Restrictions.ilike(
467 parameterName,
468 (String)parameterValue,
469 matchMode);
470 }
471 else
472 {
473 criterion = Restrictions.ilike(parameterName, parameterValue);
474 }
475 criteria.add(Restrictions.not(criterion));
476 break;
477 }
478 case SearchParameter.EQUAL_COMPARATOR:
479 {
480 criteria.add(Restrictions.eq(parameterName, parameterValue));
481 break;
482 }
483 case SearchParameter.GREATER_THAN_OR_EQUAL_COMPARATOR:
484 {
485 criteria.add(Restrictions.ge(parameterName, parameterValue));
486 break;
487 }
488 case SearchParameter.GREATER_THAN_COMPARATOR:
489 {
490 criteria.add(Restrictions.gt(parameterName, parameterValue));
491 break;
492 }
493 case SearchParameter.LESS_THAN_OR_EQUAL_COMPARATOR:
494 {
495 criteria.add(Restrictions.le(parameterName, parameterValue));
496 break;
497 }
498 case SearchParameter.LESS_THAN_COMPARATOR:
499 {
500 criteria.add(Restrictions.lt(parameterName, parameterValue));
501 break;
502 }
503 case SearchParameter.IN_COMPARATOR:
504 {
505 if (parameterValue instanceof Collection)
506 {
507 criteria.add(Restrictions.in(parameterName, (Collection)parameterValue));
508 }
509 break;
510 }
511 case SearchParameter.NOT_IN_COMPARATOR:
512 {
513 if (parameterValue instanceof Collection)
514 {
515 criteria.add(Restrictions.not(Restrictions.in(parameterName, (Collection)parameterValue)));
516 }
517 break;
518 }
519 case SearchParameter.NOT_EQUAL_COMPARATOR:
520 {
521 criteria.add(Restrictions.ne(parameterName, parameterValue));
522 break;
523 }
524 }
525 }
526 else
527 {
528 criteria.add(Restrictions.isNull(parameterName));
529 }
530 }
531 }
532 }
533
534 /**
535 * Adds an <code>Restrictions</code> to a <code>Criteria</code>. The given <code>parameterValues</code>
536 * represents either an array of <code>String</code> or another object. The different values in the
537 * array are added to a disjunction or conjunction which is connected with logical and to the other criteria of the
538 * search.
539 *
540 * @param criteria
541 * @param parameterName
542 * @param parameterValues
543 * @param searchIfNull
544 * @param comparator
545 * @param matchMode
546 */
547 private void addExpression(
548 Criteria criteria,
549 String parameterName,
550 Object[] parameterValues,
551 int comparator,
552 MatchMode matchMode)
553 {
554 if (parameterValues != null)
555 {
556 Disjunction disjunction = null;
557 Conjunction conjunction = null;
558 switch (comparator)
559 {
560 case SearchParameter.LIKE_COMPARATOR:
561 {
562 disjunction = Restrictions.disjunction();
563 if ((matchMode != null) && (parameterValues instanceof String[]))
564 {
565 String[] stringParameterValues = (String[]) parameterValues;
566 for (int index = 0; index < parameterValues.length; index++)
567 {
568 if (stringParameterValues[index] != null)
569 {
570 disjunction.add(Restrictions.like(
571 parameterName, stringParameterValues[index], matchMode));
572 }
573 else
574 {
575 disjunction.add(Restrictions
576 .isNull(parameterName));
577 }
578 }
579 }
580 else
581 {
582 for (int index = 0; index < parameterValues.length; index++)
583 {
584 if (parameterValues[index] != null)
585 {
586 disjunction.add(Restrictions.like(
587 parameterName, parameterValues[index]));
588 }
589 else
590 {
591 disjunction.add(Restrictions
592 .isNull(parameterName));
593 }
594 }
595 }
596 break;
597 }
598 case SearchParameter.INSENSITIVE_LIKE_COMPARATOR:
599 {
600 disjunction = Restrictions.disjunction();
601 if ((matchMode != null) && (parameterValues instanceof String[]))
602 {
603 String[] stringParameterValues = (String[]) parameterValues;
604 for (int index = 0; index < parameterValues.length; index++)
605 {
606 if (stringParameterValues[index] != null) {
607 disjunction.add(Restrictions.ilike(
608 parameterName, stringParameterValues[index], matchMode));
609 }
610 else {
611 disjunction.add(Restrictions
612 .isNull(parameterName));
613 }
614 }
615 }
616 else
617 {
618 for (int index = 0; index < parameterValues.length; index++)
619 {
620 if (parameterValues[index] != null)
621 {
622 disjunction.add(Restrictions.ilike(
623 parameterName, parameterValues[index]));
624 }
625 else
626 {
627 disjunction.add(Restrictions
628 .isNull(parameterName));
629 }
630 }
631 }
632 break;
633 }
634 case SearchParameter.EQUAL_COMPARATOR:
635 {
636 disjunction = Restrictions.disjunction();
637 for (int index = 0; index < parameterValues.length; index++)
638 {
639 if (parameterValues[index] != null)
640 {
641 disjunction.add(Restrictions.eq(parameterName,
642 parameterValues[index]));
643 }
644 else {
645 disjunction.add(Restrictions.isNull(parameterName));
646 }
647 }
648 break;
649 }
650 case SearchParameter.GREATER_THAN_OR_EQUAL_COMPARATOR:
651 {
652 disjunction = Restrictions.disjunction();
653 for (int index = 0; index < parameterValues.length; index++)
654 {
655 if (parameterValues[index] != null)
656 {
657 disjunction.add(Restrictions.ge(parameterName,
658 parameterValues[index]));
659 }
660 else
661 {
662 disjunction.add(Restrictions.isNull(parameterName));
663 }
664 }
665 break;
666 }
667 case SearchParameter.GREATER_THAN_COMPARATOR:
668 {
669 disjunction = Restrictions.disjunction();
670 for (int index = 0; index < parameterValues.length; index++)
671 {
672 if (parameterValues[index] != null)
673 {
674 disjunction.add(Restrictions.gt(parameterName,
675 parameterValues[index]));
676 }
677 else
678 {
679 disjunction.add(Restrictions.isNull(parameterName));
680 }
681 }
682 break;
683 }
684 case SearchParameter.LESS_THAN_OR_EQUAL_COMPARATOR:
685 {
686 disjunction = Restrictions.disjunction();
687 for (int index = 0; index < parameterValues.length; index++)
688 {
689 if (parameterValues[index] != null)
690 {
691 disjunction.add(Restrictions.le(parameterName,
692 parameterValues[index]));
693 }
694 else
695 {
696 disjunction.add(Restrictions.isNull(parameterName));
697 }
698 }
699 break;
700 }
701 case SearchParameter.LESS_THAN_COMPARATOR:
702 {
703 disjunction = Restrictions.disjunction();
704 for (int index = 0; index < parameterValues.length; index++)
705 {
706 if (parameterValues[index] != null)
707 {
708 disjunction.add(Restrictions.lt(parameterName,
709 parameterValues[index]));
710 }
711 else
712 {
713 disjunction.add(Restrictions.isNull(parameterName));
714 }
715 }
716 break;
717 }
718 case SearchParameter.IN_COMPARATOR:
719 {
720 criteria.add(Restrictions.in(parameterName, parameterValues));
721 break;
722 }
723 case SearchParameter.NOT_IN_COMPARATOR:
724 {
725 criteria.add(Restrictions.not(Restrictions.in(parameterName, parameterValues)));
726 break;
727 }
728 case SearchParameter.NOT_EQUAL_COMPARATOR:
729 {
730 conjunction = Restrictions.conjunction();
731 for (int index = 0; index < parameterValues.length; index++)
732 {
733 if (parameterValues[index] != null)
734 {
735 conjunction.add(Restrictions.ne(parameterName,
736 parameterValues[index]));
737 }
738 else
739 {
740 conjunction.add(Restrictions.isNotNull(parameterName));
741 }
742 }
743 break;
744 }
745 }
746
747 if (disjunction != null)
748 {
749 criteria.add(disjunction);
750 }
751 if (conjunction != null)
752 {
753 criteria.add(conjunction);
754 }
755 }
756 else
757 {
758 switch (comparator)
759 {
760 case SearchParameter.EMPTY_COMPARATOR:
761 {
762 criteria.add(Restrictions.isEmpty(parameterName));
763 break;
764 }
765 case SearchParameter.NOT_EMPTY_COMPARATOR:
766 {
767 criteria.add(Restrictions.isNotEmpty(parameterName));
768 break;
769 }
770 default:
771 {
772 criteria.add(Restrictions.isNull(parameterName));
773 }
774 }
775 }
776 }
777
778 /**
779 * Locates a <code>Criteria</code> for a <code>childEntityName</code>. If a
780 * <code>Criteria</code> exists for the <code>childEntityName</code>, it is returned. If
781 * not, one is created and referenced in the <code>childCriteriaMap</code> under the
782 * <code>childEntityName</code>.
783 *
784 * @param childEntityName
785 * @param parentCriteria
786 * @return criteria The Criteria for the childEntityName.
787 * @throws HibernateException
788 */
789 private Criteria locateCriteria(String childEntityName, Criteria parentCriteria) throws HibernateException
790 {
791 if (this.childCriteriaMap.containsKey(childEntityName))
792 {
793 return (Criteria) this.childCriteriaMap.get(childEntityName);
794 }
795 Criteria childCriteria = parentCriteria.createCriteria(childEntityName);
796 if (this.configuration.isForceEagerLoading())
797 {
798 parentCriteria.setFetchMode(childEntityName, FetchMode.JOIN);
799 }
800
801 // Hibernate does not support a 'unique' identifier. As a search may contain outer joins,
802 // duplicates in the resultList are possible. We eliminate any duplicates here, creating a
803 // distinctified resultSet (Suggestion from Hibernate itself; see www.hibernate.org's FAQ's).
804 parentCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
805 this.childCriteriaMap.put(childEntityName, childCriteria);
806 return childCriteria;
807 }
808
809 /**
810 * Returns the configuration of this search.
811 *
812 * @return configuration
813 */
814 public CriteriaSearchConfiguration getConfiguration()
815 {
816 return this.configuration;
817 }
818 }