Package com.gistlabs.mechanize.document.html.form

Source Code of com.gistlabs.mechanize.document.html.form.Form

/**
* Copyright (C) 2012-2014 Gist Labs, LLC. (http://gistlabs.com)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package com.gistlabs.mechanize.document.html.form;

import static com.gistlabs.mechanize.util.css.CSSHelper.byIdOrName;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.gistlabs.mechanize.Resource;
import com.gistlabs.mechanize.document.documentElements.AbstractDocumentElement;
import com.gistlabs.mechanize.document.node.Node;
import com.gistlabs.mechanize.parameters.Parameters;
import com.gistlabs.mechanize.requestor.RequestBuilder;

/**
* Represents a form.
* @author Martin Kersten<Martin.Kersten.mk@gmail.com>
* @since 2012-09-12
*/
public class Form extends AbstractDocumentElement implements Iterable<FormElement> {
  private List<FormElement> elements = new ArrayList<FormElement>();
 
  public Form(Resource page, Node formNode) {
    super(page, formNode);
    analyse();
  }

  private void analyse() {
    List<? extends Node> nodes = getNode().findAll("input, textarea, select");
    for(Node node : nodes) {
      FormElement formElement = newFormElement(node);
      if(formElement != null)
        this.elements.add(formElement);
    }
  }
 
  private FormElement newFormElement(Node node) {
    if(node.getName().equalsIgnoreCase("input") && node.hasAttribute("type")) {
      String type = node.getAttribute("type");
      if(type.equalsIgnoreCase("text"))
        return new Text(this, node);
      else if(type.equalsIgnoreCase("search"))
        return new Search(this, node);
      else if(type.equalsIgnoreCase("email"))
        return new Email(this, node);
      else if(type.equalsIgnoreCase("password"))
        return new Password(this, node);
      else if(type.equalsIgnoreCase("file"))
        return new Upload(this, node);
      else if(type.equalsIgnoreCase("hidden"))
        return new Hidden(this, node);
      else if(type.equalsIgnoreCase("submit"))
        return new SubmitButton(this, node);
      else if(type.equalsIgnoreCase("image"))
        return new SubmitImage(this, node);
      else if(type.equalsIgnoreCase("checkbox"))
        return new Checkbox(this, node);
      else if(type.equalsIgnoreCase("radio"))
        return new RadioButton(this, node);
      else
        return new FormElement(this, node);
    }
    else if(node.getName().equalsIgnoreCase("input") && !node.hasAttribute("type")) {
      //Used to map input without type to text field (as required by google.com search form)
      return new Text(this, node);
    }
    else if(node.getName().equalsIgnoreCase("textarea"))
      return new TextArea(this, node);
    else if(node.getName().equalsIgnoreCase("select"))
      return new Select(this, node);
    else
      return null;
  }
 
  public boolean isDoPost() {
    return getNode().hasAttribute("method") && getNode().getAttribute("method").equalsIgnoreCase("post");
  }
 
  public boolean isMultiPart() {
    return getNode().hasAttribute("enctype") && getNode().getAttribute("enctype").equalsIgnoreCase("multipart/form-data");
  }
 
  public String getUri() {
    String uri = null;
    if(getNode().hasAttribute("action"))
      uri = absoluteUrl(getNode().getAttribute("action"));
    else
      uri = getResource().getUri().toString();
    return uri;
  }
 
  /** Returns the element with the given name (case sensitive) or null. */
  public FormElement get(String nameOrId) {
    return find(byIdOrName(nameOrId));
  }
 
  public FormElement find(String csss) {
    for(FormElement element : elements)
      if(element.matches(csss))
        return element;
    return null;
  }
 
  @SuppressWarnings("unchecked")
  public <T> T find(String csss, Class<T> clazz) {
    for(FormElement element : elements) {
      if ((clazz==null || clazz.isInstance(element)) && element.matches(csss)) {
        return (T)element;
      }
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  private <T> T find(String csss, String value, Class<T> clazz) {
    for(FormElement element : elements) {
      if ((clazz==null || clazz.isInstance(element)) && element.matches(csss)) {
        if (value==null || value.equals(element.getValue())) {
          return (T)element;
        }
      }
    }
    return null;
  }
 
  @SuppressWarnings("unchecked")
  public <T> List<T> findAll(String csss, Class<T> clazz) {
    List<T> result = new ArrayList<T>();
    for(FormElement element : elements) {
      if ((clazz==null || clazz.isInstance(element)) && element.matches(csss)) {
        result.add((T)element);
      }
    }
    return result;
  }

  public Email findEmail(String csss) {
    return find(csss, Email.class);
  }

  public Select findSelect(String csss) {
    return find(csss, Select.class);
  }

  public Checkbox findCheckbox(String csss) {
    return find(csss, Checkbox.class);
  }

  public Search findSearch(String csss) {
    return find(csss, Search.class);
  }

  public SubmitImage findSubmitImage(String csss) {
    return find(csss, SubmitImage.class);
  }

  public Upload findUpload(String csss) {
    return find(csss, Upload.class);
  }

  public RadioButton findRadioButton(String csss) {
    return find(csss, RadioButton.class);
  }
 
  public Checkbox findCheckbox(String csss, String value) {
    return find(csss, value, Checkbox.class);
  }
 
  public RadioButton findRadioButton(String csss, String value) {
    return find(csss, value, RadioButton.class);
  }

  public TextArea findTextArea(String csss) {
    return find(csss, TextArea.class);
  }

  public SubmitButton findSubmitButton(String csss) {
    return find(csss, SubmitButton.class);
  }
 

  public Checkbox getCheckbox(String nameOrId, String value) {
    return get(nameOrId, value, Checkbox.class);
  }

  public RadioButton getRadioButton(String nameOrId) {
    return get(nameOrId, RadioButton.class);
  }
 
  public RadioButton getRadioButton(String nameOrId, String value) {
    return get(nameOrId, value, RadioButton.class);
  }
 
  public List<RadioButton> getRadioButtons(String nameOrId) {
    return getAll(nameOrId, RadioButton.class);
  }
 
  @SuppressWarnings("unchecked")
  private <T> T get(String nameOrId, Class<T> clazz) {
    for(FormElement element : elements)
      if(clazz.isInstance(element) && (nameOrId.equals(element.getName()) || nameOrId.equals(element.getId())))
        return (T)element;
    return null;
  }

  @SuppressWarnings("unchecked")
  private <T> T get(String nameOrId, String value, Class<T> clazz) {
    for(FormElement element : elements)
      if(clazz.isInstance(element) && (nameOrId.equals(element.getName()) || nameOrId.equals(element.getId()))
          && (value == element.getValue() || (value != null && value.equals(element.getValue()))))
        return (T)element;
    return null;
  }
 
  @SuppressWarnings("unchecked")
  private <T> List<T> getAll(String nameOrId, Class<T> clazz) {
    List<T> result = new ArrayList<T>();
    for(FormElement element : elements)
      if(clazz.isInstance(element) && (nameOrId.equals(element.getName()) || nameOrId.equals(element.getId())))
        result.add((T)element);
    return result;
  }
 
  public <T extends Resource> T submit() {
    return submit(this, composeParameters(null, null, 0, 0));
  }

  public <T extends Resource> T submit(SubmitButton button) {
    return submit(this, composeParameters(button, null, 0, 0));
  }

  public <T extends Resource> T submit(SubmitImage image, int x, int y) {
    return submit(this, composeParameters(null, image, x, y));
  }

  /** Returns the page object received as response to the form submit action. */
  @SuppressWarnings("unchecked")
  private <T extends Resource> T submit(Form form, Parameters parameters) {
    RequestBuilder<Resource> request = doRequest(form.getUri()).set(parameters);
    boolean doPost = form.isDoPost();
    boolean multiPart = form.isMultiPart();
    if(doPost && multiPart) {
      request.multiPart();
      addFiles(request, form);
    }
    return (T) (doPost ? request.post() : request.get());
  }

  private void addFiles(RequestBuilder<Resource> request, Form form) {
    for(FormElement formElement : form) {
      if(formElement instanceof Upload) {
        Upload upload = (Upload)formElement;
        if (upload.hasValue()) {
          File file = upload.hasFileValue() ? upload.getFileValue() : new File(upload.getValue());
          request.set(upload.getName(), file);         
        }
      }
    }
  }

  /** Returns the parameters containing all name value params beside submit button, image button, unchecked radio
   *  buttons and checkboxes and without Upload information. */
  private Parameters composeParameters(SubmitButton button, SubmitImage image, int x, int y) {
    Parameters params = new Parameters();
    for(FormElement element : this) {
      String name = element.getName();
      String value = element.getValue();
      if(element instanceof Checkable) {
        if(((Checkable)element).isChecked())
          params.add(name, value != null ? value : "");
      }
      else if(element instanceof Select) {
        Select select = (Select)element;
        for(Select.Option option : select.getOptions())
          if(option.isSelected())
            params.add(select.getName(), option.getValue() != null ? option.getValue() : "");
      }
      else if(!(element instanceof SubmitButton) && !(element instanceof SubmitImage) && !(element instanceof Upload)) {
        if(name != null)
          params.add(name, value != null ? value : "");
      }
    }
    if(button != null && button.getName() != null)
      params.add(button.getName(), button.getValue() != null ? button.getValue() : "");
    if(image != null) {
      if(image.getValue() != null && image.getValue().length() > 1)
        params.add(image.getName(), image.getValue());
      params.add(image.getName() + ".x", "" + x);
      params.add(image.getName() + ".y", "" + y);
    }
    return params;
  }
 
  public Iterator<FormElement> iterator() {
    return elements.iterator();
  }
}
TOP

Related Classes of com.gistlabs.mechanize.document.html.form.Form

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.