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.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 }