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
00157
00158
00159
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
00197
00198
00199
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 }