001 package org.springframework.rules.constraint.property; 002 003 import org.springframework.binding.PropertyAccessStrategy; 004 import org.springframework.rules.constraint.IfTrue; 005 import org.springframework.rules.reporting.TypeResolvable; 006 import org.springframework.util.Assert; 007 008 /** 009 * <p> 010 * Provides a way to trigger rules for propertyB when propertyA satisfies a 011 * certain condition: 012 * </p> 013 * 014 * <pre> 015 * if (propertyA satisfies the conditional constraint) 016 * { 017 * check the rules for propertyB 018 * } 019 * </pre> 020 * 021 * with an optional part: 022 * 023 * <pre> 024 * else 025 * { 026 * check the rules for propertyC 027 * } 028 * </pre> 029 * 030 * <p> 031 * More complex situations are possible by using compound constraints which 032 * leverages the previous to: 033 * </p> 034 * 035 * <pre> 036 * if (constraint(propertyA, propertyB,...) == true) 037 * { 038 * checkConstraint(property1, property2,...); 039 * } 040 * \\ optional part 041 * else 042 * { 043 * checkConstraint(propertyX, propertyY,...); 044 * } 045 * </pre> 046 * 047 * <p> 048 * This class can be compared to the {@link IfTrue} class: it applies the same 049 * pattern but on different <b>properties</b> instead of on a <b>property value</b>. 050 * </p> 051 * 052 * @author jh 053 * 054 */ 055 public class ConditionalPropertyConstraint extends AbstractPropertyConstraint implements TypeResolvable { 056 057 /** The condition which triggers further rules to be checked. */ 058 private final PropertyConstraint ifConstraint; 059 060 /** The constraint to be checked when the condition is satisfied. */ 061 private final PropertyConstraint thenConstraint; 062 063 /** The constraint to be checked when the condition is <b>NOT</b> satisfied. */ 064 private final PropertyConstraint elseConstraint; 065 066 /** Type used to fetch message. */ 067 private String type; 068 069 /** 070 * @see #ConditionalPropertyConstraint(PropertyConstraint, PropertyConstraint, String) 071 */ 072 public ConditionalPropertyConstraint(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint) { 073 this(ifConstraint, thenConstraint, null, null); 074 } 075 076 /** 077 * Create a constraint which simulates the if...then pattern applied 078 * on separate properties. 079 * 080 * @param ifConstraint the PropertyConstraint that triggers the test 081 * (satisfying a certain condition). 082 * @param thenConstraint the PropertyConstraint to test in the specified 083 * condition. 084 */ 085 public ConditionalPropertyConstraint(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, String type) { 086 this(ifConstraint, thenConstraint, null, type); 087 } 088 089 /** 090 * @see #ConditionalPropertyConstraint(PropertyConstraint, PropertyConstraint, PropertyConstraint, String) 091 */ 092 public ConditionalPropertyConstraint(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, 093 PropertyConstraint elseConstraint) { 094 this(ifConstraint, thenConstraint, elseConstraint, null); 095 } 096 /** 097 * Create a constraint which simulates the if...then...else pattern applied 098 * on separate properties. 099 * 100 * @param ifConstraint the PropertyConstraint that triggers the test 101 * (satisfying a certain condition). 102 * @param thenConstraint the PropertyConstraint to test in the specified 103 * condition. 104 * @param elseConstraint the PropertyConstraint to test if the condition is 105 * <b>NOT</b> satisfied. May be <code>null</code>. 106 * @param type the messageCode used to fetch the message. 107 */ 108 public ConditionalPropertyConstraint(PropertyConstraint ifConstraint, PropertyConstraint thenConstraint, 109 PropertyConstraint elseConstraint, String type) { 110 super(ifConstraint.getPropertyName()); 111 Assert.notNull(ifConstraint); 112 Assert.notNull(thenConstraint); 113 this.ifConstraint = ifConstraint; 114 this.thenConstraint = thenConstraint; 115 this.elseConstraint = elseConstraint; 116 this.type = type; 117 } 118 119 public boolean isCompoundRule() { 120 return true; 121 } 122 123 public boolean isDependentOn(String propertyName) { 124 if (elseConstraint == null) 125 return ifConstraint.isDependentOn(propertyName) || thenConstraint.isDependentOn(propertyName); 126 127 return ifConstraint.isDependentOn(propertyName) || thenConstraint.isDependentOn(propertyName) 128 || elseConstraint.isDependentOn(propertyName); 129 } 130 131 protected boolean test(PropertyAccessStrategy domainObjectAccessStrategy) { 132 if (ifConstraint.test(domainObjectAccessStrategy)) 133 return thenConstraint.test(domainObjectAccessStrategy); 134 if (elseConstraint != null) 135 return elseConstraint.test(domainObjectAccessStrategy); 136 137 return true; 138 } 139 140 public String getType() { 141 return type; 142 } 143 144 public void setType(String type) { 145 this.type = type; 146 } 147 }