View Javadoc

1   /*
2       Jiffie Plugin for Jameleon - An Internet Explorer plug-in for Jameleon
3       Copyright (C) 2004-2006 Christian W. Hargraves (engrean@hotmail.com) and
4                          Matthias Marschall (matthias@marschalls.de)
5   
6       This program is free software; you can redistribute it and/or modify
7       it under the terms of the GNU General Public License as published by
8       the Free Software Foundation; either version 2 of the License, or
9       (at your option) any later version.
10  
11      This program is distributed in the hope that it will be useful,
12      but WITHOUT ANY WARRANTY; without even the implied warranty of
13      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14      GNU General Public License for more details.
15  
16      You should have received a copy of the GNU General Public License
17      along with this program; if not, write to the Free Software
18      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20  package net.sf.jameleon.plugin.jiffie.util;
21  
22  import net.sf.jameleon.util.Configurator;
23  import net.sf.jameleon.util.JameleonUtility;
24  
25  import com.jacob.com.ComFailException;
26  
27  import net.sf.jiffie.*;
28  import net.sf.jiffie.xpath.JiffieXPath;
29  
30  import junit.framework.Assert;
31  
32  import org.jaxen.JaxenException;
33  import org.jaxen.XPath;
34  
35  import java.util.ArrayList;
36  import java.util.Iterator;
37  import java.util.List;
38  import java.util.regex.Matcher;
39  import java.util.regex.Pattern;
40  import java.util.StringTokenizer;
41  
42  /***
43   * This class was created to be used by the IEFunctionTag. The idea is to have the
44   * logic in this class and simply have have the IEFunctionTag be a facade. This
45   * should make unit testing much easier and the IEFunctionTag much smaller.
46   */
47  public class IHTMLElementFinder {
48  
49      protected DocumentDelegate docDelegate;
50      private static String ELEMENT_CSS = "border : 5px solid #FF00FF;";
51      private static String FORM_FIELD_CSS = "background : #CCFF33;";
52      private static boolean CHECK_FOR_NON_STANDARD_ATTRIBUTES = false;
53  
54      public IHTMLElementFinder(DocumentDelegate docDelegate) {
55          this.docDelegate = docDelegate;
56          Configurator config = Configurator.getInstance();
57          String elementCSS = config.getValue("jiffie-plugin.highlightedElementCss");
58          String formFieldCss = config.getValue("jiffie-plugin.highlightedFormFieldCss");
59          CHECK_FOR_NON_STANDARD_ATTRIBUTES = new Boolean(config.getValue("jiffie-plugin.checkForNonStandardAttr")).booleanValue();
60          if (elementCSS != null && elementCSS.trim().length() > 0) {
61              ELEMENT_CSS = elementCSS;
62          }
63          if (formFieldCss != null && formFieldCss.trim().length() > 0) {
64              FORM_FIELD_CSS = formFieldCss;
65          }
66      }
67  
68      /***
69       * Gets the area HTML tag with the given alt text
70       * @param altText - the alt text that the desired area tag should have
71       * @return A matching area tag
72       */
73      public IHTMLElement getAreaElementByAltText(String altText) {
74          IHTMLElement areaElement = null;
75          try {
76              ElementList links = docDelegate.getDocument().getElementListByTag("area");
77              IHTMLElement element = null;
78              String alt;
79              Iterator it = links.iterator();
80              while (it.hasNext()) {
81                  element = (IHTMLElement)it.next();
82                  alt = getAttributeValue(element, "alt");
83                  if (altText.equalsIgnoreCase(alt)) {
84                      areaElement = element;
85                  } else {
86                      release(element);
87                  }
88              }
89          } catch (JiffieException je) {
90              Assert.fail("Trouble retrieving area tag with '"+altText+"': "+JameleonUtility.getStack(je));
91          }
92          highlightFormField(areaElement);
93          return areaElement;
94      }
95  
96      /***
97       * Gets an attribute's value for a given element
98       * @param element - The element that contains the attribute
99       * @param attributeName - The name of the attribute with the desired value
100      * 
101      * @return the value for a attribute
102      * Contributed by Alex Eagar
103      */
104     public String getAttributeValue(IHTMLElement element, String attributeName) {
105         String value = null;
106         if (CHECK_FOR_NON_STANDARD_ATTRIBUTES) {
107             IHTMLAttributeCollection attributes = element.getAttributes();
108             int attributeCount = attributes.getLength();
109             for (int i = 0; i < attributeCount && value == null; i++) {
110                 if (attributes.item(i).getName().equalsIgnoreCase(attributeName)) {
111                     value = attributes.item(i).getValue();
112                 }
113             }
114         }else{
115             value = element.getStringProperty(attributeName);
116         }
117          return value;
118     }
119 
120     /***
121      * This method returns the IHTMLDOMNode identified by the given xpath. The IHTMLDOMNode could be either an
122      * IHTMLElement, an IHTMLDOMAttribute or an IHTMLDOMTextNode.
123      * @param xpath2evaluate - The xpath identifying the wanted node in the DOM.
124      * @return Depending on the given xpath either IHTMLElement, IHTMLDOMAttribute or IHTMLDOMTextNode.
125      */
126     public IHTMLDOMNode getByXPath(String xpath2evaluate) {
127         XPath xpath = null;
128         IHTMLDOMNode o = null;
129         if (xpath2evaluate != null && xpath2evaluate.length() > 0) {
130             IHTMLDocument2 doc = docDelegate.getDocument();
131             try {
132                 xpath = new JiffieXPath(xpath2evaluate);
133                 o = (IHTMLDOMNode) xpath.selectSingleNode(doc);
134             } catch (JaxenException e) {
135                 throw new RuntimeException("Jaxen was not able to evaluate xpath: '" + xpath2evaluate + "'");
136             } catch (ClassCastException e) {
137                 throw new RuntimeException("XPath did not evaluate to an IHTMLDOMNode");
138             } finally {
139                 doc.release();
140             }
141         } else {
142             throw new RuntimeException("Please provide an xpath to identify the element.");
143         }
144         return o;
145     }
146 
147     /***
148      * Gets the checkbox given by it's field name
149      *
150      * @param checkboxFieldName - the name of the checkbox
151      * @return the checkbox representing the field name.
152      * @throws RuntimeException if the field does not exist in the form.
153      */
154     public IHTMLInputElement getCheckbox(String checkboxFieldName) {
155         IHTMLInputElement checkbox = null;
156         if (docDelegate.getWorkingForm() != null) {
157             checkbox = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name"}, new String[]{"checkbox", checkboxFieldName});
158         } else {
159             checkbox = (IHTMLInputElement) getIHTMLElement("input", new String[]{"type", "name"}, new String[]{"checkbox", checkboxFieldName});
160         }
161         highlightFormField(checkbox);
162         return checkbox;
163     }
164 
165     /***
166      * Gets the checkbox given by it's field name and value
167      *
168      * @param checkboxFieldName - the name of the checkbox
169      * @param checkboxFieldValue - the value of the checkbox
170      * @return the checkbox representing the field name.
171      * @throws RuntimeException if the field does not exist in the form.
172      */
173     public IHTMLInputElement getCheckboxWithNameAndValue(String checkboxFieldName, String checkboxFieldValue) {
174         IHTMLInputElement checkbox = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name", "value"}, new String[]{"checkbox", checkboxFieldName, checkboxFieldValue});
175         highlightFormField(checkbox);
176         return checkbox;
177     }
178 
179     /***
180     * @param xpath2evaluate - The XPath identifying the element
181     * @return The IHTMLElement identified by the given XPath. Null ifthe XPath does not identify any element.
182     */
183     public IHTMLElement getElementByXPath (String xpath2evaluate) {
184         IHTMLDOMNode node = getByXPath(xpath2evaluate);
185         IHTMLElement element = null;
186         if (node != null) {
187             if (node instanceof IHTMLElement) {
188                 element = (IHTMLElement) node;
189             } else {
190                 release(element);
191                 throw new RuntimeException("XPath did not evaluate to an IHTMLElement node. Node found is: " + node);
192             }
193         }
194         highlightElement(element);
195         return element;
196     }
197 
198     /***
199     * @param xpath2evaluate - The XPath identifying the element
200     * @return A List of matching elements
201     */
202     public List getElementsByXPath(String xpath2evaluate) {
203         XPath xpath = null;
204         List l = new ArrayList();
205         if (xpath2evaluate != null && xpath2evaluate.length() > 0) {
206             IHTMLDocument2 doc = docDelegate.getDocument();
207             try {
208                 xpath = new JiffieXPath(xpath2evaluate);
209                 l = xpath.selectNodes(doc);
210             } catch (JaxenException e) {
211                 throw new RuntimeException("Jaxen was not able to evaluate xpath: '" + xpath2evaluate + "'");
212             } finally {
213                 doc.release();
214             }
215         } else {
216             throw new IllegalArgumentException("xpath2evaluate is a required field!");
217         }
218         return l;
219     }
220 
221     /***
222      * Gets a frame by the id attribute
223      * @param container - the ElementContainer that contains the desired frame.
224      * @param frameId - the id of the frame
225      * @return the frame represented by the frame id
226      */
227     public IHTMLFrameBase2 getFrameWithId(ElementContainer container, String frameId){
228         return getFrame(container, "id", frameId);
229     }
230 
231     /***
232      * Gets a frame by the id attribute
233      * @param frameId - the id of the frame
234      * @return the frame represented by the frame id
235      */
236     public IHTMLFrameBase2 getFrameWithId(String frameId){
237         return getFrameWithId(docDelegate.getDocument(),frameId);
238     }
239 
240     /***
241      * Gets a frame by the name attribute
242      * @param container - the ElementContainer that contains the desired frame.
243      * @param frameName - the name of the frame
244      * @return the frame represented by the frame name
245      */
246     public IHTMLFrameBase2 getFrameWithName(ElementContainer container, String frameName){
247         return getFrame(container, "name", frameName);
248     }
249 
250     /***
251      * Gets a frame by the name attribute
252      * @param frameName - the name of the frame
253      * @return the frame represented by the frame name
254      */
255     public IHTMLFrameBase2 getFrameWithName(String frameName){
256         return getFrameWithName(docDelegate.getDocument(),frameName);
257     }
258 
259     /***
260      * Gets a frame by the src attribute
261      * @param container - the ElementContainer that contains the desired frame.
262      * @param frameSrc - the source of the frame
263      * @return the frame represented by the frame src
264      */
265     public IHTMLFrameBase2 getFrameWithSrc(ElementContainer container, String frameSrc){
266         return getFrame(container, "src", frameSrc);
267     }
268 
269     /***
270      * Gets a frame by the src attribute
271      * @param frameSrc - the source of the frame
272      * @return the frame represented by the frame src
273      */
274     public IHTMLFrameBase2 getFrameWithSrc(String frameSrc){
275         return getFrameWithSrc(docDelegate.getDocument(),frameSrc);
276     }
277 
278     /***
279      * Gets a frame by the name attribute
280      * @param container - the ElementContainer that contains the desired frame.
281      * @param attrName - the attribute with which to find the frame(name/id/src)
282      * @param attrValue - the name,id, or src of the frame. This can be a comma-separated 
283      *                    list of names, ids or srcs.
284      * @return the frame represented by the frame name
285      */
286     public IHTMLFrameBase2 getFrame(ElementContainer container, String attrName, String attrValue){
287         List frameAttrValueList = parseStringOfTokens(attrValue, ",");
288         IHTMLFrameBase2 frame = null;
289         Iterator iter = frameAttrValueList.iterator();
290         while (iter.hasNext()) {
291             String frameAttrValue = (String)iter.next();
292             ElementContainer curContainer = container;
293             if (frame != null) {
294                 try {
295                     curContainer = frame.getDocument(true);
296                 } catch (JiffieException je) {
297                     throw new RuntimeException("No frame with " + attrName + " of "+ frameAttrValue + " exists in the current document", je);
298                 }
299             }
300             frame = internalGetFrame(curContainer, attrName, frameAttrValue);
301         }
302         return frame;
303     }
304 
305     /***
306      * Gets a frame by the specified attribute
307      * @param container - the ElementContainer that contains the desired frame.
308      * @param attrName - the attribute with which to find the frame (name, id, src)
309      * @param attrValue - the name,id, or src of the frame
310      * @return the frame represented by the frame name
311      */
312     protected IHTMLFrameBase2 internalGetFrame(ElementContainer container, String attrName, String attrValue){
313         IHTMLFrameBase2 frame = null;
314         Object obj = getIHTMLElement(container, "frame", attrName, attrValue);
315         if (obj != null) {
316             frame = (IHTMLFrameBase2)obj;
317         } else {
318             obj = getIHTMLElement(container, "iframe", attrName, attrValue);
319             if (obj != null) {
320                 frame = (IHTMLFrameBase2)obj;
321             }
322         }
323         return frame;
324     }
325 
326     /***
327      * Parses a comma-separated list.
328      * @param tokenSeparatedList - A token-delimited String 
329      * @param token - The token to parse the String with 
330      * @return A List of tokens from the comma-separated list 
331      */
332     public List parseStringOfTokens(String tokenSeparatedList, String token) {
333         List retval = new ArrayList();
334         if (tokenSeparatedList != null && tokenSeparatedList.length() > 0) {
335             StringTokenizer tokenizer = new StringTokenizer(tokenSeparatedList, token);
336             while (tokenizer.hasMoreTokens()) {
337                 retval.add(tokenizer.nextToken());
338             }
339         }
340         return retval;
341     }
342 
343     /***
344      * Tries to get a form via the following methods in order.
345      * <ol>
346      * <li><code>getFormWithId()</code> - Gets a form with the expected id attribute
347      * <li><code>getFormWithName()</code> - Gets a form with the expected name attribute
348      * <li><code>getFormWithIndex()</code> - The parameter is converted to a number, representing
349      * the index of the form on the page.
350      * <li><code>getFormWithXPath</code> - Gets a form with the expected XPath
351      * </ol>
352      *
353      * @param formInfo - The form id or name or index or XPath identifying the form
354      * @return the first form that corresponds to the above mentioned or <code>null</code> if no <code>Form</code> is found.
355      */
356     public IHTMLFormElement getForm(String formInfo) {
357         IHTMLFormElement form = null;
358         if (formInfo == null) {
359             throw new RuntimeException(JameleonUtility.createErrMsg("Please provide something defining the form"));
360         }
361         try {
362             form = getFormWithId(formInfo);
363             if (form == null) {
364                 form = getFormWithName(formInfo);
365                 if (form == null) {
366                     if (Character.isDigit(formInfo.charAt(0))) {
367                         int index = new Integer(formInfo).intValue();
368                         form = getFormWithIndex(index);
369                     } else {
370                         if (form == null) {
371                             form = getFormWithXPath(formInfo);
372                         }
373                     }
374                 }
375             }
376         } catch (Exception e) {
377             throw new RuntimeException(JameleonUtility.createErrMsg("Couldn't get form \"" + formInfo + "\""), e);
378         }
379         highlightElement(form);
380         return form;
381     }
382 
383     /***
384      * Gets the first matching element with a given attribute and attribute value
385      * @param htmlTag - The name of the element or tag. For an input element, you'd pass "input"
386      * @param attributeName - The name of the attribute to exist in the element.
387      * @param attributeValue - The value of the name attribute to exist in the element.
388      */
389     public IHTMLElement getFormElement(String htmlTag, String attributeName, String attributeValue ) {
390         List elements = getFormElements(htmlTag);
391 
392         IHTMLElement element = null;
393         IHTMLElement elementFound = null;
394         Iterator it = elements.iterator();
395         String attributeV;
396         while (it.hasNext() && elementFound == null) {
397             element = (IHTMLElement) it.next();
398             attributeV = getAttributeValue(element, attributeName);
399             //Under the case where it's a src attribute, only check to see if it ends with the expected value
400             //because the jiffie API transforms to an abosolute URL not matter what.
401             if (attributeName != null && attributeName.equalsIgnoreCase("src")) {
402                 if (attributeV != null && attributeV.endsWith(attributeValue)) {
403                     elementFound = element;
404                 }
405             } else {
406                 if (attributeV != null && attributeV.equals(attributeValue)) {
407                     elementFound = element;
408                 }
409             }
410             if (elementFound == null) {
411                 release(element);
412             }
413         }
414         highlightElement(elementFound);
415         return elementFound;
416     }
417 
418     /***
419      * Gets the first matching element with given attributes and attribute values
420      * @param htmlTag - The name of the element or tag. For an input
421      *                element, you'd pass "input"
422      * @param attributeNames - A List of names of attributes to
423      *                       exist in the element.
424      * @param attributeValues - A List of values of name attributes
425      *                        to exist in the element. Must be in
426      *                        the same order as attributeNames
427      */
428     public IHTMLElement getFormElement(String htmlTag, String[] attributeNames, String[] attributeValues ) {
429         List elements = getFormElements(htmlTag);
430 
431         IHTMLElement element = null;
432         IHTMLElement elementFound = null;
433         Iterator it = elements.iterator();
434         String attributeV;
435         boolean matches = true;
436         while (it.hasNext() && elementFound == null) {
437             element = (IHTMLElement) it.next();
438             for (int i = 0; i < attributeNames.length && matches; i++) {
439                 attributeV = getAttributeValue(element, attributeNames[i]);
440                 if (attributeNames[i] != null && attributeNames[i].equalsIgnoreCase("src")) {
441                     if (attributeV == null || !attributeV.endsWith(attributeValues[i])) {
442                         matches = false;
443                     }
444                 } else {
445                     if (attributeV == null || !attributeV.equals(attributeValues[i])) {
446                         matches = false;
447                     }
448                 }
449             }
450             if (matches) {
451                 elementFound = element;
452             } else {
453                 release(element);
454             }
455             matches = true;
456         }
457         highlightElement(elementFound);
458         return elementFound;
459     }
460 
461     /***
462      * Gets a list of html elements.
463      * @param htmlTag - The name of the element or tag. For an input element, you'd pass "input"
464      */
465     public List getFormElements(String htmlTag) {
466         ElementList elements = null;
467         if (docDelegate.getWorkingForm() != null) {
468             try {
469                 elements = docDelegate.getWorkingForm().getElementListByTag(htmlTag);
470             } catch (JiffieException je) {
471                 throw new RuntimeException("No "+ htmlTag + " elements exist in the working form", je);
472             }
473         } else {
474             throw new RuntimeException("There is no working form set!");
475         }
476         return elements;
477     }
478 
479     /***
480      * Gets a list of elements with a given attribute and attribute value
481      * @param htmlTag - The name of the element or tag. For an input element, you'd pass "input"
482      * @param attributeName - The name of the attribute to exist in the element.
483      * @param attributeValue - The value of the name attribute to exist in the element.
484      */
485     public List getFormElements(String htmlTag, String attributeName, String attributeValue ) {
486         List elements = getFormElements(htmlTag);
487         List matchingElements = new ArrayList();
488 
489         IHTMLElement element = null;
490         Iterator it = elements.iterator();
491         String attributeV;
492         boolean found = false;
493         while (it.hasNext()) {
494             element = (IHTMLElement) it.next();
495             attributeV = getAttributeValue(element, attributeName);
496             //Under the case where it's a src attribute, only check to see if it ends with the expected value
497             //because the jiffie API transforms to an abosolute URL not matter what.
498             if (attributeName != null && attributeName.equalsIgnoreCase("src")) {
499                 if (attributeV != null && attributeV.endsWith(attributeValue)) {
500                     found = true;
501                 }
502             } else {
503                 if (attributeV != null && attributeV.equals(attributeValue)) {
504                     found = true;
505                 }
506             }
507             if (found) {
508                 matchingElements.add(element);
509             } else {
510                 release(element);
511             }
512             found = false;
513         }
514         return matchingElements;
515     }
516 
517     /***
518      * Gets a list of elements with given attributes and attribute values
519      * @param htmlTag - The name of the element or tag. For an input
520      *                element, you'd pass "input"
521      * @param attributeNames - A List of names of attributes to
522      *                       exist in the element.
523      * @param attributeValues - A List of values of name attributes
524      *                        to exist in the element. Must be in
525      *                        the same order as attributeNames
526      */
527     public List getFormElements(String htmlTag, String[] attributeNames, String[] attributeValues ) {
528         List elements = getFormElements(htmlTag);
529         List matchingElements = new ArrayList();
530 
531         IHTMLElement element = null;
532         Iterator it = elements.iterator();
533         String attributeV;
534         boolean matches = true;
535         while (it.hasNext()) {
536             element = (IHTMLElement) it.next();
537             for (int i = 0; i < attributeNames.length && matches; i++) {
538                 attributeV = getAttributeValue(element, attributeNames[i]);
539                 if (attributeNames[i] != null && attributeNames[i].equalsIgnoreCase("src")) {
540                     if (attributeV == null || !attributeV.endsWith(attributeValues[i])) {
541                         matches = false;
542                     }
543                 } else {
544                     if (attributeV == null || !attributeV.equals(attributeValues[i])) {
545                         matches = false;
546                     }
547                 }
548             }
549             if (matches) {
550                 matchingElements.add(element);
551             } else {
552                 release(element);
553             }
554             matches = true;
555         }
556         return matchingElements;
557     }
558 
559     public ElementList getForms() {
560         ElementList forms = null;
561         IHTMLDocument2 doc = docDelegate.getDocument();
562         try {
563             forms = doc.getElementListByTag("form");
564         } catch (JiffieException je) {
565             throw new RuntimeException("No forms exist on the current page", je);
566         } finally {
567             release(doc);
568         }
569         return forms;
570     }
571 
572     /***
573      * Tries to get a form with the id attribute provided
574      *
575      * @param id - The name of the form to be returned.
576      * @return a form with corresponding to the given name.
577      */
578     public IHTMLFormElement getFormWithId(String id) {
579         IHTMLFormElement form = null;
580         IHTMLDocument2 doc = docDelegate.getDocument();
581         try {
582             IDispatch dis = doc.getElementById(id);
583             if (dis instanceof IHTMLFormElement) {
584                 form = (IHTMLFormElement) dis;
585             } else {
586                 release(dis);
587             }
588 
589         } catch (Exception e) {
590             throw new RuntimeException(JameleonUtility.createErrMsg("Couldn't get a form with the given id \"" + id + "\""), e);
591         } finally {
592             release(doc);
593         }
594         highlightElement(form);
595         return form;
596     }
597 
598     /***
599      * Tries to get the nth form on the page. When a form has no id or name attribute defined,
600      * this method gets all of the forms on the page and returns the nth form, defined by index
601      *
602      * @param index - The number representing the (n-1)th form. The first form would be 0
603      * @return a form with corresponding to the given name.
604      */
605     public IHTMLFormElement getFormWithIndex(int index) {
606         IHTMLFormElement form = null;
607         IHTMLDocument2 doc = docDelegate.getDocument();
608         try {
609             ElementList formList = doc.getElementListByTag("form");
610             if (formList.size() > index) {
611                 Object obj = formList.item(index);
612                 if (obj instanceof IHTMLFormElement) {
613                     form = (IHTMLFormElement) obj;
614                 }
615             } else {
616                 throw new RuntimeException ("Couldn't get a form with the given index \"" + index + "\"");
617             }
618         } catch (JiffieException e) {
619             Assert.fail("Couldn't get a form with the given index \"" + index + "\"");
620         } finally {
621             release(doc);
622         }
623         highlightElement(form);
624         return form;
625     }
626 
627     /***
628      * Tries to get a form with the name attribute provided
629      *
630      * @param name - The name of the form to be returned.
631      * @return a form with corresponding to the given name.
632      */
633     public IHTMLFormElement getFormWithName(String name) {
634         IHTMLFormElement form = null;
635         IHTMLDocument2 doc = docDelegate.getDocument();
636         try {
637             Object obj = doc.getElementByName(name);
638             if (obj instanceof IHTMLFormElement) {
639                 form = (IHTMLFormElement) obj;
640             }
641         } catch (Exception e) {
642             throw new RuntimeException(JameleonUtility.createErrMsg("Couldn't get a form with the given name \"" + name + "\""), e);
643         } finally {
644             doc.release();
645         }
646         highlightElement(form);
647         return form;
648     }
649 
650     /***
651      * Gets a form with the given XPATH.
652      * @param xpath - the XPATH of the form
653      * @return the form matching the provided XPATH.
654      */
655     public IHTMLFormElement getFormWithXPath(String xpath) {
656         IHTMLFormElement form = null;
657         IHTMLElement element = getElementByXPath(xpath);
658         if (element instanceof IHTMLFormElement) {
659             form = (IHTMLFormElement) element;
660         } else {
661             release(element);
662         }  
663         highlightElement(form);
664         return form;
665     }
666 
667     /***
668      * Gets the hidden field given by it's field name
669      *
670      * @param fieldName - the name of the hidden field
671      * @return the hidden field representing the field name.
672      * @throws RuntimeException if the field does not exist in the form.
673      */
674     public IHTMLInputElement getHiddenField(String fieldName) {
675         IHTMLInputElement hiddenField = null;
676         if (docDelegate.getWorkingForm() != null) {
677             hiddenField = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name"}, new String[]{"hidden", fieldName});
678         } else {
679             hiddenField = (IHTMLInputElement) getIHTMLElement("input", new String[]{"type", "name"}, new String[]{"hidden", fieldName});
680         }
681         return hiddenField;
682     }
683 
684     /***
685      * Gets the first matching IHTMLElement with the given html tag, attribute and attribute value
686      * @param container - The ElementContainer to use to get the attributes out of.
687      * @param htmlTag - The HTML tag to get back.
688      * @param attributeName - the attibute in the HTML element
689      * @param attributeValue - the value of attibute in the HTML element
690      * @return the first matching IHTMLElement with the given html tag, attribute and attribute value
691      */
692     public IHTMLElement getIHTMLElement(ElementContainer container, String htmlTag, String attributeName, String attributeValue){
693         IHTMLElement elementFound = null;
694         try {
695             ElementList list = container.getElementListByTag(htmlTag);
696             Iterator it = list.iterator();
697             IHTMLElement element;
698             String attrV;
699             while (it.hasNext() && elementFound == null) {
700                 element = (IHTMLElement)it.next();
701                 attrV = getAttributeValue(element, attributeName);
702                 if (attributeValueMatches(attributeName,attributeValue,attrV)) {
703                     elementFound = element;
704                 } else {
705                     release(element);
706                 }
707             }
708         } catch (JiffieException je) {
709             throw new RuntimeException("Could not find a '"+htmlTag+"' with the "+attributeName+"="+attributeValue, je);
710         }
711         highlightElement(elementFound);
712         return elementFound;
713     }
714 
715     /***
716      * Gets the first matching IHTMLElement with the given html tag, attribute and attribute value
717      * @param htmlTag - The HTML tag to get back.
718      * @param attributeName - the attibute in the HTML element
719      * @param attributeValue - the value of attibute in the HTML element
720      * @return the first matching IHTMLElement with the given html tag, attribute and attribute value
721      */
722     public IHTMLElement getIHTMLElement(String htmlTag, String attributeName, String attributeValue){
723         return getIHTMLElement(docDelegate.getDocument(), htmlTag, attributeName, attributeValue);
724     }
725 
726     /***
727      * Gets the first matching IHTMLElement with the given html tag, attributes and attribute values
728      * @param container - The ElementContainer to use to get the attributes out of.
729      * @param htmlTag - The HTML tag to get back.
730      * @param attributeNames - a list of attibutes in the HTML element
731      * @param attributeValues - a list of values of attibutes in the same order as the names
732      * @return the first matching IHTMLElement with the given html tag, attribute and attribute value
733      */
734     public IHTMLElement getIHTMLElement(ElementContainer container, String htmlTag, String[] attributeNames, String[] attributeValues){
735         IHTMLElement elementFound = null;
736         try {
737             ElementList list = container.getElementListByTag(htmlTag);
738             Iterator it = list.iterator();
739             IHTMLElement element;
740             String attrV;
741             while (it.hasNext() && elementFound == null) {
742                 boolean matches = true;
743                 element = (IHTMLElement)it.next();
744                 for (int i = 0; i < attributeValues.length && matches; i++) {
745                     attrV = getAttributeValue(element, attributeNames[i]);
746                     if (!attributeValueMatches(attributeNames[i], attributeValues[i], attrV)) {
747                         matches = false;
748                     }
749                 }
750                 if (matches) {
751                     elementFound = element;
752                 } else {
753                     release(element);
754                 }
755             }
756         } catch (JiffieException je) {
757             throw new RuntimeException("Could not find a matching '"+htmlTag+"' tag!", je);
758         }
759         highlightElement(elementFound);
760         return elementFound;
761     }
762 
763     /***
764      * Gets the first matching IHTMLElement with the given html tag, attributes and attribute values
765      * @param htmlTag - The HTML tag to get back.
766      * @param attributeNames - a list of attibutes in the HTML element
767      * @param attributeValues - a list of values of attibutes in the same order as the names
768      * @return the first matching IHTMLElement with the given html tag, attribute and attribute value
769      */
770     public IHTMLElement getIHTMLElement(String htmlTag, String[] attributeNames, String[] attributeValues){
771         return getIHTMLElement(docDelegate.getDocument(),htmlTag,attributeNames, attributeValues);
772     }
773 
774     /***
775      * Gets a List of matching IHTMLElements with the given html tag, attribute and attribute value
776      * @param container - The ElementContainer to use to get the attributes out of.
777      * @param htmlTag - The HTML tag to get back.
778      * @param attributeName - the attibute in the HTML element
779      * @param attributeValue - the value of attibute in the HTML element
780      * @return a List of matching IHTMLElements with the given html tag, attribute and attribute value
781      */
782     public List getIHTMLElements(ElementContainer container, String htmlTag, String attributeName, String attributeValue){
783         List elements = new ArrayList();
784         try {
785             ElementList list = container.getElementListByTag(htmlTag);
786             Iterator it = list.iterator();
787             IHTMLElement element;
788             String attrV;
789             while (it.hasNext()) {
790                 element = (IHTMLElement)it.next();
791                 attrV = getAttributeValue(element, attributeName);
792                 if (attributeValueMatches(attributeName,attributeValue,attrV)) {
793                     elements.add(element);
794                 } else {
795                     release(element);
796                 }
797             }
798         } catch (JiffieException je) {
799             throw new RuntimeException("Could not find a '"+htmlTag+"' with the "+attributeName+"="+attributeValue, je);
800         }
801         return elements;
802     }
803 
804     /***
805      * Gets a List of matching IHTMLElements with the given html tag, attribute and attribute value
806      * @param htmlTag - The HTML tag to get back.
807      * @param attributeName - the attibute in the HTML element
808      * @param attributeValue - the value of attibute in the HTML element
809      * @return a List of matching IHTMLElements with the given html tag, attribute and attribute value
810      */
811     public List getIHTMLElements(String htmlTag, String attributeName, String attributeValue){
812         return getIHTMLElements(docDelegate.getDocument(),htmlTag,attributeName,attributeValue);
813     }
814 
815     /***
816      * Gets a List of matching IHTMLElements with the given html tag, attributes and attribute values
817      * @param container - The ElementContainer to use to get the attributes out of.
818      * @param htmlTag - The HTML tag to get back.
819      * @param attributeNames - a list of attibutes in the HTML element
820      * @param attributeValues - a list of values of attibutes in the same order as the names
821      * @return a List of matching IHTMLElements with the given html tag, attribute and attribute value
822      */
823     public List getIHTMLElements(ElementContainer container, String htmlTag, String[] attributeNames, String[] attributeValues){
824         List elements = new ArrayList();
825         try {
826             ElementList list = container.getElementListByTag(htmlTag);
827             Iterator it = list.iterator();
828             IHTMLElement element;
829             String attrV;
830             while (it.hasNext()) {
831                 boolean matches = true;
832                 element = (IHTMLElement)it.next();
833                 for (int i = 0; i < attributeValues.length && matches; i++) {
834                     attrV = getAttributeValue(element, attributeNames[i]);
835                     if (!attributeValueMatches(attributeNames[i], attributeValues[i], attrV)) {
836                         matches = false;
837                     }
838                 }
839                 if (matches) {
840                     elements.add(element);
841                 } else {
842                     release(element);
843                 }
844             }
845         } catch (JiffieException je) {
846             throw new RuntimeException("Could not find a matching '"+htmlTag+"' tag!" , je);
847         }
848         return elements;
849     }
850 
851     /***
852      * Gets a List of matching IHTMLElements with the given html tag, attributes and attribute values
853      * @param htmlTag - The HTML tag to get back.
854      * @param attributeNames - a list of attibutes in the HTML element
855      * @param attributeValues - a list of values of attibutes in the same order as the names
856      * @return a List of matching IHTMLElements with the given html tag, attribute and attribute value
857      */
858     public List getIHTMLElements(String htmlTag, String[] attributeNames, String[] attributeValues){
859         return getIHTMLElements(docDelegate.getDocument(),htmlTag,attributeNames, attributeValues);
860     }
861 
862     /***
863      * Helper method to find a link with given img alt text
864      *
865      * @param text - The alt text of the img contained by the link
866      * @return The IHTMLAnchorElement for the link
867      */
868     public IHTMLAnchorElement getImageLinkWithAltText(String text) {
869         IHTMLAnchorElement link = null;
870         // get all anchor elements
871         IHTMLDocument2 doc = docDelegate.getDocument();
872         try {
873             ElementList links = doc.getElementListByTag("a");
874             // find the one, which has the given 'text' as the alt attribute of an embedded image tag
875             Iterator it = links.iterator();
876             IHTMLAnchorElement anchorElement;
877             IHTMLImgElement imgElement;
878             while (it.hasNext()) {
879                 anchorElement = (IHTMLAnchorElement) it.next();
880                 imgElement = (IHTMLImgElement) anchorElement.getElementByTag("img");
881                 if (null != imgElement) {
882                     if ( imgElement.getName().equalsIgnoreCase(text) || 
883                          ( getAttributeValue(imgElement, "alt") != null 
884                            && getAttributeValue(imgElement, "alt").equalsIgnoreCase(text)
885                          ) ) {
886                         link = anchorElement;
887                         break;
888                     } else {
889                         release(imgElement);
890                     }
891                 }
892             }
893         } catch (JiffieException je) {
894             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find image link with alt text '" + text +"'!"), je);
895         } finally {
896             release(doc);
897         }
898         highlightElement(link);
899         return link;
900     }
901 
902     /***
903      * Tries to get an input field by name. This method does not care what type of
904      * input field it is.
905      *
906      * @param inputFieldName - The name of the input field that exists in the current working form
907      * @return the first element with the provided name.
908      */
909     public IHTMLInputElement getInputFieldByName(String inputFieldName) {
910         IHTMLInputElement field = null;
911         try {
912             field = (IHTMLInputElement) docDelegate.getWorkingForm().getElementByNameAndTag(inputFieldName, "input");
913         } catch (JiffieException je) {
914             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find the input field with the given name "+inputFieldName), je);
915         }
916         return field;
917     }
918 
919     /***
920      * Tries to get an input field by name. This method does not care what type of
921      * input field it is.
922      *
923      * @param inputFieldName - The name of the input field that exists in the current working form
924      * @return the first element with the provided name.
925      */
926     public List getInputFieldsByName(String inputFieldName) {
927         return getIHTMLElements("input", "name", inputFieldName);
928     }
929 
930     /***
931      * Tries to get a link via the following methods in order.
932      * <ol>
933      * <li><code>getLinkWith()</code> - Gets a link with the diplayed text
934      * <li><code>getLinkWithID()</code> - Gets a link with the <code>id</code> attribute set.
935      * <li><code>getImageLinkWithAltText</code> - Gets a link with the alt attribute or alt text.
936      * <li><code>getLinkWithName()</code> - Gets a link with the name attribute set.
937      * <li><code>getLinkWithImageSrc()</code> - Gets a link with the image src.
938      * </ol>
939      *
940      * @param text - The link text or the link id or the alt text or the link name.
941      * @return the first link that corresponds to the above mentioned or <code>null</code> if no <code>WebLink</code> is found.
942      * todo order should be id, name, label, imageText.
943      */
944     public IHTMLAnchorElement getLink(String text) {
945         IHTMLAnchorElement link = null;
946         boolean success = false;
947         int passes = 0;
948         while (!success && passes < 5) {
949             try {
950                 link = getLinkWith(text);
951                 if (link == null) {
952                     link = getLinkWithID(text);
953                     if (link == null) {
954                         link = getImageLinkWithAltText(text);
955                         if (link == null) {
956                             link = getLinkWithName(text);
957                             if (link == null) {
958                                 link = getLinkWithImageSrc(text);
959                             }
960                         }
961                     }
962                 }
963                 success = true;
964             } catch (ComFailException e) {
965                 //Assert.fail(JameleonUtility.createErrMsg("Communication to Internet Explorer failed. Please re-run test!"));
966                 success = false;
967                 passes++;
968             }
969         }
970         highlightElement(link);
971         return link;
972     }
973 
974     /***
975      * Helper method to find a link with contained text
976      *
977      * @param text - The text contained by the link
978      * @return The IHTMLAnchorElement for the link
979      */
980     public IHTMLAnchorElement getLinkWith(String text) {
981         IHTMLAnchorElement link = null;
982         // get all anchor elements
983         IHTMLDocument2 doc = docDelegate.getDocument();
984         try {
985             ElementList links = doc.getElementListByTag("a");
986 
987             Iterator it = links.iterator();
988             // find the one, which has the given 'text'
989             while (it.hasNext()) {
990                 IHTMLAnchorElement anchorElement = (IHTMLAnchorElement) it.next();
991                 if (anchorElement.getInnerText().trim().equalsIgnoreCase(text)) {
992                     link = anchorElement;
993                     break;
994                 } else {
995                     release(anchorElement);
996                 }
997             }
998         } catch (JiffieException je) {
999             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find link with the text '" + text +"'!"), je);
1000         } finally {
1001             release(doc);
1002         }
1003         highlightElement(link);
1004         return link;
1005     }
1006 
1007     /***
1008      * Helper method to find a link with the regex
1009      * found in the href, and the text contained in the
1010      * inner text, ID, or name.
1011      *
1012      * @param regex - The regex to be found in the href attribute of the link
1013      * @param text - The text contained by the link
1014      * @return The IHTMLAnchorElement for the link
1015      */
1016     public IHTMLAnchorElement getLinkWithHref(String regex, String text) {
1017         IHTMLAnchorElement link = null;
1018         // get all anchor elements
1019         IHTMLDocument2 doc = docDelegate.getDocument();
1020         try {
1021             boolean isTextNull = (text == null || text.length() == 0);
1022             ElementList links = doc.getElementListByTag("a");
1023             Matcher matcher = Pattern.compile(regex, Pattern.CASE_INSENSITIVE).matcher("");
1024             // Find the one, which has the given 'regex'
1025             Iterator it = links.iterator();
1026             while (it.hasNext()) {
1027                 IHTMLAnchorElement anchorElement = (IHTMLAnchorElement) it.next();
1028                 String href = anchorElement.getHref().trim();
1029                 matcher.reset(href);
1030                 if (matcher.find() && (isTextNull || (anchorElement.getInnerText().indexOf(text) > -1||
1031                       anchorElement.getID().trim().equalsIgnoreCase(text) ||
1032                       anchorElement.getName().trim().equalsIgnoreCase(text)))) {
1033                     link = anchorElement;
1034                     break;
1035                 } else {
1036                     release(anchorElement);
1037                 }
1038             }
1039         } catch (JiffieException je) {
1040             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find link with href like '" + regex +"'!"), je);
1041         } finally {
1042             release(doc);
1043         }
1044         highlightElement(link);
1045         return link;
1046     }
1047 
1048     /***
1049      * Helper method to find all links with contained text
1050      *
1051      * @param text - The text contained by the links
1052      * @return The IHTMLAnchorElement for the link
1053      */
1054     public List getLinksWith(String text) {
1055         List links = new ArrayList();
1056         // get all anchor elements
1057         IHTMLDocument2 doc = docDelegate.getDocument();
1058         try {
1059             ElementList allLinks = doc.getElementListByTag("a");
1060             // find the one, which has the given 'text'
1061             IHTMLAnchorElement anchorElement;
1062             Iterator it = allLinks.iterator();
1063             while (it.hasNext()) {
1064                 anchorElement = (IHTMLAnchorElement) it.next();
1065                 if (anchorElement.getInnerText().trim().equalsIgnoreCase(text)) {
1066                     links.add(anchorElement);
1067                 } else {
1068                     release(anchorElement);
1069                 }
1070             }
1071         } catch (JiffieException je) {
1072             throw new RuntimeException( "Could not find link with the text '" + text +"'!", je);
1073         } finally {
1074             release(doc);
1075         }
1076         return links;
1077     }
1078 
1079     /***
1080      * Helper method to find a link with given id
1081      *
1082      * @param id - The id of the link
1083      * @return The IHTMLAnchorElement for the link
1084      */
1085     public IHTMLAnchorElement getLinkWithID(String id) {
1086         IHTMLAnchorElement link = null;
1087         IHTMLDocument2 doc = docDelegate.getDocument();
1088         try {
1089             link = (IHTMLAnchorElement) doc.getElementById(id);
1090         } catch (ClassCastException e) {
1091             // the element with given 'id' is not an anchor
1092             link = null;
1093         } catch (JiffieException je) {
1094             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find link with id '" + id +"'!"), je);
1095         } finally {
1096             release(doc);
1097         }
1098         highlightElement(link);
1099         return link;
1100     }
1101 
1102     /***
1103      * Helper method to find a link with given img src attribute
1104      *
1105      * @param src - The part of the src attribute of the img contained by the link
1106      * @return The IHTMLAnchorElement for the link
1107      */
1108     public IHTMLAnchorElement getLinkWithImageSrc(String src) {
1109         IHTMLAnchorElement link = null;
1110         // get all anchor elements
1111         IHTMLDocument2 doc = docDelegate.getDocument();
1112         try {
1113             ElementList links = doc.getElementListByTag("a");
1114             Iterator it = links.iterator();
1115             // find the one, which has the given 'src' as the src attribute of an embedded image tag
1116             IHTMLAnchorElement anchorElement;
1117             IHTMLImgElement imgElement;
1118             while (it.hasNext()) {
1119                 anchorElement = (IHTMLAnchorElement) it.next();
1120                 imgElement = (IHTMLImgElement) anchorElement.getElementByTag("img");
1121                 if (null != imgElement) {
1122                     if (imgElement.getSrc() != null && imgElement.getSrc().indexOf(src) > 0) {
1123                         link = anchorElement;
1124                         break;
1125                     } else {
1126                         release(imgElement);
1127                     }
1128                 }
1129             }
1130         } catch (JiffieException je) {
1131             throw new RuntimeException( JameleonUtility.createErrMsg("Could not find image link with src '" + src +"'!"), je);
1132         } finally {
1133             release(doc);
1134         }
1135         highlightElement(link);
1136         return link;
1137     }
1138 
1139     /***
1140      * Helper method to find a link with given name
1141      *
1142      * @param name - The name of the link to find
1143      * @return The IHTMLAnchorElement for the link
1144      */
1145     public IHTMLAnchorElement getLinkWithName(String name) {
1146         IHTMLAnchorElement link = null;
1147         IHTMLDocument2 doc = docDelegate.getDocument();
1148         try {
1149             IDispatch dis = doc.getElementByNameAndTag(name, "a");
1150             if (dis != null) {
1151                 if (dis instanceof IHTMLAnchorElement) {
1152                     link = (IHTMLAnchorElement) dis;
1153                 } else {
1154                     release(dis);
1155                     throw new RuntimeException(JameleonUtility.createErrMsg("'"+name+"' is not a link. It is a " + dis));
1156                 }
1157             }
1158         } catch (JiffieException je) {
1159             throw new RuntimeException(JameleonUtility.createErrMsg("Could not find link with name '"+name+"'"), je);
1160         } finally {
1161             release(doc);
1162         }
1163         highlightElement(link);
1164         return link;
1165     }
1166 
1167     /***
1168      * Gets the text field given by it's field name
1169      *
1170      * @param passwordFieldName - the name of the password field
1171      * @return the password field representing the field name.
1172      * @throws RuntimeException if the field does not exist in the form.
1173      */
1174     public IHTMLInputElement getPasswordField(String passwordFieldName) {
1175         IHTMLInputElement password = null;
1176         if (docDelegate.getWorkingForm() != null) {
1177             password = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name"}, new String[]{"password",passwordFieldName});
1178         } else {
1179             password = (IHTMLInputElement) getIHTMLElement("input", new String[]{"type", "name"}, new String[]{"password", passwordFieldName});
1180         }
1181         highlightFormField(password);
1182         return password;
1183     }
1184 
1185 
1186     /***
1187      * Gets the radio button with the specified name and value
1188      *
1189      * @param radioButtonName - the name of the radio button
1190      * @param value           - the value to set the radio button to.
1191      * @return a radio button with the specified name and valud
1192      */
1193     public IHTMLInputElement getRadioButton(String radioButtonName, String value) {
1194         IHTMLInputElement radioButton = null;
1195         if (docDelegate.getWorkingForm() != null) {
1196             radioButton = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name", "value"}, new String[]{"radio", radioButtonName, value});
1197         } else {
1198             radioButton = (IHTMLInputElement) getIHTMLElement("input", new String[]{"type", "name", "value"}, new String[]{"radio", radioButtonName, value});
1199         }
1200         highlightFormField(radioButton);
1201         return radioButton;
1202     }
1203 
1204     /***
1205      * Gets the select field defined by <code>selectFieldName</code>
1206      *
1207      * @param selectFieldName - the name of the select field
1208      * @return the select field matching the <code>selectFieldName</code>.
1209      */
1210     public IHTMLSelectElement getSelectField(String selectFieldName) {
1211         IHTMLSelectElement select = null;
1212         if (docDelegate.getWorkingForm() != null) {
1213             select = (IHTMLSelectElement)getFormElement("select", "name", selectFieldName);
1214         } else {
1215             select = (IHTMLSelectElement)getIHTMLElement("select", "name", selectFieldName);
1216         }
1217         highlightFormField(select);
1218         return select;
1219     }
1220 
1221     /***
1222      * Gets the currently selected option from the given select field defined by <code>selectFieldName</code>
1223      *
1224      * @param selectFieldName - the name of the select field
1225      * @return the select option currently selected.
1226      */
1227     public IHTMLOptionElement getSelectedOptionField(String selectFieldName) {
1228         IHTMLOptionElement selectedOption = null;
1229         try {
1230             IHTMLSelectElement ele = getSelectField(selectFieldName);
1231             if (ele != null) {
1232                 int selectedIndex = ele.getSelectedIndex();
1233                 ElementList options = ele.getElementListByTag("option");
1234                 selectedOption = (IHTMLOptionElement)options.get(selectedIndex);
1235             } else {
1236                 throw new RuntimeException("Could not get select field, " + selectFieldName + "!");
1237             }
1238         } catch (JiffieException je) {
1239             throw new RuntimeException("Could not get select field, " + selectFieldName + "!", je);
1240         }
1241         return selectedOption;
1242     }
1243 
1244     /***
1245      * Gets the currently selected option from the given select field defined by <code>selectFieldName</code>
1246      *
1247      * @param selectFieldName - the name of the select field
1248      * @param displayedText - the text displayed in the browser
1249      * @return the select option currently selected.
1250      */
1251     public IHTMLOptionElement getSelectOptionWithText(String selectFieldName, String displayedText) {
1252         IHTMLOptionElement selectedOption = null;
1253         try {
1254             IHTMLSelectElement ele = getSelectField(selectFieldName);
1255             if (ele != null) {
1256                 ElementList options = ele.getElementListByTag("option");
1257                 Iterator it = options.iterator();
1258                 String textValue;
1259                 IHTMLOptionElement option;
1260                 while (it.hasNext() && selectedOption == null) {
1261                     option = (IHTMLOptionElement)it.next();
1262                     textValue = option.getInnerText();
1263                     if (textValue != null && textValue.equals(displayedText)) {
1264                         selectedOption = option;
1265                     } else {
1266                         release(option);
1267                     }
1268                 }
1269                 if (selectedOption == null) {
1270                     throw new RuntimeException(displayedText +" option is not available for "+selectFieldName);
1271                 }
1272             } else {
1273                 throw new RuntimeException("Could not get select field, " + selectFieldName + "!");
1274             }
1275         } catch (JiffieException je) {
1276             throw new RuntimeException("Could not get select field, " + selectFieldName + "!", je);
1277         }
1278         return selectedOption;
1279     }
1280 
1281 
1282     /***
1283      * Tries to get a submit element in the following order.
1284      * <br/>
1285      * <ol>
1286      * <li>&lt;input type="submit" value="...">
1287      * <li>&lt;input type="image" src="...">
1288      * <li>&lt;input type="button" value="...">
1289      * </ol>
1290      *
1291      * @param id - The identifier of the submit element to find. 
1292      *             For submit and button types, it will try to match it with the value attribute.
1293      *             For image input types, it will try to match it with the src or alt attribute.
1294      * @return The input element.
1295      * todo support find <button>...</button>.
1296      */
1297     public IHTMLInputElement getSubmit(String id) {
1298         IHTMLInputElement submit = getSubmit("submit", id);
1299         if (submit == null) {
1300             submit = getSubmit("image", id);
1301             if (submit == null) {
1302                 submit = getSubmit("button", id);
1303             }
1304         }
1305         highlightElement(submit);
1306         return submit;
1307     }
1308 
1309 
1310     /***
1311      * Gets the submit button identified by it's value (the label shown in the browser). Supported ways of finding a
1312      * submit are:<br/>
1313      * &lt;input type="submit" value="some value"><br />
1314      * &lt;input type="image" src="jameleon.jpg" alt="alt text"><br />
1315      * &lt;input type="button" value="some value" onclick="submit();"><br />
1316      * &lt;button id="button tag" type="submit">button tag&lt;/button><br />
1317      *
1318      * @param type  - type of submit field 'submit', 'image' or 'button'
1319      * @param value - the value of the submit field (this is the label of the submit button shown in the browser)
1320      * @return the input field representing the submit button or null if not found.
1321      * @throws RuntimeException if the field does not exist in the form.
1322      * todo introduce constants for supported types.
1323      */
1324     public IHTMLInputElement getSubmit(String type, String value) {
1325         IHTMLInputElement submit = null;
1326         List validType = new ArrayList();
1327         validType.add("submit");
1328         validType.add("image");
1329         validType.add("button");
1330         if (type == null || !validType.contains(type)) {
1331             throw new RuntimeException("Please provide a valid type: 'submit', 'image' or 'button'");
1332         }
1333         if (docDelegate.getWorkingForm() != null) {
1334             try {
1335                 List inputElements = docDelegate.getWorkingForm().getElementListByTag("input");
1336                 if (inputElements != null && !inputElements.isEmpty()) {
1337                     Iterator it = inputElements.iterator();
1338                     while (it.hasNext()) {
1339                         IDispatch dis = (IDispatch)it.next();
1340                         if (dis instanceof IHTMLInputElement) {
1341                             IHTMLInputElement input = (IHTMLInputElement) dis;
1342                             if (type.equals(input.getType())) {
1343                                 if ((type.equals("submit") || type.equals("button")) && input.getValue().equals(value)) {
1344                                     submit = (IHTMLInputElement) dis;
1345                                 } else if (type.equals("image") && 
1346                                            ( getAttributeValue(input, "alt").equals(value) ||
1347                                              getAttributeValue(input, "src").endsWith(value) ) ) {
1348                                     submit = (IHTMLInputElement) dis;
1349                                 } else {
1350                                     release(input);
1351                                 }
1352                             } else {
1353                                 release(input);
1354                             }
1355                         } else {
1356                             release(dis);
1357                         }
1358                     }
1359                 } else {
1360                     throw new RuntimeException("There are no input fields in the working form!");
1361                 }
1362             } catch (JiffieException je) {
1363                 throw new RuntimeException("Could not check " + value, je);
1364             }
1365         } else {
1366             throw new RuntimeException("There is no working form set!");
1367         }
1368         highlightElement(submit);
1369         return submit;
1370     }
1371 
1372     /***
1373      * Gets a submit button by it's name from the working form
1374      *
1375      * @param buttonName - the name of the submit button
1376      * @return the submit button with the provided <code>buttonName</code>
1377      * @throws RuntimeException if the desired submit button isn't found in the working form.
1378      */
1379     public IHTMLInputElement getSubmitButtonWithName(String buttonName) {
1380         IHTMLInputElement submitButton = null;
1381         if (docDelegate.getWorkingForm() != null) {
1382             IHTMLInputElement tmpButton = getInputFieldByName(buttonName);
1383             if (tmpButton != null) {
1384                 if ("submit".equals(tmpButton.getType()) ||
1385                     "button".equals(tmpButton.getType()) ||
1386                     "image".equals(tmpButton.getType())) {
1387                     submitButton = tmpButton;
1388                 } else {
1389                     release(tmpButton);
1390                     throw new RuntimeException(buttonName + " is not a submit button!");
1391                 }
1392             } else {
1393                 throw new RuntimeException(buttonName + " does not exist as a form submit button!");
1394             }
1395         } else {
1396             throw new RuntimeException("There is no working form set!");
1397         }
1398         highlightElement(submitButton);
1399         return submitButton;
1400     }
1401 
1402     /***
1403      * Gets the first submit button by it's name from the working form
1404      *
1405      * @param buttonName - the name of the submit button
1406      * @param value - the value attribute of the button
1407      * @return the submit button with the provided <code>buttonName</code> and <code>value</code>.
1408      * @throws RuntimeException if the desired submit button isn't found in the working form.
1409      */
1410     public IHTMLInputElement getSubmitButtonWithNameAndValue(String buttonName, String value) {
1411         IHTMLInputElement submitButton = null;
1412         if (docDelegate.getWorkingForm() != null) {
1413             List elements = getInputFieldsByName(buttonName);
1414             if (elements != null && !elements.isEmpty()) {
1415                 IHTMLInputElement tmpButton;
1416                 Iterator it = elements.iterator();
1417                 while (it.hasNext()) {
1418                     tmpButton = (IHTMLInputElement)it.next();
1419                     if (("submit".equals(tmpButton.getType()) ||
1420                          "button".equals(tmpButton.getType()) ||
1421                          "image".equals(tmpButton.getType())) && 
1422                         value.equals(tmpButton.getValue())) {
1423                         submitButton = tmpButton;
1424                         break;
1425                     } else {
1426                         release(tmpButton);
1427                     }
1428                 }
1429             } else {
1430                 throw new RuntimeException(buttonName + " does not exist as a form submit button!");
1431             }
1432         } else {
1433             throw new RuntimeException("There is no working form set!");
1434         }
1435         highlightElement(submitButton);
1436         return submitButton;
1437     }
1438 
1439     /***
1440      * Gets the first submit button by it's value from the working form
1441      *
1442      * @param value - the value attribute of the button
1443      * @return the submit button with the provided <code>value</code>.
1444      * @throws RuntimeException if the desired submit button isn't found in 
1445      * the working form.
1446      */
1447     public IHTMLInputElement getSubmitButtonWithValue(String value) {
1448         IHTMLInputElement submitButton = null;
1449         if (docDelegate.getWorkingForm() != null) {
1450             try {
1451                 ElementList elements = docDelegate.getWorkingForm().getElementListByTag("input");
1452                 if (elements != null) {
1453                     Object obj;
1454                     IHTMLInputElement tmpButton;
1455                     Iterator it = elements.iterator();
1456                     while (it.hasNext()) {
1457                         obj = it.next();
1458                         if (obj instanceof IHTMLInputElement) {
1459                             tmpButton = (IHTMLInputElement) obj;
1460 
1461                             if (("submit".equals(tmpButton.getType()) ||
1462                                  "button".equals(tmpButton.getType()) ||
1463                                  "image".equals(tmpButton.getType())) && 
1464                                 value.equals(tmpButton.getValue())) {
1465                                 submitButton = tmpButton;
1466                                 break;
1467                             } else {
1468                                 release(tmpButton);
1469                             }
1470                         }
1471                     }
1472                 } else {
1473                     throw new RuntimeException("Could not find a submit button with the provided value: "+value);
1474                 }
1475             } catch (JiffieException je) {
1476                 throw new RuntimeException("Could not find a submit button with the provided value: "+value, je);
1477             }
1478         } else {
1479             throw new RuntimeException("There is no working form set!");
1480         }
1481         highlightElement(submitButton);
1482         return submitButton;
1483     }
1484 
1485     /***
1486      * Gets the text field given by it's field name
1487      *
1488      * @param fieldName - the name of the text field
1489      * @return the text field representing the field name.
1490      * @throws RuntimeException if the field does not exist in the form.
1491      */
1492     public IHTMLInputElement getTextField(String fieldName) {
1493         IHTMLInputElement text = null;
1494         if (docDelegate.getWorkingForm() != null) {
1495             text = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name"}, new String[]{"text", fieldName});
1496         } else {
1497             text = (IHTMLInputElement) getIHTMLElement("input", new String[]{"type", "name"}, new String[]{"text", fieldName});
1498         }
1499         highlightFormField(text);
1500         return text;
1501     }
1502 
1503     /***
1504      * Gets the file input field given by it's field name
1505      *
1506      * @param fieldName - the name of the file input field
1507      * @return the file input field representing the field name.
1508      * @throws RuntimeException if the field does not exist in the form.
1509      */
1510     public IHTMLInputElement getFileInputField(String fieldName) {
1511         IHTMLInputElement file = (IHTMLInputElement) getFormElement("input", new String[]{"type", "name"}, new String[]{"file", fieldName});
1512         highlightFormField(file);
1513         return file;
1514     }
1515 
1516     /***
1517      * Gets the text area given by it's field name
1518      *
1519      * @param fieldName - the name of the text area
1520      * @return the text area representing the field name.
1521      * @throws RuntimeException if the field does not exist in the form.
1522      */
1523     public IHTMLTextAreaElement getTextArea(String fieldName) {
1524         IHTMLTextAreaElement textArea = null;
1525         if (docDelegate.getWorkingForm() != null) {
1526             textArea = (IHTMLTextAreaElement) getFormElement("textarea", "name", fieldName);
1527         } else {
1528             textArea = (IHTMLTextAreaElement) getIHTMLElement("textarea", "name", fieldName);
1529         }
1530         highlightFormField(textArea);
1531         return textArea;
1532     }
1533 
1534     /***
1535      * Checks to see if the current page has the desired block of text
1536      * @param text - the expected text
1537      * @return True if the expected text is found
1538      */
1539     public boolean isTextInPage(String text){
1540         IHTMLDocument2 doc = docDelegate.getDocument();
1541         boolean textInPage = false;
1542         if (doc != null) {
1543             try {
1544                 String html = doc.getBody().getParentElement().getOuterHtml();
1545                 textInPage = ( html.indexOf(text) >= 0);
1546             } catch (JiffieException je) {
1547                 throw new RuntimeException("Couldn't get text on current page", je);
1548             } finally {
1549                 release(doc);
1550             }
1551         }
1552         return textInPage;
1553     }
1554 
1555     protected void release(IDispatch dis){
1556         if (dis != null) {
1557             dis.release();
1558         }
1559     }
1560 
1561     public void highlightElement(IHTMLElement element){
1562         if (docDelegate.highlightActiveElement() && 
1563             element != null &&
1564             !element.isReleased()) {
1565             element.getStyle().setCssText(ELEMENT_CSS);
1566         }
1567     }
1568 
1569     public void highlightFormField(IHTMLElement element){
1570         if (docDelegate.highlightActiveElement() && 
1571             element != null &&
1572             !element.isReleased()) {
1573             element.getStyle().setCssText(FORM_FIELD_CSS);
1574         }
1575     }
1576 
1577     protected boolean attributeValueMatches(String attributeName, String expectedValue, String actualValue){
1578         boolean matches = false;
1579 
1580         if ( (attributeName != null) && 
1581              (attributeName.equalsIgnoreCase("src") ||
1582               attributeName.equalsIgnoreCase("href")) ) {
1583             if (expectedValue != null && actualValue.endsWith(expectedValue)) {
1584                 matches = true;
1585             }
1586         } else {
1587             if (expectedValue != null && expectedValue.equals(actualValue)) {
1588                 matches = true;
1589             }
1590         }
1591         return matches;
1592     }
1593 }