Coverage Report - net.sf.jolene.dom.Form
 
Classes in this File Line Coverage Branch Coverage Complexity
Form
92%
104/113
88%
53/60
0
Form$1
100%
1/1
N/A
0
 
 1  
 package net.sf.jolene.dom;
 2  
 
 3  
 import net.sf.jolene.constants.Elements;
 4  
 import net.sf.jolene.constants.Tags;
 5  
 import net.sf.jolene.html.Attributes;
 6  
 import org.apache.commons.beanutils.BeanUtils;
 7  
 
 8  
 import java.util.*;
 9  
 
 10  
 /**
 11  
  * A form in a html document. This acts as a container for other html objects.
 12  
  *
 13  
  * @author Dan Howard
 14  
  * @since Oct 21, 2003
 15  
  */
 16  0
 public final class Form extends HTMLElement {
 17  
 
 18  
     List<HTMLElement> elements;
 19  
 
 20  43
     Form() {
 21  43
         tag = Tags.form;
 22  43
         elements = new ArrayList<HTMLElement>(16);
 23  43
     }
 24  
 
 25  
 
 26  
     @Override
 27  
     public Form clone() {
 28  1
         Form form = (Form) super.clone();
 29  13
         for (int j = 0; j < elements.size(); j++) {
 30  12
             HTMLElement element = elements(j).clone();
 31  12
             form.addElement(element);
 32  
         }
 33  1
         return form;
 34  
     }
 35  
 
 36  
 
 37  
     /**
 38  
      * This method returns the widget specified by the numeric index.
 39  
      * The prefered way of retrieving an object from the form is to
 40  
      * use it's name or id instead since the order of the objects can be
 41  
      * changed easily by a page designer.
 42  
      *
 43  
      * @param element - The integer element number of the object desired.
 44  
      * @return HTMLElement
 45  
      */
 46  
     public HTMLElement elements(int element) {
 47  1310
         return elements.get(element);
 48  
     }
 49  
 
 50  
     /**
 51  
      * This method retrieves an object from the document by name or id.
 52  
      * When the document is opened it creates objects by looking at the ID
 53  
      * attribute first. If that attribute doesn't exist it uses the NAME
 54  
      * attribute. If neither exist then the only way to address these
 55  
      * objects is by number (not recommended).<br>
 56  
      * This method returns the base HTMLElement object so if you want a Select or
 57  
      * Grid object you can either cast it:
 58  
      * <pre>
 59  
      * Grid grid grid = (Grid)document.forms(0).elements("Grid1");
 60  
      * </pre>
 61  
      * or use the appropriate getter:
 62  
      * <pre>
 63  
      * Grid grid = document.forms(0).getGrid("Grid1");
 64  
      * </pre>
 65  
      *
 66  
      * @param elementName - The string name or id of the object desired.
 67  
      * @return HTMLElement or null if not found or elementName is null.
 68  
      */
 69  
     public HTMLElement elements(String elementName) {
 70  
 
 71  100
         if (elementName == null) {
 72  0
             return null;
 73  
         }
 74  
 
 75  
         // locate the object whose name == this string.
 76  100
         String name = "";
 77  
         HTMLElement element;
 78  
         int j;
 79  
 
 80  603
         for (j = 0; j < elements.size(); j++) {
 81  
 
 82  597
             if (elementName.equalsIgnoreCase(elements.get(j).getName())) {
 83  94
                 break;
 84  
             }
 85  
 /*
 86  
             if (element.hasAttribute("id")) {
 87  
                 name = element.getAttribute("id");
 88  
                 if (name.equalsIgnoreCase(elementName)) {
 89  
                     break; // found it.
 90  
                 }
 91  
             } else if (element.hasAttribute("name")) {
 92  
                 name = (String) element.getAttribute("name");
 93  
                 if (name.equalsIgnoreCase(elementName)) {
 94  
                     break; // found it.
 95  
                 }
 96  
             } else {
 97  
                 // We have to throw an exception here? We have an object with no NAME!!!!!
 98  
 
 99  
             }
 100  
 */
 101  
 
 102  
         }
 103  
 
 104  100
         if (j < elements.size()) {
 105  94
             return elements(j);
 106  
         } else {
 107  
             // THROW EXCEPTION
 108  
             // Based on the HashMap, no exception is thrown but a null is returned which
 109  
             // will cause a null pointer exception later.
 110  6
             return null;
 111  
         }
 112  
     }
 113  
 
 114  
 
 115  
     /**
 116  
      * @return Number of elements in the form.
 117  
      */
 118  
     public int getElementCount() {
 119  17
         return elements.size();
 120  
     }
 121  
 
 122  
     /**
 123  
      * Returns the specified element casted to a Grid object.
 124  
      *
 125  
      * @param name name of grid
 126  
      * @return Grid
 127  
      */
 128  
     public Grid getGrid(String name) {
 129  0
         return (Grid) elements(name);
 130  
     }
 131  
 
 132  
     /**
 133  
      * Returns a Map of Radio objects based the specified radio group name.
 134  
      * The map's order is insertion-order.
 135  
      *
 136  
      * @param groupName of radios
 137  
      * @return Map<String, HTMLElement>
 138  
      */
 139  
     public Map<String, HTMLElement> getRadioGroup(String groupName) {
 140  2
         Map<String, HTMLElement> map = new LinkedHashMap<String, HTMLElement>(3);
 141  
         // loop through the objects for radios with the specified name
 142  
         // and add each to a hashmap based on their VALUE attribute.
 143  
         // If no value exists, log a warn and add each with an integer as
 144  
         // the key.
 145  32
         for (int j = 0; j < elements.size(); j++) {
 146  30
             HTMLElement element = elements.get(j);
 147  30
             if (element instanceof Radio) {
 148  6
                 if (groupName.equalsIgnoreCase(element.getName())) {
 149  6
                     log.debug("Radio " + groupName + " found.");
 150  
                     String key;
 151  6
                     if (element.hasAttribute("value")) {
 152  6
                         key = element.getAttribute("value");
 153  6
                         log.debug("Radio " + groupName + " key " + key);
 154  
                     } else {
 155  0
                         key = String.valueOf(j);
 156  0
                         log.debug("getRadioGroup: Radio has no value: " + element + " assigning " + key);
 157  
                     }
 158  6
                     map.put(key, element);
 159  
                 }
 160  
             }
 161  
         }
 162  2
         return map;
 163  
     }
 164  
 
 165  
     /**
 166  
      * Returns the specified element casted to a Select object.
 167  
      *
 168  
      * @param name name of select
 169  
      * @return Select
 170  
      */
 171  
     public Select getSelect(String name) {
 172  4
         return (Select) elements(name);
 173  
     }
 174  
 
 175  
     /**
 176  
      * Checks if the specified object exists in the form.
 177  
      *
 178  
      * @param name name to check
 179  
      * @return boolean
 180  
      */
 181  
     public boolean hasElement(String name) {
 182  10
         return elements(name) != null;
 183  
     }
 184  
 
 185  
 /*
 186  
     public Label getLabel(String name) {
 187  
         return (Label) elements(name);
 188  
     }
 189  
 
 190  
     public Button getButton(String name) {
 191  
         return (Button) elements(name);
 192  
     }
 193  
 */
 194  
 
 195  
     /**
 196  
      * Poplates the form objects based on the supplied java bean.
 197  
      *
 198  
      * @param bean any object which can be examined by BeanUtils.
 199  
      * @throws FormPolulateException if BeanUtils fails.
 200  
      */
 201  
     public void populate(Object bean) throws FormPolulateException {
 202  
 
 203  1
         Map<String, String> map = null;
 204  
         //@todo should this support nested properties like the grid?
 205  
         try {
 206  1
             map = BeanUtils.describe(bean);
 207  0
         } catch (Exception e) {
 208  0
             throw new FormPolulateException(e);
 209  1
         }
 210  1
         populate(map);
 211  1
     }
 212  
 
 213  
     /**
 214  
      * Populates the form object from the supplied map object.
 215  
      *
 216  
      * @param map - name/values where names match element names
 217  
      */
 218  
     public void populate(Map<String, String> map) {
 219  1
         Map<String, String> radios = new HashMap<String, String>(3);
 220  
 
 221  1
         Iterator it = map.keySet().iterator();
 222  11
         while (it.hasNext()) {
 223  10
             String key = (String) it.next();
 224  
 
 225  
             // Prevent null values in the bean from throwing null pointer
 226  
             String value;
 227  10
             if (map.get(key) == null) {
 228  0
                 value = "";
 229  
             } else {
 230  10
                 value = (String) map.get(key);
 231  
             }
 232  
 
 233  10
             if (hasElement(key.toString())) {
 234  
                 // Do not auto populate Radios since we don't really
 235  
                 // know which radio to assign the value to since usually
 236  
                 // they would have the same name. See getRadioGroup() method.
 237  9
                 if (elements(key) instanceof Radio) {
 238  1
                     radios.put(key, "");
 239  
                 } else {
 240  8
                     if (elements(key) instanceof CheckBox) {
 241  1
                         if (value.equalsIgnoreCase("true")) {
 242  1
                             elements(key).setChecked(true);
 243  
                         } else {
 244  0
                             elements(key).setChecked(false);
 245  
                         }
 246  
                     } else {
 247  7
                         elements(key).setValue(value);
 248  
                     }
 249  
                 }
 250  
             }
 251  10
         }
 252  
 
 253  
         /*
 254  
         Check radios. If there are any radios that matched a field in the bean
 255  
         then it means that maybe that fields value matches a radio value from the
 256  
         group.  For each group check if the values match and set the CHECKED for
 257  
         the ones that do.
 258  
         */
 259  1
         it = radios.keySet().iterator();
 260  2
         while (it.hasNext()) {
 261  
             String key;
 262  1
             key = it.next().toString();
 263  
 
 264  
             Iterator<HTMLElement> itGroup;
 265  1
             itGroup = getRadioGroup(key).values().iterator();
 266  4
             while (itGroup.hasNext()) {
 267  3
                 HTMLElement radio = itGroup.next();
 268  3
                 radio.setChecked(false);
 269  3
                 if (radio.getValue() != null && map.get(key) != null) {
 270  3
                     if (radio.getValue().equalsIgnoreCase(map.get(key).toString())) {
 271  1
                         radio.setChecked(true);
 272  
                     }
 273  
                 }
 274  3
             }
 275  1
         }
 276  
 
 277  1
     }
 278  
 
 279  
     final HTMLElement addObject(Elements type, Attributes attributes, int start, int end) {
 280  
 
 281  
         HTMLElement element;
 282  
 
 283  309
         log.debug("TYPE:" + type);
 284  
 
 285  1
         switch (type) {
 286  
 
 287  
             case select:
 288  30
                 element = new Select();
 289  30
                 break;
 290  
 
 291  
             case textarea:
 292  7
                 element = new TextArea();
 293  7
                 break;
 294  
 
 295  
             case label:
 296  15
                 element = new Label();
 297  15
                 break;
 298  
 
 299  
             case button:
 300  4
                 element = new Button();
 301  4
                 break;
 302  
 
 303  
             case image:
 304  78
                 element = new Image();
 305  78
                 break;
 306  
 
 307  
             case grid:
 308  11
                 element = new Grid();
 309  11
                 break;
 310  
 
 311  
             case radio:
 312  18
                 element = new Radio();
 313  18
                 break;
 314  
 
 315  
             case checkbox:
 316  14
                 element = new CheckBox();
 317  14
                 break;
 318  
 
 319  
             case text:
 320  3
                 element = new Text();
 321  3
                 break;
 322  
 
 323  
             default:
 324  129
                 element = new Input();
 325  
         }
 326  
 
 327  309
         log.debug("CLASS:" + element.getClass().getName());
 328  
 
 329  309
         Iterator i = attributes.keySet().iterator();
 330  
 
 331  1233
         while (i.hasNext()) {
 332  
             String key, value;
 333  924
             key = (String) i.next();
 334  924
             value = attributes.getAttribute(key);
 335  924
             element.setAttribute(key, value);
 336  
 
 337  
             // Ensure to call setValue for values.
 338  924
             if ("value".equalsIgnoreCase(key)) {
 339  94
                 element.setValue(value);
 340  
             }
 341  924
         }
 342  
 
 343  
         // Also assign the object's name if found.
 344  309
         if (attributes.hasAttribute("name")) {
 345  183
             element.setName(attributes.getAttribute("name"));
 346  126
         } else if (attributes.hasAttribute("id")) {
 347  29
             element.setName(attributes.getAttribute("id"));
 348  
         }
 349  
 
 350  309
         element.setStartPoint(start);
 351  309
         element.setEndPoint(end);
 352  
 
 353  309
         elements.add(element);
 354  309
         return element;
 355  
     }
 356  
 
 357  
     /**
 358  
      * Used for cloning.
 359  
      *
 360  
      * @param element to add
 361  
      * @return HTMLElement
 362  
      */
 363  
     HTMLElement addElement(HTMLElement element) {
 364  12
         elements.add(element);
 365  12
         return element;
 366  
     }
 367  
 
 368  
 
 369  
 }