We’ve been using a slightly modified version o the Struts Validator on my project. And we’ve found that it was neccessary to repeat the field definitions over and over again. Since we have (or will have) several hundred forms I needed a way to reduce the amount of repetition.

I took a low-tech approach that only needed a few lines of code to implement by adding a formRefList attribute to the form tag. So my XML file might look like this:

  <form name="FieldGroupOne">
    <field property="STATUS />
    <field property="NAME" depends="alphanumeric,maxLength" />
  </form>

  <form name="FormOne" formRefList="FieldGroupOne">
    <field property="NAME" depends="required" />
  </form>

The result of my modfication is that the FormOne form has two identically-named fields both of which are evaluated when it comes time to validate the field.
The following description of how I implemented my change assumed that you already know how to compile the Validator project. Also note that errors are simply handled by printing to STDOUT because I use a JUnit test that is run during an automated build and regression test to ensure that the XML files are correct. So the error checking code should never be implemented.

  1. Add public FastHashMap getHForms() { return hForms; } to the FormSet class.
  2. Add protected String formRefList; with the appropriate getter and setter methods.
  3. After the XML files are processed, run the following code:
    		// The Formsets are stored under Locale keys. Store
    		// the form object into a hashmap for later processing.
    		Iterator iFormSets = ((Vector)resources.getValidatorFormSet().get("en_US")).iterator();
    		while (iFormSets.hasNext()) {
    			FormSet fs = ((FormSet)iFormSets.next());
    			Iterator iForms = fs.getHForms().keySet().iterator();
    			while (iForms.hasNext()) {
    				String formName = (String)iForms.next();
    				formObjects.put(formName, fs.getHForms().get(formName));
    			}
    		}
    
    		// Now iterate over the forms looking for formRefList
    		// attributes.
    		Iterator iForms = formObjects.keySet().iterator();
    		while (iForms.hasNext()) {
    			String formName = (String)iForms.next();
    			Form form = (Form)formObjects.get(formName);
    			String formRefList = form.getFormRefList();
    			if (formRefList != null && formRefList.length() > 0) {
    				//System.out.println("Before processing " + form);
    				StringTokenizer st = new StringTokenizer(formRefList);
    				while (st.hasMoreTokens()) {
    					String referencedFormName = st.nextToken();
    					Form referencedForm = (Form)formObjects.get(referencedFormName);
    					if (referencedForm == null) {
    						System.out.println("No object for referenced form [" + referencedFormName + "].");
    					} else {
    						List lReferencedFields = referencedForm.getFields();
    						if (lReferencedFields == null) {
    							System.out.println("No fields in referenced form [" + referencedFormName + "].");
    						} else {
    							Iterator iReferencedFields = lReferencedFields.iterator();
    							while (iReferencedFields.hasNext()) {
    								Field referencedField = (Field)iReferencedFields.next();
    								form.addField(referencedField);
    							}
    						}
    					}
    				}
    				//System.out.println("After processing Form " + form);
    			}
    		}
    
  4. </ol>