Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

FormElement.java

00001 package edu.virtualschool.jwaa.xml;
00002 
00003 import java.lang.reflect.Constructor;
00004 import java.lang.reflect.InvocationTargetException;
00005 import java.util.Iterator;
00006 import java.util.List;
00007 
00008 import org.apache.log4j.Logger;
00009 import org.jdom.Attribute;
00010 import org.jdom.Element;
00011 import org.jdom.JDOMException;
00012 import org.jdom.Text;
00013 import org.jdom.xpath.XPath;
00014 
00015 import edu.virtualschool.jwaa.Fault;
00016 import edu.virtualschool.jwaa.GenericIdentifiable;
00017 
00024 public class FormElement extends GenericIdentifiable
00025 {
00026   final PageElement page;
00027   final String bodyText;
00028   final String logicText;
00029   final Constructor constructor;
00030     
00031   final static Class[] constructorTypes = new Class[] { Controller.class };
00032   final static Logger logger = Logger.getLogger(FormElement.class.getName());
00033   final static Outputter outputter = new Outputter(false);
00034   
00035   FormElement(PageElement page, Element element) 
00036     throws ValidationFault, IOFault
00037   {
00038     super(element.getAttributeValue("id"));
00039     this.page = page;
00040     Attribute typeAttr = element.getAttribute("type");
00041     String className = DefaultForm.class.getName();
00042     if (typeAttr != null)
00043     {
00044       className = typeAttr.getValue();
00045       typeAttr.detach();
00046     }
00047     try
00048     {
00049       Class c = Class.forName(className);
00050       if (!GenericForm.class.isAssignableFrom(c))
00051         throw new ValidationFault(className+" is not a GenericForm");
00052       this.constructor = c.getConstructor(constructorTypes);
00053     }
00054     catch (ClassNotFoundException e)
00055     {
00056       throw new ValidationFault("class " + className + " not found");
00057     }
00058     catch (SecurityException e)
00059     {
00060       throw new ValidationFault("Security exception creating " + className);
00061     }
00062     catch (IllegalArgumentException e)
00063     {
00064       throw new ValidationFault(
00065         "Illegal argument exception creating " + className);
00066     }
00067     catch (NoSuchMethodException e)
00068     {
00069       throw new ValidationFault("Constructor " + className+"(Controller) not found");
00070     }
00071     
00072     Element logicElement = element.getChild("logic", element.getNamespace());
00073     if (logicElement == null)
00074     {
00075       this.logicText = "#defaultLogic()";
00076     }
00077     else
00078     {
00079       List list = logicElement.getContent();
00080       this.logicText = outputter.output(list);
00081       logicElement.detach();
00082     }
00083     try
00084     {
00085       rewriteTextAndPasswordFields(element);
00086       rewriteTickFields(element);
00087       rewriteSelectFields(element);
00088       rewriteTextAreaFields(element);
00089     }
00090     catch (JDOMException e)
00091     {
00092       throw new ValidationFault("JDOM exception", e);
00093     }
00094     if (element.getAttributeValue("action") == null)
00095       element.setAttribute("action", page.getLink().toString());
00096     if (element.getAttributeValue("method") == null)
00097       element.setAttribute("method", "post");
00098     if (element.getAttributeValue("enctype") == null)
00099       element.setAttribute("enctype", "application/x-www-form-urlencoded");
00100     element.removeAttribute("id");
00101     this.bodyText = outputter.output(element);
00102   }
00103   private static XPath textPath = null;
00104   void rewriteTextAndPasswordFields(Element element)
00105     throws JDOMException, ValidationFault
00106   {
00107     if (textPath == null)
00108       textPath = XPath.newInstance(".//input[@type=\"text\"]|.//input[@type=\"password\"]|.//input[not(@type)]");
00109     List list = textPath.selectNodes(element);
00110     for (Iterator iterator = list.iterator(); iterator.hasNext(); )
00111     {
00112       Object o = iterator.next();
00113       Element e = (Element)o;
00114       String n = e.getName();
00115       String nameAttr = e.getAttributeValue("name");
00116       String valueAttr = e.getAttributeValue("value");
00117       if (nameAttr == null)
00118         throw new ValidationFault(n+" element requres a name attribute");
00119       if (valueAttr != null)
00120         continue;
00121       e.setAttribute("value", "$!form.getValue('"+nameAttr+"')");
00122     }
00123   }
00124   private static XPath inputPath = null;
00125   void rewriteTickFields(Element element) 
00126     throws JDOMException, ValidationFault
00127   {
00128     if (inputPath == null)
00129       inputPath = XPath.newInstance(".//input[@type=\"radio\"]|.//input[@type=\"checkbox\"]");
00130     for (Iterator inputItr = inputPath.selectNodes(element).iterator(); inputItr.hasNext(); )
00131     {
00132       Object inputObj = inputItr.next();
00133       Element inputElement = (Element)inputObj;
00134       String inputElementName = inputElement.getName();
00135 
00136       String valueAttr = inputElement.getAttributeValue("value");
00137       String nameAttr = inputElement.getAttributeValue("name");
00138       String checkedAttr = inputElement.getAttributeValue("checked");
00139 
00140       if (nameAttr == null)
00141         throw new ValidationFault(inputElementName+" element requres a name attribute");
00142       if (checkedAttr != null)
00143         continue;
00144       
00145       StringBuffer buf = new StringBuffer();
00146       for (Iterator attrItr = inputElement.getAttributes().iterator(); attrItr.hasNext(); )
00147       {
00148         Attribute attr = (Attribute)attrItr.next();
00149         buf.append(attr.getName()+"=\""+attr.getValue()+"\" ");
00150         attrItr.remove();
00151       }
00152       Text t = new Text("#rewriteTickField('"+nameAttr+"' '"+valueAttr+"' '"+buf+"')");
00153       Element parent = (Element)inputElement.getParent();
00154       int index = parent.indexOf(inputElement);
00155       parent.setContent(index, t);
00156 //      inputElement.setName("span");
00157 //      List list = new ArrayList();
00158 //      list.add(t);
00159 //      inputElement.setContent(list);
00160     }
00161   }
00162   private static XPath selectPath = null;
00163   private static XPath optionsPath = null;
00164   void rewriteSelectFields(Element element) 
00165     throws JDOMException, ValidationFault
00166   {
00167     if (selectPath == null)
00168       selectPath = XPath.newInstance(".//select");
00169     if (optionsPath == null)
00170       optionsPath = XPath.newInstance("./option");
00171     for (Iterator selectItr = selectPath.selectNodes(element).iterator(); selectItr.hasNext(); )
00172     {
00173       Object selectObj = selectItr.next();
00174       Element selectElement = (Element)selectObj;
00175       String selectElementName = selectElement.getName();
00176       String selectNameAttr = selectElement.getAttributeValue("name");
00177       if (selectNameAttr == null)
00178         throw new ValidationFault(selectElementName+" element requres a name attribute");
00179       List optionsList = optionsPath.selectNodes(selectElement);
00180       for (Iterator optionsIterator = optionsList.iterator(); optionsIterator.hasNext(); )
00181       {
00182         Object optionObject = optionsIterator.next();
00183         Element optionElement = (Element)optionObject;
00184         StringBuffer buf = new StringBuffer();
00185         for (Iterator attrIterator = optionElement.getAttributes().iterator(); attrIterator.hasNext(); )
00186         {
00187           Attribute attr = (Attribute)attrIterator.next();
00188           buf.append("'"+attr.getName()+"=\""+attr.getValue()+"\"'");
00189           attrIterator.remove();
00190         }
00191         String optionValue = optionElement.getText();
00192         Text t = new Text("#rewriteSelectField('"+selectNameAttr+"' '"+optionValue+"' '"+buf+"')");
00193         Element parent = (Element)optionElement.getParent();
00194         int index = parent.indexOf(optionElement);
00195         parent.setContent(index, t);
00196 //        optionElement.setName("span");
00197 //        List list = new ArrayList();
00198 //        list.add(t);
00199 //        optionElement.setContent(list);
00200       }
00201     }
00202   }
00203   private static XPath textAreaPath = null;
00204   void rewriteTextAreaFields(Element element) 
00205     throws JDOMException, ValidationFault
00206   {
00207     if (textAreaPath == null)
00208       textAreaPath = XPath.newInstance(".//textarea");
00209     for (Iterator i = textAreaPath.selectNodes(element).iterator(); i.hasNext(); )
00210     {
00211       Object o = i.next();
00212       Element e = (Element)o;
00213       String n = e.getName();
00214       String nameAttr = e.getAttributeValue("name");
00215       if (nameAttr == null)
00216         throw new ValidationFault(n+" element requres a name attribute");
00217       String text = e.getText();
00218       e.setText("$!form.getValue('"+nameAttr+"')");
00219     }
00220   }
00221   public final PageElement getPage()
00222   {
00223     return page;
00224   }
00225   public final String getText()
00226   {
00227     return logicText+bodyText;
00228   }
00229   GenericForm getFormInstance(Controller page) throws Fault
00230   {
00231     Object[] argValues = new Object[] { page };
00232     try
00233     {
00234       Object instance = constructor.newInstance(argValues);
00235       if (instance instanceof GenericForm)
00236         return (GenericForm)instance;
00237       else
00238         throw new ValidationFault("Form type must be GenericForm");
00239     }
00240     catch (IllegalArgumentException e)
00241     {
00242       throw new Fault(e, e);
00243     }
00244     catch (InstantiationException e)
00245     {
00246       throw new Fault(e, e);
00247     }
00248     catch (IllegalAccessException e)
00249     {
00250       throw new Fault(e, e);
00251     }
00252     catch (InvocationTargetException e)
00253     {
00254       throw new Fault(e, e);
00255     }
00256   }
00257 }