001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.validator;
018:
019: import java.io.Serializable;
020: import java.util.ArrayList;
021: import java.util.Collections;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.apache.commons.collections.FastHashMap;// DEPRECATED
027:
028: /**
029: * <p>
030: *
031: * This contains a set of validation rules for a form/JavaBean. The information
032: * is contained in a list of <code>Field</code> objects. Instances of this class
033: * are configured with a <form> xml element. </p> <p>
034: *
035: * The use of FastHashMap is deprecated and will be replaced in a future
036: * release. </p>
037: *
038: * @version $Revision: 478334 $ $Date: 2006-11-22 21:31:54 +0000 (Wed, 22 Nov 2006) $
039: */
040: public class Form implements Serializable {
041:
042: /** The name/key the set of validation rules is stored under. */
043: protected String name = null;
044:
045: /**
046: * List of <code>Field</code>s. Used to maintain the order they were added
047: * in although individual <code>Field</code>s can be retrieved using <code>Map</code>
048: * of <code>Field</code>s.
049: */
050: protected List lFields = new ArrayList();
051:
052: /**
053: * Map of <code>Field</code>s keyed on their property value.
054: *
055: * @deprecated Subclasses should use getFieldMap() instead.
056: */
057: protected FastHashMap hFields = new FastHashMap();
058:
059: /**
060: * The name/key of the form which this form extends from.
061: *
062: * @since Validator 1.2.0
063: */
064: protected String inherit = null;
065:
066: /**
067: * Whether or not the this <code>Form</code> was processed for replacing
068: * variables in strings with their values.
069: */
070: private boolean processed = false;
071:
072: /**
073: * Gets the name/key of the set of validation rules.
074: *
075: * @return The name value
076: */
077: public String getName() {
078: return name;
079: }
080:
081: /**
082: * Sets the name/key of the set of validation rules.
083: *
084: * @param name The new name value
085: */
086: public void setName(String name) {
087: this .name = name;
088: }
089:
090: /**
091: * Add a <code>Field</code> to the <code>Form</code>.
092: *
093: * @param f The field
094: */
095: public void addField(Field f) {
096: this .lFields.add(f);
097: this .hFields.put(f.getKey(), f);
098: }
099:
100: /**
101: * A <code>List</code> of <code>Field</code>s is returned as an unmodifiable
102: * <code>List</code>.
103: *
104: * @return The fields value
105: */
106: public List getFields() {
107: return Collections.unmodifiableList(lFields);
108: }
109:
110: /**
111: * Returns the Field with the given name or null if this Form has no such
112: * field.
113: *
114: * @param fieldName The field name
115: * @return The field value
116: * @since Validator 1.1
117: */
118: public Field getField(String fieldName) {
119: return (Field) this .hFields.get(fieldName);
120: }
121:
122: /**
123: * Returns true if this Form contains a Field with the given name.
124: *
125: * @param fieldName The field name
126: * @return True if this form contains the field by the given name
127: * @since Validator 1.1
128: */
129: public boolean containsField(String fieldName) {
130: return this .hFields.containsKey(fieldName);
131: }
132:
133: /**
134: * Merges the given form into this one. For any field in <code>depends</code>
135: * not present in this form, include it. <code>depends</code> has precedence
136: * in the way the fields are ordered.
137: *
138: * @param depends the form we want to merge
139: * @since Validator 1.2.0
140: */
141: protected void merge(Form depends) {
142:
143: List templFields = new ArrayList();
144: Map temphFields = new FastHashMap();
145: Iterator dependsIt = depends.getFields().iterator();
146: while (dependsIt.hasNext()) {
147: Field defaultField = (Field) dependsIt.next();
148: if (defaultField != null) {
149: String fieldKey = defaultField.getKey();
150: if (!this .containsField(fieldKey)) {
151: templFields.add(defaultField);
152: temphFields.put(fieldKey, defaultField);
153: } else {
154: Field old = getField(fieldKey);
155: hFields.remove(fieldKey);
156: lFields.remove(old);
157: templFields.add(old);
158: temphFields.put(fieldKey, old);
159: }
160: }
161: }
162: lFields.addAll(0, templFields);
163: hFields.putAll(temphFields);
164: }
165:
166: /**
167: * Processes all of the <code>Form</code>'s <code>Field</code>s.
168: *
169: * @param globalConstants A map of global constants
170: * @param constants Local constants
171: * @param forms Map of forms
172: * @since Validator 1.2.0
173: */
174: protected void process(Map globalConstants, Map constants, Map forms) {
175: if (isProcessed()) {
176: return;
177: }
178:
179: int n = 0;//we want the fields from its parent first
180: if (isExtending()) {
181: Form parent = (Form) forms.get(inherit);
182: if (parent != null) {
183: if (!parent.isProcessed()) {
184: //we want to go all the way up the tree
185: parent.process(constants, globalConstants, forms);
186: }
187: for (Iterator i = parent.getFields().iterator(); i
188: .hasNext();) {
189: Field f = (Field) i.next();
190: //we want to be able to override any fields we like
191: if (hFields.get(f.getKey()) == null) {
192: lFields.add(n, f);
193: hFields.put(f.getKey(), f);
194: n++;
195: }
196: }
197: }
198: }
199: hFields.setFast(true);
200: //no need to reprocess parent's fields, we iterate from 'n'
201: for (Iterator i = lFields.listIterator(n); i.hasNext();) {
202: Field f = (Field) i.next();
203: f.process(globalConstants, constants);
204: }
205:
206: processed = true;
207: }
208:
209: /**
210: * Returns a string representation of the object.
211: *
212: * @return string representation
213: */
214: public String toString() {
215: StringBuffer results = new StringBuffer();
216:
217: results.append("Form: ");
218: results.append(name);
219: results.append("\n");
220:
221: for (Iterator i = lFields.iterator(); i.hasNext();) {
222: results.append("\tField: \n");
223: results.append(i.next());
224: results.append("\n");
225: }
226:
227: return results.toString();
228: }
229:
230: /**
231: * Validate all Fields in this Form on the given page and below.
232: *
233: * @param params A Map of parameter class names to parameter
234: * values to pass into validation methods.
235: * @param actions A Map of validator names to ValidatorAction
236: * objects.
237: * @param page Fields on pages higher than this will not be
238: * validated.
239: * @return A ValidatorResults object containing all
240: * validation messages.
241: * @throws ValidatorException
242: */
243: ValidatorResults validate(Map params, Map actions, int page)
244: throws ValidatorException {
245: return validate(params, actions, page, null);
246: }
247:
248: /**
249: * Validate all Fields in this Form on the given page and below.
250: *
251: * @param params A Map of parameter class names to parameter
252: * values to pass into validation methods.
253: * @param actions A Map of validator names to ValidatorAction
254: * objects.
255: * @param page Fields on pages higher than this will not be
256: * validated.
257: * @return A ValidatorResults object containing all
258: * validation messages.
259: * @throws ValidatorException
260: * @since 1.2.0
261: */
262: ValidatorResults validate(Map params, Map actions, int page,
263: String fieldName) throws ValidatorException {
264:
265: ValidatorResults results = new ValidatorResults();
266: params.put(Validator.VALIDATOR_RESULTS_PARAM, results);
267:
268: // Only validate a single field if specified
269: if (fieldName != null) {
270: Field field = (Field) this .hFields.get(fieldName);
271:
272: if (field == null) {
273: throw new ValidatorException("Unknown field "
274: + fieldName + " in form " + getName());
275: }
276: params.put(Validator.FIELD_PARAM, field);
277:
278: if (field.getPage() <= page) {
279: results.merge(field.validate(params, actions));
280: }
281: } else {
282: Iterator fields = this .lFields.iterator();
283: while (fields.hasNext()) {
284: Field field = (Field) fields.next();
285:
286: params.put(Validator.FIELD_PARAM, field);
287:
288: if (field.getPage() <= page) {
289: results.merge(field.validate(params, actions));
290: }
291: }
292: }
293:
294: return results;
295: }
296:
297: /**
298: * Whether or not the this <code>Form</code> was processed for replacing
299: * variables in strings with their values.
300: *
301: * @return The processed value
302: * @since Validator 1.2.0
303: */
304: public boolean isProcessed() {
305: return processed;
306: }
307:
308: /**
309: * Gets the name/key of the parent set of validation rules.
310: *
311: * @return The extends value
312: * @since Validator 1.2.0
313: */
314: public String getExtends() {
315: return inherit;
316: }
317:
318: /**
319: * Sets the name/key of the parent set of validation rules.
320: *
321: * @param inherit The new extends value
322: * @since Validator 1.2.0
323: */
324: public void setExtends(String inherit) {
325: this .inherit = inherit;
326: }
327:
328: /**
329: * Get extends flag.
330: *
331: * @return The extending value
332: * @since Validator 1.2.0
333: */
334: public boolean isExtending() {
335: return inherit != null;
336: }
337:
338: /**
339: * Returns a Map of String field keys to Field objects.
340: *
341: * @return The fieldMap value
342: * @since Validator 1.2.0
343: */
344: protected Map getFieldMap() {
345: return hFields;
346: }
347: }
|