001 /* 002 * Copyright 2002-2004 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 005 * use this file except in compliance with the License. You may obtain a copy of 006 * the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 012 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 013 * License for the specific language governing permissions and limitations under 014 * the License. 015 */ 016 package org.springframework.rules.factory; 017 018 import java.util.Comparator; 019 import java.util.Set; 020 021 import org.springframework.rules.closure.Closure; 022 import org.springframework.rules.constraint.Constraint; 023 import org.springframework.rules.closure.support.AlgorithmsAccessor; 024 import org.springframework.rules.closure.BinaryConstraint; 025 import org.springframework.rules.constraint.*; 026 import org.springframework.rules.constraint.Like.LikeType; 027 import org.springframework.rules.constraint.property.CompoundPropertyConstraint; 028 import org.springframework.rules.constraint.property.ConditionalPropertyConstraint; 029 import org.springframework.rules.constraint.property.NegatedPropertyConstraint; 030 import org.springframework.rules.constraint.property.ParameterizedPropertyConstraint; 031 import org.springframework.rules.constraint.property.PropertiesConstraint; 032 import org.springframework.rules.constraint.property.PropertyConstraint; 033 import org.springframework.rules.constraint.property.PropertyValueConstraint; 034 import org.springframework.rules.constraint.property.UniquePropertyValueConstraint; 035 import org.springframework.util.Assert; 036 import org.springframework.util.ObjectUtils; 037 038 /** 039 * A factory for easing the construction and composition of constraints. 040 * 041 * @author Keith Donald 042 */ 043 public class Constraints extends AlgorithmsAccessor { 044 045 private static Constraints INSTANCE = new Constraints(); 046 047 public Constraints() { 048 049 } 050 051 public static Constraints instance() { 052 return INSTANCE; 053 } 054 055 public static void load(Constraints sharedInstance) { 056 Assert.notNull(sharedInstance, "The global constraints factory cannot be null"); 057 INSTANCE = sharedInstance; 058 } 059 060 /** 061 * Bind the specified parameter to the second argument of the 062 * <code>BinaryConstraint</code>. The result is a <code>Constraint</code> 063 * which will test a single variable argument against the constant 064 * parameter. 065 * 066 * @param constraint the binary constraint to bind to 067 * @param parameter the parameter value (constant) 068 * @return The constraint 069 */ 070 public Constraint bind(BinaryConstraint constraint, Object parameter) { 071 return new ParameterizedBinaryConstraint(constraint, parameter); 072 } 073 074 /** 075 * Bind the specified <code>int</code> parameter to the second argument of 076 * the <code>BinaryConstraint</code>. The result is a 077 * <code>Constraint</code> which will test a single variable argument 078 * against the constant <code>int</code> parameter. 079 * 080 * @param constraint the binary constraint to bind to 081 * @param parameter the <code>int</code> parameter value (constant) 082 * @return The constraint 083 */ 084 public Constraint bind(BinaryConstraint constraint, int parameter) { 085 return new ParameterizedBinaryConstraint(constraint, parameter); 086 } 087 088 /** 089 * Bind the specified <code>float</code> parameter to the second argument 090 * of the <code>BinaryConstraint</code>. The result is a 091 * <code>Constraint</code> which will test a single variable argument 092 * against the constant <code>float</code> parameter. 093 * 094 * @param constraint the binary constraint to bind to 095 * @param parameter the <code>float</code> parameter value (constant) 096 * @return The constraint 097 */ 098 public Constraint bind(BinaryConstraint constraint, float parameter) { 099 return new ParameterizedBinaryConstraint(constraint, parameter); 100 } 101 102 /** 103 * Bind the specified <code>double</code> parameter to the second argument 104 * of the <code>BinaryConstraint</code>. The result is a 105 * <code>Constraint</code> which will test a single variable argument 106 * against the constant <code>double</code> parameter. 107 * 108 * @param constraint the binary constraint to bind to 109 * @param parameter the <code>double</code> parameter value (constant) 110 * @return The constraint 111 */ 112 public Constraint bind(BinaryConstraint constraint, double parameter) { 113 return new ParameterizedBinaryConstraint(constraint, parameter); 114 } 115 116 /** 117 * Bind the specified <code>boolean</code> parameter to the second 118 * argument of the <code>BinaryConstraint</code>. The result is a 119 * <code>Constraint</code> which will test a single variable argument 120 * against the constant <code>boolean</code> parameter. 121 * 122 * @param constraint the binary constraint to bind to 123 * @param parameter the <code>boolean</code> parameter value (constant) 124 * @return The constraint 125 */ 126 public Constraint bind(BinaryConstraint constraint, boolean parameter) { 127 return new ParameterizedBinaryConstraint(constraint, parameter); 128 } 129 130 /** 131 * Attaches a constraint that tests the result returned by evaluating the 132 * specified closure. This effectively attaches a constraint on the closure 133 * return value. 134 * 135 * @param closure the closure 136 * @param constraint the constraint to test the closure result 137 * @return The testing constraint, which on the call to test(o) first 138 * evaluates 'o' using the closure and then tests the result. 139 */ 140 public Constraint testResultOf(Closure closure, Constraint constraint) { 141 return new ClosureResultConstraint(closure, constraint); 142 } 143 144 public Constraint eq(Object value) { 145 return EqualTo.value(value); 146 } 147 148 public Constraint eq(int value) { 149 return eq(new Integer(value)); 150 } 151 152 public Constraint eq(Object value, Comparator comparator) { 153 return EqualTo.value(value, comparator); 154 } 155 156 public Constraint gt(Comparable value) { 157 return GreaterThan.value(value); 158 } 159 160 public Constraint gt(Object value, Comparator comparator) { 161 return GreaterThan.value(value, comparator); 162 } 163 164 public Constraint gt(int value) { 165 return gt(new Integer(value)); 166 } 167 168 public Constraint gt(long value) { 169 return gt(new Long(value)); 170 } 171 172 public Constraint gt(float value) { 173 return gt(new Float(value)); 174 } 175 176 public Constraint gt(double value) { 177 return gt(new Double(value)); 178 } 179 180 public Constraint gte(Comparable value) { 181 return GreaterThanEqualTo.value(value); 182 } 183 184 public Constraint gte(Object value, Comparator comparator) { 185 return GreaterThanEqualTo.value(value, comparator); 186 } 187 188 public Constraint gte(int value) { 189 return gte(new Integer(value)); 190 } 191 192 public Constraint gte(long value) { 193 return gte(new Long(value)); 194 } 195 196 public Constraint gte(float value) { 197 return gte(new Float(value)); 198 } 199 200 public Constraint gte(double value) { 201 return gte(new Double(value)); 202 } 203 204 public Constraint lt(Comparable value) { 205 return LessThan.value(value); 206 } 207 208 public Constraint lt(Comparable value, Comparator comparator) { 209 return LessThan.value(value, comparator); 210 } 211 212 public Constraint lt(int value) { 213 return lt(new Integer(value)); 214 } 215 216 public Constraint lt(long value) { 217 return lt(new Long(value)); 218 } 219 220 public Constraint lt(float value) { 221 return lt(new Float(value)); 222 } 223 224 public Constraint lt(double value) { 225 return lt(new Double(value)); 226 } 227 228 public Constraint lte(Comparable value) { 229 return LessThanEqualTo.value(value); 230 } 231 232 public Constraint lte(Object value, Comparator comparator) { 233 return LessThanEqualTo.value(value, comparator); 234 } 235 236 public Constraint lte(int value) { 237 return lte(new Integer(value)); 238 } 239 240 public Constraint lte(long value) { 241 return lte(new Long(value)); 242 } 243 244 public Constraint lte(float value) { 245 return lte(new Float(value)); 246 } 247 248 public Constraint lte(double value) { 249 return lte(new Double(value)); 250 } 251 252 public Constraint range(Comparable min, Comparable max) { 253 return new Range(min, max); 254 } 255 256 public Constraint range(Comparable min, Comparable max, boolean inclusive) { 257 return new Range(min, max, inclusive); 258 } 259 260 public Constraint range(Object min, Object max, Comparator comparator) { 261 return new Range(min, max, comparator); 262 } 263 264 public Constraint range(Object min, Object max, Comparator comparator, boolean inclusive) { 265 return new Range(min, max, comparator, inclusive); 266 } 267 268 public Constraint range(int min, int max) { 269 return new Range(min, max); 270 } 271 272 public Constraint range(long min, long max) { 273 return new Range(min, max); 274 } 275 276 public Constraint range(float min, float max) { 277 return new Range(min, max); 278 } 279 280 public Constraint range(double min, double max) { 281 return new Range(min, max); 282 } 283 284 public Constraint present() { 285 return Required.present(); 286 } 287 288 /** 289 * Returns a required constraint. 290 * 291 * @return The required constraint instance. 292 */ 293 public Constraint required() { 294 return Required.instance(); 295 } 296 297 public Constraint ifTrue(Constraint constraint, Constraint mustAlsoBeTrue) { 298 return new IfTrue(constraint, mustAlsoBeTrue); 299 } 300 301 public Constraint ifTrue(Constraint constraint, Constraint mustAlsoBeTrue, Constraint elseMustAlsoBeTrue) { 302 return new IfTrue(constraint, mustAlsoBeTrue, elseMustAlsoBeTrue); 303 } 304 305 public Constraint ifTrue(Constraint constraint, Constraint mustAlsoBeTrue, String type) { 306 return new IfTrue(constraint, mustAlsoBeTrue, type); 307 } 308 309 public Constraint ifTrue(Constraint constraint, Constraint mustAlsoBeTrue, Constraint elseMustAlsoBeTrue, String type) { 310 return new IfTrue(constraint, mustAlsoBeTrue, elseMustAlsoBeTrue, type); 311 } 312 313 /** 314 * Returns a ConditionalPropertyConstraint: one property will trigger the 315 * validation of another. 316 * 317 * @see ConditionalPropertyConstraint 318 */ 319 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint) { 320 return new ConditionalPropertyConstraint(ifConstraint, thenConstraint); 321 } 322 323 /** 324 * Returns a ConditionalPropertyConstraint: one property will trigger the 325 * validation of another. 326 * 327 * @see ConditionalPropertyConstraint 328 */ 329 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, String type) { 330 return new ConditionalPropertyConstraint(ifConstraint, thenConstraint, type); 331 } 332 333 /** 334 * Returns a ConditionalPropertyConstraint: one property will trigger the 335 * validation of another. 336 * 337 * @see ConditionalPropertyConstraint 338 */ 339 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, 340 PropertyConstraint elseConstraint) { 341 return new ConditionalPropertyConstraint(ifConstraint, thenConstraint, elseConstraint); 342 } 343 344 /** 345 * Returns a ConditionalPropertyConstraint: one property will trigger the 346 * validation of another. 347 * 348 * @see ConditionalPropertyConstraint 349 */ 350 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, 351 PropertyConstraint elseConstraint, String type) { 352 return new ConditionalPropertyConstraint(ifConstraint, thenConstraint, elseConstraint, type); 353 } 354 355 /** 356 * Returns a ConditionalPropertyConstraint: one property will trigger the 357 * validation of another. 358 * 359 * @see ConditionalPropertyConstraint 360 */ 361 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint[] thenConstraints) { 362 return new ConditionalPropertyConstraint(ifConstraint, new CompoundPropertyConstraint(new And(thenConstraints))); 363 } 364 365 /** 366 * Returns a ConditionalPropertyConstraint: one property will trigger the 367 * validation of another. 368 * 369 * @see ConditionalPropertyConstraint 370 */ 371 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint[] thenConstraints, String type) { 372 return new ConditionalPropertyConstraint(ifConstraint, new CompoundPropertyConstraint(new And(thenConstraints)), type); 373 } 374 375 /** 376 * Returns a ConditionalPropertyConstraint: one property will trigger the 377 * validation of another. 378 * 379 * @see ConditionalPropertyConstraint 380 */ 381 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint[] thenConstraints, 382 PropertyConstraint[] elseConstraints) { 383 return new ConditionalPropertyConstraint(ifConstraint, 384 new CompoundPropertyConstraint(new And(thenConstraints)), new CompoundPropertyConstraint(new And( 385 elseConstraints))); 386 } 387 388 /** 389 * Returns a ConditionalPropertyConstraint: one property will trigger the 390 * validation of another. 391 * 392 * @see ConditionalPropertyConstraint 393 */ 394 public PropertyConstraint ifTrue(PropertyConstraint ifConstraint, PropertyConstraint[] thenConstraints, 395 PropertyConstraint[] elseConstraints, String type) { 396 return new ConditionalPropertyConstraint(ifConstraint, 397 new CompoundPropertyConstraint(new And(thenConstraints)), new CompoundPropertyConstraint(new And( 398 elseConstraints)), type); 399 } 400 401 /** 402 * Returns a maxlength constraint. 403 * 404 * @param maxLength The maximum length in characters. 405 * @return The configured maxlength constraint. 406 */ 407 public Constraint maxLength(int maxLength) { 408 return new StringLengthConstraint(maxLength); 409 } 410 411 /** 412 * Returns a minlength constraint. 413 * 414 * @param minLength The minimum length in characters. 415 * @return The configured minlength constraint. 416 */ 417 public Constraint minLength(int minLength) { 418 return new StringLengthConstraint(RelationalOperator.GREATER_THAN_EQUAL_TO, minLength); 419 } 420 421 /** 422 * Returns a 'like' constraint. 423 * 424 * @param encodedLikeString the likeString 425 * @return The Like constraint. 426 */ 427 public Constraint like(String encodedLikeString) { 428 return new Like(encodedLikeString); 429 } 430 431 /** 432 * Creates a constraint backed by a regular expression. 433 * 434 * @param regexp The regular expression string. 435 * @return The constraint. 436 */ 437 public Constraint regexp(String regexp) { 438 return new RegexpConstraint(regexp); 439 } 440 441 /** 442 * Creates a constraint backed by a regular expression, with a type for 443 * reporting. 444 * 445 * @param regexp The regular expression string. 446 * @return The constraint. 447 */ 448 public Constraint regexp(String regexp, String type) { 449 RegexpConstraint c = new RegexpConstraint(regexp); 450 c.setType(type); 451 return c; 452 } 453 454 /** 455 * Returns a constraint whose test is determined by a boolean method on a 456 * target object. 457 * 458 * @param targetObject The targetObject 459 * @param methodName The method name 460 * @return The constraint. 461 */ 462 public Constraint method(Object target, String methodName, String constraintType) { 463 return new MethodInvokingConstraint(target, methodName, constraintType); 464 } 465 466 /** 467 * Returns a 'in' group (or set) constraint. 468 * 469 * @param group the group items 470 * @return The InGroup constraint 471 */ 472 public Constraint inGroup(Set group) { 473 return new InGroup(group); 474 } 475 476 /** 477 * Returns a 'in' group (or set) constraint. 478 * 479 * @param group the group items 480 * @return The InGroup constraint. 481 */ 482 public Constraint inGroup(Object[] group) { 483 return new InGroup(group); 484 } 485 486 /** 487 * Returns a 'in' group (or set) constraint. 488 * 489 * @param group the group items 490 * @return The InGroup constraint. 491 */ 492 public Constraint inGroup(int[] group) { 493 return inGroup(ObjectUtils.toObjectArray(group)); 494 } 495 496 /** 497 * AND two constraints. 498 * 499 * @param constraint1 the first constraint 500 * @param constraint2 the second constraint 501 * @return The compound AND constraint 502 */ 503 public And and(Constraint constraint1, Constraint constraint2) { 504 return new And(constraint1, constraint2); 505 } 506 507 /** 508 * Return the conjunction (all constraint) for all constraints. 509 * 510 * @param constraints the constraints 511 * @return The compound AND constraint 512 */ 513 public And all(Constraint[] constraints) { 514 return new And(constraints); 515 } 516 517 /** 518 * Returns a new, empty conjunction prototype, capable of composing 519 * individual constraints where 'ALL' must test true. 520 * 521 * @return the UnaryAnd 522 */ 523 public And conjunction() { 524 return new And(); 525 } 526 527 /** 528 * OR two constraints. 529 * 530 * @param constraint1 the first constraint 531 * @param constraint2 the second constraint 532 * @return The compound OR constraint 533 */ 534 public Or or(Constraint constraint1, Constraint constraint2) { 535 return new Or(constraint1, constraint2); 536 } 537 538 /** 539 * Return the disjunction (any constraint) for all constraints. 540 * 541 * @param constraints the constraints 542 * @return The compound AND constraint 543 */ 544 public Or any(Constraint[] constraints) { 545 return new Or(constraints); 546 } 547 548 /** 549 * Returns a new, empty disjunction prototype, capable of composing 550 * individual constraints where 'ANY' must test true. 551 * 552 * @return the UnaryOr 553 */ 554 public Or disjunction() { 555 return new Or(); 556 } 557 558 /** 559 * Returns a new, empty exclusive disjunction prototype, capable of composing 560 * individual constraints where only one must test true. 561 * 562 * @return the UnaryXOr 563 */ 564 public XOr exclusiveDisjunction() { 565 return new XOr(); 566 } 567 568 /** 569 * Negate the specified constraint. 570 * 571 * @param constraint The constraint to negate 572 * @return The negated constraint. 573 */ 574 public Constraint not(Constraint constraint) { 575 if (!(constraint instanceof Not)) 576 return new Not(constraint); 577 578 return ((Not)constraint).getConstraint(); 579 } 580 581 /** 582 * Attach a value constraint for the provided bean property. 583 * 584 * @param propertyName the bean property name 585 * @param valueConstraint the value constraint 586 * @return The bean property expression that tests the constraint 587 */ 588 public PropertyConstraint value(String propertyName, Constraint valueConstraint) { 589 return new PropertyValueConstraint(propertyName, valueConstraint); 590 } 591 592 /** 593 * Returns a present bean property expression. 594 * 595 * @return The present constraint instance. 596 */ 597 public PropertyConstraint present(String propertyName) { 598 return value(propertyName, present()); 599 } 600 601 /** 602 * Returns a required bean property expression. 603 * 604 * @return The required constraint instance. 605 */ 606 public PropertyConstraint required(String property) { 607 return value(property, required()); 608 } 609 610 /** 611 * Return a 'like' constraint applied as a value constraint to the provided 612 * property. 613 * 614 * @param property The property to constrain 615 * @param likeType The like type 616 * @param value The like string value to match 617 * @return The Like constraint 618 */ 619 public PropertyConstraint like(String property, LikeType likeType, String value) { 620 return value(property, new Like(likeType, value)); 621 } 622 623 /** 624 * Returns a 'in' group (or set) constraint appled to the provided property. 625 * 626 * @param propertyName the property 627 * @param group the group items 628 * @return The InGroup constraint. 629 */ 630 public PropertyConstraint inGroup(String propertyName, Object[] group) { 631 return value(propertyName, new InGroup(group)); 632 } 633 634 /** 635 * Apply an "all" value constraint to the provided bean property. 636 * 637 * @param propertyName The bean property name 638 * @param constraints The constraints that form a all conjunction 639 * @return 640 */ 641 public PropertyConstraint all(String propertyName, Constraint[] constraints) { 642 return value(propertyName, all(constraints)); 643 } 644 645 /** 646 * Apply an "any" value constraint to the provided bean property. 647 * 648 * @param propertyName The bean property name 649 * @param constraints The constraints that form a all disjunction 650 * @return 651 */ 652 public PropertyConstraint any(String propertyName, Constraint[] constraints) { 653 return value(propertyName, any(constraints)); 654 } 655 656 /** 657 * Negate a bean property expression. 658 * 659 * @param e the expression to negate 660 * @return The negated expression 661 */ 662 public PropertyConstraint not(PropertyConstraint e) { 663 return new NegatedPropertyConstraint(e); 664 } 665 666 public PropertyConstraint valueProperty(String propertyName, BinaryConstraint constraint, Object value) { 667 return new ParameterizedPropertyConstraint(propertyName, constraint, value); 668 } 669 670 /** 671 * Apply a "equal to" constraint to a bean property. 672 * 673 * @param propertyName The first property 674 * @param propertyValue The constraint value 675 * @return The constraint 676 */ 677 public PropertyConstraint eq(String propertyName, Object propertyValue) { 678 return new ParameterizedPropertyConstraint(propertyName, eq(propertyValue)); 679 } 680 681 /** 682 * Apply a "equal to" constraint to a bean property. 683 * 684 * @param propertyName The first property 685 * @param propertyValue The constraint value 686 * @param comparator the comparator to use while comparing the values 687 * @return The constraint 688 * 689 * @since 0.3.0 690 */ 691 public PropertyConstraint eq(String propertyName, Object propertyValue, Comparator comparator) { 692 return new ParameterizedPropertyConstraint(propertyName, eq(propertyValue, comparator)); 693 } 694 695 /** 696 * Apply a "greater than" constraint to a bean property. 697 * 698 * @param propertyName The first property 699 * @param propertyValue The constraint value 700 * @return The constraint 701 */ 702 public PropertyConstraint gt(String propertyName, Comparable propertyValue) { 703 return new ParameterizedPropertyConstraint(propertyName, gt(propertyValue)); 704 } 705 706 /** 707 * Apply a "greater than equal to" constraint to a bean property. 708 * 709 * @param propertyName The first property 710 * @param propertyValue The constraint value 711 * @return The constraint 712 */ 713 public PropertyConstraint gte(String propertyName, Comparable propertyValue) { 714 return new ParameterizedPropertyConstraint(propertyName, gte(propertyValue)); 715 } 716 717 /** 718 * Apply a "less than" constraint to a bean property. 719 * 720 * @param propertyName The first property 721 * @param propertyValue The constraint value 722 * @return The constraint 723 */ 724 public PropertyConstraint lt(String propertyName, Comparable propertyValue) { 725 return new ParameterizedPropertyConstraint(propertyName, lt(propertyValue)); 726 } 727 728 /** 729 * Apply a "less than equal to" constraint to a bean property. 730 * 731 * @param propertyName The first property 732 * @param propertyValue The constraint value 733 * @return The constraint 734 */ 735 public PropertyConstraint lte(String propertyName, Comparable propertyValue) { 736 return new ParameterizedPropertyConstraint(propertyName, lte(propertyValue)); 737 } 738 739 public PropertyConstraint valueProperties(String propertyName, BinaryConstraint constraint, String otherPropertyName) { 740 return new PropertiesConstraint(propertyName, constraint, otherPropertyName); 741 } 742 743 /** 744 * Apply a "equal to" constraint to two bean properties. 745 * 746 * @param propertyName The first property 747 * @param otherPropertyName The other property 748 * @param comparator the comparator to use while comparing the values 749 * @return The constraint 750 * 751 * @since 0.3.0 752 */ 753 public PropertyConstraint eqProperty(String propertyName, String otherPropertyName, Comparator comparator) { 754 return valueProperties(propertyName, EqualTo.instance(comparator), otherPropertyName); 755 } 756 757 /** 758 * Apply a "greater than" constraint to two properties 759 * 760 * @param propertyName The first property 761 * @param otherPropertyName The other property 762 * @param comparator the comparator to use while comparing the values 763 * @return The constraint 764 * 765 * @since 0.3.0 766 */ 767 public PropertyConstraint gtProperty(String propertyName, String otherPropertyName, Comparator comparator) { 768 return valueProperties(propertyName, GreaterThan.instance(comparator), otherPropertyName); 769 } 770 771 /** 772 * Apply a "greater than or equal to" constraint to two properties. 773 * 774 * @param propertyName The first property 775 * @param otherPropertyName The other property 776 * @param comparator the comparator to use while comparing the values 777 * @return The constraint 778 * 779 * @since 0.3.0 780 */ 781 public PropertyConstraint gteProperty(String propertyName, String otherPropertyName, Comparator comparator) { 782 return valueProperties(propertyName, GreaterThanEqualTo.instance(comparator), otherPropertyName); 783 } 784 785 /** 786 * Apply a "less than" constraint to two properties. 787 * 788 * @param propertyName The first property 789 * @param otherPropertyName The other property 790 * @param comparator the comparator to use while comparing the values 791 * @return The constraint 792 * 793 * @since 0.3.0 794 */ 795 public PropertyConstraint ltProperty(String propertyName, String otherPropertyName, Comparator comparator) { 796 return valueProperties(propertyName, LessThan.instance(comparator), otherPropertyName); 797 } 798 799 /** 800 * Apply a "less than or equal to" constraint to two properties. 801 * 802 * @param propertyName The first property 803 * @param otherPropertyName The other property 804 * @param comparator the comparator to use while comparing the values 805 * @return The constraint 806 * 807 * @since 0.3.0 808 */ 809 public PropertyConstraint lteProperty(String propertyName, String otherPropertyName, Comparator comparator) { 810 return valueProperties(propertyName, LessThanEqualTo.instance(comparator), otherPropertyName); 811 } 812 813 /** 814 * Apply a inclusive "range" constraint to a bean property. 815 * 816 * @param propertyName the property with the range constraint. 817 * @param min the low edge of the range 818 * @param max the high edge of the range 819 * @param comparator the comparator to use while comparing the values 820 * @return The range constraint constraint 821 * 822 * @since 0.3.0 823 */ 824 public PropertyConstraint inRange(String propertyName, Object min, Object max, Comparator comparator) { 825 return value(propertyName, range(min, max, comparator)); 826 } 827 828 /** 829 * Apply a inclusive "range" constraint between two other properties to a 830 * bean property. 831 * 832 * @param propertyName the property with the range constraint. 833 * @param minPropertyName the low edge of the range 834 * @param maxPropertyName the high edge of the range 835 * @param comparator the comparator to use while comparing the values 836 * @return The range constraint constraint 837 * 838 * @since 0.3.0 839 */ 840 public PropertyConstraint inRangeProperties(String propertyName, String minPropertyName, String maxPropertyName, Comparator comparator) { 841 Constraint min = gteProperty(propertyName, minPropertyName, comparator); 842 Constraint max = lteProperty(propertyName, maxPropertyName, comparator); 843 return new CompoundPropertyConstraint(new And(min, max)); 844 } 845 846 /** 847 * Apply a "equal to" constraint to two bean properties. 848 * 849 * @param propertyName The first property 850 * @param otherPropertyName The other property 851 * @return The constraint 852 */ 853 public PropertyConstraint eqProperty(String propertyName, String otherPropertyName) { 854 return valueProperties(propertyName, EqualTo.instance(), otherPropertyName); 855 } 856 857 /** 858 * Apply a "greater than" constraint to two properties 859 * 860 * @param propertyName The first property 861 * @param otherPropertyName The other property 862 * @return The constraint 863 */ 864 public PropertyConstraint gtProperty(String propertyName, String otherPropertyName) { 865 return valueProperties(propertyName, GreaterThan.instance(), otherPropertyName); 866 } 867 868 /** 869 * Apply a "greater than or equal to" constraint to two properties. 870 * 871 * @param propertyName The first property 872 * @param otherPropertyName The other property 873 * @return The constraint 874 */ 875 public PropertyConstraint gteProperty(String propertyName, String otherPropertyName) { 876 return valueProperties(propertyName, GreaterThanEqualTo.instance(), otherPropertyName); 877 } 878 879 /** 880 * Apply a "less than" constraint to two properties. 881 * 882 * @param propertyName The first property 883 * @param otherPropertyName The other property 884 * @return The constraint 885 */ 886 public PropertyConstraint ltProperty(String propertyName, String otherPropertyName) { 887 return valueProperties(propertyName, LessThan.instance(), otherPropertyName); 888 } 889 890 /** 891 * Apply a "less than or equal to" constraint to two properties. 892 * 893 * @param propertyName The first property 894 * @param otherPropertyName The other property 895 * @return The constraint 896 */ 897 public PropertyConstraint lteProperty(String propertyName, String otherPropertyName) { 898 return valueProperties(propertyName, LessThanEqualTo.instance(), otherPropertyName); 899 } 900 901 /** 902 * Apply a inclusive "range" constraint to a bean property. 903 * 904 * @param propertyName the property with the range constraint. 905 * @param min the low edge of the range 906 * @param max the high edge of the range 907 * @return The range constraint constraint 908 */ 909 public PropertyConstraint inRange(String propertyName, Comparable min, Comparable max) { 910 return value(propertyName, range(min, max)); 911 } 912 913 /** 914 * Apply a inclusive "range" constraint between two other properties to a 915 * bean property. 916 * 917 * @param propertyName the property with the range constraint. 918 * @param minPropertyName the low edge of the range 919 * @param maxPropertyName the high edge of the range 920 * @return The range constraint constraint 921 */ 922 public PropertyConstraint inRangeProperties(String propertyName, String minPropertyName, String maxPropertyName) { 923 Constraint min = gteProperty(propertyName, minPropertyName); 924 Constraint max = lteProperty(propertyName, maxPropertyName); 925 return new CompoundPropertyConstraint(new And(min, max)); 926 } 927 928 /** 929 * Create a unique property value constraint that will test a collection of 930 * domain objects, returning true if all objects have unique values for the 931 * provided propertyName. 932 * @param propertyName The property name 933 * @return The constraint 934 */ 935 public PropertyConstraint unique(String propertyName) { 936 return new UniquePropertyValueConstraint(propertyName); 937 } 938 }