/* * Copyright 2001-2008 Geert Bevin <gbevin[remove] at uwyn dot com> * Licensed under the Apache License, Version 2.0 (the "License") * $Id: MockForm.java 3918 2008-04-14 17:35:35Z gbevin $ */ package com.uwyn.rife.test; import java.util.*; import com.uwyn.rife.engine.RequestMethod; import com.uwyn.rife.tools.ArrayUtils; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Corresponds to a form in a HTML document after it has been parsed with * {@link ParsedHtml#parse}. * * @author Geert Bevin (gbevin[remove] at uwyn dot com) * @version $Revision: 3918 $ * @since 1.1 */ public class MockForm { private MockResponse mResponse; private Node mNode; private Map<String, String[]> mParameters = new LinkedHashMap<String, String[]>(); private Map<String, MockFileUpload[]> mFiles = new LinkedHashMap<String, MockFileUpload[]>(); MockForm(MockResponse response, Node node) { assert node != null; mResponse = response; mNode = node; Stack<NodeList> node_lists = new Stack<NodeList>(); NodeList child_nodes = mNode.getChildNodes(); if (child_nodes != null && child_nodes.getLength() > 0) { node_lists.push(child_nodes); } while (node_lists.size() > 0) { child_nodes = node_lists.pop(); for (int i = 0; i < child_nodes.getLength(); i++) { Node child_node = child_nodes.item(i); String node_name = child_node.getNodeName(); String node_name_attribute = ParsedHtml.getNodeAttribute(child_node, "name", null); if (node_name_attribute != null) { if ("input".equals(node_name)) { String input_type = ParsedHtml.getNodeAttribute(child_node, "type", null); if (input_type != null) { String input_value = ParsedHtml.getNodeAttribute(child_node, "value", null); if ("text".equals(input_type) || "password".equals(input_type) || "hidden".equals(input_type)) { addParameterValue(node_name_attribute, input_value); } else { boolean input_checked = ParsedHtml.getNodeAttribute(child_node, "checked", null) != null; if (null == input_value) { input_value = "on"; } if ("checkbox".equals(input_type)) { if (input_checked) { addParameterValue(node_name_attribute, input_value); } } else if ("radio".equals(input_type)) { if (input_checked) { setParameter(node_name_attribute, input_value); } } } } } else if ("textarea".equals(node_name)) { String value = child_node.getTextContent(); addParameterValue(node_name_attribute, value); } else if ("select".equals(node_name)) { List<String> selected_options = new ArrayList<String>(); boolean select_multiple = ParsedHtml.getNodeAttribute(child_node, "multiple", null) != null; String first_option_value = null; // go over all the select child nodes to find the options tags NodeList select_child_nodes = child_node.getChildNodes(); for (int j = 0; j < select_child_nodes.getLength(); j++) { Node select_child_node = select_child_nodes.item(j); String select_node_name = select_child_node.getNodeName(); // process each select option if ("option".equals(select_node_name)) { // obtain the option value String option_value = ParsedHtml.getNodeAttribute(select_child_node, "value", null); if (null == option_value) { option_value = select_child_node.getTextContent(); } // remember the first option value if (null == first_option_value) { first_option_value = option_value; } // select the indicated options boolean option_selected = ParsedHtml.getNodeAttribute(select_child_node, "selected", null) != null; if (option_selected) { if (!select_multiple) { selected_options.clear(); } selected_options.add(option_value); } } } // if no options were selected and the select is not multiple, // the first option should be automatically selected if (0 == selected_options.size() && !select_multiple && select_child_nodes.getLength() > 0) { selected_options.add(first_option_value); } // add the selected values to the parameters for (String value : selected_options) { addParameterValue(node_name_attribute, value); } } } NodeList planned_child_nodes = child_node.getChildNodes(); if (planned_child_nodes != null && planned_child_nodes.getLength() > 0) { node_lists.push(planned_child_nodes); } } } } /** * Retrieves the DOM XML node that this form corresponds to. * * @return the corresponding DOM XML node * @since 1.0 */ public Node getNode() { return mNode; } /** * Creates a new {@link MockRequest} that contains the method, the * parameters and the files of this form. * * @return the created <code>MockRequest</code> * @since 1.0 */ public MockRequest getRequest() { return new MockRequest() .method(RequestMethod.getMethod(getMethod())) .parameters(mParameters) .files(mFiles); } /** * Submit this form with its current parameters and files; and returns the * response. * * @return the resulting {@link MockResponse} * @since 1.0 */ public MockResponse submit() { return mResponse.getMockConversation().doRequest(getAction(), getRequest()); } private void addParameterValue(String name, String value) { if (null == value) { value = ""; } String[] values = mParameters.get(name); if (null == values) { values = new String[] {value}; } else { values = ArrayUtils.join(values, value); } mParameters.put(name, values); } /** * Retrieves all the parameters of this form. * * @return a <code>Map</code> of the parameters with the names as the keys * and their value arrays as the values * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public Map<String, String[]> getParameters() { return mParameters; } /** * Retrieves all the parameter names of this form. * * @return a <code>Collection</code> of the parameter names * @see #getParameters * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public Collection<String> getParameterNames() { return mParameters.keySet(); } /** * Checks whether a named parameter is present in this form. * * @param name the name of the parameter to check * @return <code>true</code> if the parameter is present; or * <p><code>false</code> otherwise * @see #getParameters * @see #getParameterNames * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public boolean hasParameter(String name) { return mParameters.containsKey(name); } /** * Retrieves the first value of a parameter in this form. * * @param name the name of the parameter * @return the first value of the parameter; or * <p><code>null</code> if no such parameter could be found * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public String getParameterValue(String name) { String[] values = getParameterValues(name); if (null == values || 0 == values.length) { return null; } return values[0]; } /** * Retrieves the values of a parameter in this form. * * @param name the name of the parameter * @return the values of the parameter; or * <p><code>null</code> if no such parameter could be found * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public String[] getParameterValues(String name) { return mParameters.get(name); } /** * Sets a parameter in this form. * * @param name the name of the parameter * @param value the value of the parameter * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @since 1.1 */ public void setParameter(String name, String value) { if (null == name || null == value) { return; } mParameters.put(name, new String[] {value}); } /** * Sets a parameter in this form. * * @param name the name of the parameter * @param value the value of the parameter * @return this <code>MockForm</code> instance * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public MockForm parameter(String name, String value) { setParameter(name, value); return this; } /** * Sets a parameter in this form. * * @param name the name of the parameter * @param values the value array of the parameter * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String) * @since 1.1 */ public void setParameter(String name, String[] values) { if (null == name) { return; } if (null == values) { mParameters.remove(name); } else { mParameters.put(name, values); } } /** * Sets a parameter in this form. * * @param name the name of the parameter * @param values the value array of the parameter * @return this <code>MockForm</code> instance * @see #getParameters * @see #getParameterNames * @see #hasParameter * @see #getParameterValue * @see #getParameterValues * @see #setParameter(String, String[]) * @see #setParameter(String, String) * @since 1.1 */ public MockForm parameter(String name, String[] values) { setParameter(name, values); return this; } /** * Sets a file in this form. * * @param name the parameter name of the file * @param file the file specification that will be uploaded * @see #setFiles(String, MockFileUpload[]) * @since 1.1 */ public void setFile(String name, MockFileUpload file) { if (null == name || null == file) { return; } mFiles.put(name, new MockFileUpload[] {file}); } /** * Sets a file in this form. * * @param name the parameter name of the file * @param file the file specification that will be uploaded * @return this <code>MockForm</code> instance * @see #setFiles(String, MockFileUpload[]) * @since 1.1 */ public MockForm file(String name, MockFileUpload file) { setFile(name, file); return this; } /** * Sets files in this request. * * @param name the parameter name of the file * @param files the file specifications that will be uploaded * @see #setFile(String, MockFileUpload) * @since 1.1 */ public void setFiles(String name, MockFileUpload[] files) { if (null == name) { return; } if (null == files) { mFiles.remove(name); } else { mFiles.put(name, files); } } /** * Sets files in this request. * * @param name the parameter name of the file * @param files the file specifications that will be uploaded * @return this <code>MockForm</code> instance * @see #setFile(String, MockFileUpload) * @since 1.1 */ public MockForm files(String name, MockFileUpload[] files) { setFiles(name, files); return this; } /** * Retrieves the content of this form's <code>id</code> attribute. * * @return the content of the <code>id</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getId() { return getAttribute("id"); } /** * Retrieves the content of this form's <code>class</code> attribute. * * @return the content of the <code>class</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getClassName() { return getAttribute("class"); } /** * Retrieves the content of this form's <code>title</code> attribute. * * @return the content of the <code>title</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getTitle() { return getAttribute("title"); } /** * Retrieves the content of this form's <code>action</code> attribute. * * @return the content of the <code>action</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getAction() { return getAttribute("action"); } /** * Retrieves the content of this form's <code>method</code> attribute. * * @return the content of the <code>method</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getMethod() { return getAttribute("method"); } /** * Retrieves the content of this form's <code>name</code> attribute. * * @return the content of the <code>name</code> attribute; or * <p>null if no such attribute could be found * @since 1.0 */ public String getName() { return getAttribute("name"); } private String getAttribute(String attributeName) { return ParsedHtml.getNodeAttribute(mNode, attributeName, null); } }