Friday, February 28, 2003

onProject Creates Sarbanes-Oxley Act Compliance Software

My friends at onProject have created an application to help companies comply with the reporting and disclosure requirements of Section 404. I'm sure it's great and wish them the best of luck!
The Company where I was consulting closed their doors yesterday due to a combination of factors. Few, if any, were related to the application development work that was being done. I can recommend several of the staff so if you are looking for graphic designers, html writers, ColdFusion; Java; or Vitria developers let me know and I'll play matchmaker.

Thursday, February 06, 2003

Java; Struts Validator; How to Create Standard Field Definitions in the Validation XML Files

Hopefully, you read my last post about creating Field Groups. This post shows how to create a standard field defnitions that can reused over and over in form definitions. My field definitions look like this in my XML:
  <form name="FieldDefinitions">
    <field property="PROJECT_NAME" depends="required,alphanumeric,maxLength">
       <arg0 key="attributes.project_name.displayname"/>
       <var><var-name>maxLength</var-name><var-value>100</var-value></var>
       <var><var-name>allowSpaces</var-name><var-value>T</var-value></var>
    </field>
    <field property="PROJECT_DESCRIPTION" depends="alphanumeric">
       <arg0 key="attributes.project_description.displayname"/>
       <var><var-name>maxLength</var-name><var-value>1000</var-value></var>
       <var><var-name>allowSpaces</var-name><var-value>T</var-value></var>
    </field>
  </form>

  <form name="FormOne" >
    <field property="PROJECT_NAME" depends="required" fieldRef="PROJECT_NAME" />
  </form>
The result of my modification is that the depends attribute of the Field Definition is appended to the depends information of the PROJECT_NAME field. Additionally the arg0 element and var elements are copied to the PROJECT_NAME 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 not handled 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 fieldRef; with the appropriate getter and setter methods to the Field class.
  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));
          }
        }
    
        Form fieldDefinitions = resources.get(Locale.getDefault(), "FieldDefinitions");
        Map fieldDefinitionMap = fieldDefinitions.getFieldMap();
        
        // 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);
          // see if any fields refer to field definitions.
          List lFields = form.getFields();
          if (lFields == null) {
            System.out.println("No fields in form [" + formName + "].");
          } else {
            Iterator iFields = lFields.iterator();
            while (iFields.hasNext()) {
              Field field = (Field)iFields.next();
              String fieldRef = field.getFieldRef();
              if (fieldRef != null && fieldRef.length() > 0) {
                Field referencedField = (Field)fieldDefinitionMap.get(fieldRef);
                String referencedDepends = referencedField.getDepends();
                if (referencedDepends.length() > 0) {
                  String depends = field.getDepends();
                  if (depends != null && depends.length() > 0) {
                    field.setDepends(depends + "," + referencedDepends);
                  } else {
                    field.setDepends(referencedDepends);
                  }
                }
                field.addArg0(referencedField.getArg0());
                Map referencedFieldVars = referencedField.getVars();
                Iterator iReferencedFieldVars = referencedFieldVars.keySet().iterator();
                while (iReferencedFieldVars.hasNext()) {
                  String varName = (String)iReferencedFieldVars.next();
                  field.addVar(referencedField.getVar(varName));
                }
                //System.out.println(field);
              }
            }
          }
    
        }
    

Java; Struts Validator; How to Create Field Groups in the Validation XML Files

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);
    			}
    		}