1 package org.apache.fulcrum.intake.validator;
2
3 /*
4 * Licensed to the Apache Software Foundation (ASF) under one
5 * or more contributor license agreements. See the NOTICE file
6 * distributed with this work for additional information
7 * regarding copyright ownership. The ASF licenses this file
8 * to you under the Apache License, Version 2.0 (the
9 * "License"); you may not use this file except in compliance
10 * with the License. You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing,
15 * software distributed under the License is distributed on an
16 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 * KIND, either express or implied. See the License for the
18 * specific language governing permissions and limitations
19 * under the License.
20 */
21
22 import java.util.List;
23
24 import org.apache.fulcrum.intake.IntakeException;
25 import org.apache.fulcrum.intake.model.Field;
26 import org.apache.fulcrum.intake.model.Group;
27
28 /**
29 * Helper Class to manage relations between fields. The following
30 * comparisons are supported:
31 *
32 * <table>
33 * <caption>Validation rules</caption>
34 * <tr>
35 * <th>Name</th><th>Valid Values</th><th>Default Value</th>
36 * </tr>
37 * <tr>
38 * <td>less-than</td>
39 * <td><name of other field></td>
40 * <td> </td>
41 * </tr>
42 * <tr>
43 * <td>greater-than</td>
44 * <td><name of other field></td>
45 * <td> </td>
46 * </tr>
47 * <tr>
48 * <td>less-than-or-equal</td>
49 * <td><name of other field></td>
50 * <td> </td>
51 * </tr>
52 * <tr>
53 * <td>greater-than-or-equal</td>
54 * <td><name of other field></td>
55 * <td> </td>
56 * </tr>
57 * </table>
58 *
59 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
60 * @version $Id$
61 */
62 public class FieldReference
63 {
64 public static enum Comparison
65 {
66 /** Rule for "<" comparison */
67 LT ("less-than"),
68
69 /** Rule for ">" comparison */
70 GT ("greater-than"),
71
72 /** Rule for "<=" comparison */
73 LTE ("less-than-or-equal"),
74
75 /** Rule for ">=" comparison */
76 GTE ("greater-than-or-equal");
77
78 private final String text;
79
80 private Comparison(String text)
81 {
82 this.text = text;
83 }
84
85 @Override
86 public String toString()
87 {
88 return text;
89 }
90
91 public static Comparison fromString(String string)
92 {
93 if (string != null)
94 {
95 for (Comparison c : Comparison.values())
96 {
97 if (string.equals(c.text))
98 {
99 return c;
100 }
101 }
102 }
103
104 return null;
105 }
106 }
107
108 /** Numeric comparison */
109 private Comparison compare = null;
110
111 /** Name of referenced field */
112 private String fieldName = null;
113
114 /** Error message */
115 private String message = null;
116
117 /**
118 * Constructor
119 */
120 public FieldReference()
121 {
122 // do nothing
123 }
124
125 /**
126 * @return the comparison type
127 */
128 public Comparison getComparison()
129 {
130 return compare;
131 }
132
133 /**
134 * @param compare the comparison type to set
135 */
136 public void setComparison(Comparison compare)
137 {
138 this.compare = compare;
139 }
140
141 /**
142 * @return the field name
143 */
144 public String getFieldName()
145 {
146 return fieldName;
147 }
148
149 /**
150 * @param fieldName the field name to set
151 */
152 public void setFieldName(String fieldName)
153 {
154 this.fieldName = fieldName;
155 }
156
157 /**
158 * @return the message
159 */
160 public String getMessage()
161 {
162 return message;
163 }
164
165 /**
166 * @param message the message to set
167 */
168 public void setMessage(String message)
169 {
170 this.message = message;
171 }
172
173 /**
174 * Map the comparison strings to their numeric counterparts
175 *
176 * @param key the string representation of a comparison operator
177 * @return the numeric representation of the given comparison operator
178 */
179 public static Comparison getComparisonType(String key)
180 {
181 return Comparison.fromString(key);
182 }
183
184 /**
185 * Check the parsed value against the referenced fields
186 *
187 * @param fieldReferences List of field references to check
188 * @param compareCallback Callback to the actual compare operation
189 * @param value the parsed value of the related field
190 * @param group the group the related field belongs to
191 *
192 * @param <T> the field type
193 *
194 * @throws ValidationException if the validation against at least one related field fails
195 */
196 public static <T> void checkReferences(List<FieldReference> fieldReferences, CompareCallback<T> compareCallback,
197 T value, Group group)
198 throws ValidationException
199 {
200 for (FieldReference ref : fieldReferences)
201 {
202 boolean comp_true = true;
203
204 try
205 {
206 @SuppressWarnings("unchecked")
207 Field<T> refField = (Field<T>) group.get(ref.getFieldName());
208
209 if (refField.isSet())
210 {
211 /*
212 * Fields are processed in sequence so that our
213 * reference field might have been set but not
214 * yet validated. We check this here.
215 */
216 if (!refField.isValidated())
217 {
218 refField.validate();
219 }
220
221 if (refField.isValid())
222 {
223 comp_true = compareCallback.compareValues(ref.getComparison(),
224 value,
225 refField.getValue());
226 }
227 }
228 }
229 catch (IntakeException e)
230 {
231 throw new ValidationException(ref.getMessage());
232 }
233
234 if (comp_true == false)
235 {
236 throw new ValidationException(ref.getMessage());
237 }
238 }
239 }
240 }