001 package org.apache.fulcrum.intake.validator;
002
003 /*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements. See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership. The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License. You may obtain a copy of the License at
011 *
012 * http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied. See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022 import java.util.Iterator;
023 import java.util.List;
024
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.apache.fulcrum.intake.IntakeException;
028 import org.apache.fulcrum.intake.model.Field;
029 import org.apache.fulcrum.intake.model.Group;
030
031 /**
032 * Helper Class to manage relations between fields. The following
033 * comparisons are supported:
034 *
035 * <table>
036 * <tr>
037 * <th>Name</th><th>Valid Values</th><th>Default Value</th>
038 * </tr>
039 * <tr>
040 * <td>less-than</td>
041 * <td><name of other field></td>
042 * <td> </td>
043 * </tr>
044 * <tr>
045 * <td>greater-than</td>
046 * <td><name of other field></td>
047 * <td> </td>
048 * </tr>
049 * <tr>
050 * <td>less-than-or-equal</td>
051 * <td><name of other field></td>
052 * <td> </td>
053 * </tr>
054 * <tr>
055 * <td>greater-than-or-equal</td>
056 * <td><name of other field></td>
057 * <td> </td>
058 * </tr>
059 * </table>
060 *
061 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
062 * @version $Id: DateStringValidator.java 534527 2007-05-02 16:10:59Z tv $
063 */
064 public class FieldReference
065 {
066 /** a local logger */
067 protected static final Log log = LogFactory.getLog(FieldReference.class);
068
069 /** Rule name for "<" comparison */
070 public static final String RANGE_LT = "less-than";
071
072 /** Rule name for ">" comparison */
073 public static final String RANGE_GT = "greater-than";
074
075 /** Rule name for "<=" comparison */
076 public static final String RANGE_LTE = "less-than-or-equal";
077
078 /** Rule name for ">=" comparison */
079 public static final String RANGE_GTE = "greater-than-or-equal";
080
081 /** Integer value for "<" comparison */
082 public static final int COMPARE_LT = 1;
083
084 /** Integer value for ">" comparison */
085 public static final int COMPARE_GT = 2;
086
087 /** Integer value for "<=" comparison */
088 public static final int COMPARE_LTE = 3;
089
090 /** Integer value for ">=" comparison */
091 public static final int COMPARE_GTE = 4;
092
093 /** Numeric comparison */
094 private int compare = 0;
095
096 /** Name of referenced field */
097 private String fieldName = null;
098
099 /** Error message */
100 private String message = null;
101
102 /**
103 * Constructor
104 */
105 public FieldReference()
106 {
107 // do nothing
108 }
109
110 /**
111 * @return the comparison type
112 */
113 public int getCompare()
114 {
115 return compare;
116 }
117
118 /**
119 * @param compare the comparison type to set
120 */
121 public void setCompare(int compare)
122 {
123 this.compare = compare;
124 }
125
126 /**
127 * @return the field name
128 */
129 public String getFieldName()
130 {
131 return fieldName;
132 }
133
134 /**
135 * @param fieldName the field name to set
136 */
137 public void setFieldName(String fieldName)
138 {
139 this.fieldName = fieldName;
140 }
141
142 /**
143 * @return the message
144 */
145 public String getMessage()
146 {
147 return message;
148 }
149
150 /**
151 * @param message the message to set
152 */
153 public void setMessage(String message)
154 {
155 this.message = message;
156 }
157
158 /**
159 * Map the comparison strings to their numeric counterparts
160 *
161 * @param key the string representation of a comparison operator
162 * @return the numeric representation of the given comparison operator
163 */
164 public static int getCompareType(String key)
165 {
166 int compareType = 0;
167
168 if (key.equals(RANGE_LT))
169 {
170 compareType = COMPARE_LT;
171 }
172 else if (key.equals(RANGE_LTE))
173 {
174 compareType = COMPARE_LTE;
175 }
176 else if (key.equals(RANGE_GT))
177 {
178 compareType = COMPARE_GT;
179 }
180 else if (key.equals(RANGE_GTE))
181 {
182 compareType = COMPARE_GTE;
183 }
184
185 return compareType;
186 }
187
188 /**
189 * Check the parsed value against the referenced fields
190 *
191 * @param fieldReferences List of field references to check
192 * @param compareCallback Callback to the actual compare operation
193 * @param value the parsed value of the related field
194 * @param group the group the related field belongs to
195 *
196 * @throws ValidationException
197 */
198 public static void checkReferences(List fieldReferences, CompareCallback compareCallback,
199 Object value, Group group)
200 throws ValidationException
201 {
202 for (Iterator i = fieldReferences.iterator(); i.hasNext();)
203 {
204 FieldReference ref = (FieldReference)i.next();
205 boolean comp_true = true;
206
207 try
208 {
209 Field refField = group.get(ref.getFieldName());
210
211 if (refField.isSet())
212 {
213 /*
214 * Fields are processed in sequence so that our
215 * reference field might have been set but not
216 * yet validated. We check this here.
217 */
218 if (!refField.isValidated())
219 {
220 refField.validate();
221 }
222
223 if (refField.isValid())
224 {
225 try
226 {
227 comp_true = compareCallback.compareValues(ref.getCompare(),
228 value,
229 refField.getValue());
230 }
231 catch (ClassCastException e)
232 {
233 throw new IntakeException("Type mismatch comparing " +
234 value + " with " + refField.getValue(), e);
235 }
236 }
237 }
238 }
239 catch (IntakeException e)
240 {
241 log.error("Validate operation failed.", e);
242 throw new ValidationException(ref.getMessage());
243 }
244
245 if (comp_true == false)
246 {
247 throw new ValidationException(ref.getMessage());
248 }
249 }
250 }
251 }