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}