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