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