001: /*
002: * Copyright 2001-2007 Geert Bevin <gbevin[remove] at uwyn dot com>
003: * Distributed under the terms of either:
004: * - the common development and distribution license (CDDL), v1.0; or
005: * - the GNU Lesser General Public License, v2.1 or later
006: * $Id: MockForm.java 3634 2007-01-08 21:42:24Z gbevin $
007: */
008: package com.uwyn.rife.test;
009:
010: import java.util.*;
011:
012: import com.uwyn.rife.engine.RequestMethod;
013: import com.uwyn.rife.tools.ArrayUtils;
014: import org.w3c.dom.Node;
015: import org.w3c.dom.NodeList;
016:
017: /**
018: * Corresponds to a form in a HTML document after it has been parsed with
019: * {@link ParsedHtml#parse}.
020: *
021: * @author Geert Bevin (gbevin[remove] at uwyn dot com)
022: * @version $Revision: 3634 $
023: * @since 1.1
024: */
025: public class MockForm {
026: private MockResponse mResponse;
027: private Node mNode;
028: private Map<String, String[]> mParameters = new LinkedHashMap<String, String[]>();
029: private Map<String, MockFileUpload[]> mFiles = new LinkedHashMap<String, MockFileUpload[]>();
030:
031: MockForm(MockResponse response, Node node) {
032: assert node != null;
033:
034: mResponse = response;
035: mNode = node;
036:
037: Stack<NodeList> node_lists = new Stack<NodeList>();
038:
039: NodeList child_nodes = mNode.getChildNodes();
040: if (child_nodes != null && child_nodes.getLength() > 0) {
041: node_lists.push(child_nodes);
042: }
043:
044: while (node_lists.size() > 0) {
045: child_nodes = node_lists.pop();
046:
047: for (int i = 0; i < child_nodes.getLength(); i++) {
048: Node child_node = child_nodes.item(i);
049:
050: String node_name = child_node.getNodeName();
051: String node_name_attribute = ParsedHtml
052: .getNodeAttribute(child_node, "name", null);
053: if (node_name_attribute != null) {
054: if ("input".equals(node_name)) {
055: String input_type = ParsedHtml
056: .getNodeAttribute(child_node, "type",
057: null);
058: if (input_type != null) {
059: String input_value = ParsedHtml
060: .getNodeAttribute(child_node,
061: "value", null);
062: if ("text".equals(input_type)
063: || "password".equals(input_type)
064: || "hidden".equals(input_type)) {
065: addParameterValue(node_name_attribute,
066: input_value);
067: } else {
068: boolean input_checked = ParsedHtml
069: .getNodeAttribute(child_node,
070: "checked", null) != null;
071: if (null == input_value) {
072: input_value = "on";
073: }
074:
075: if ("checkbox".equals(input_type)) {
076: if (input_checked) {
077: addParameterValue(
078: node_name_attribute,
079: input_value);
080: }
081: } else if ("radio".equals(input_type)) {
082: if (input_checked) {
083: setParameter(
084: node_name_attribute,
085: input_value);
086: }
087: }
088: }
089: }
090: } else if ("textarea".equals(node_name)) {
091: String value = child_node.getTextContent();
092: addParameterValue(node_name_attribute, value);
093: } else if ("select".equals(node_name)) {
094: List<String> selected_options = new ArrayList<String>();
095:
096: boolean select_multiple = ParsedHtml
097: .getNodeAttribute(child_node,
098: "multiple", null) != null;
099:
100: String first_option_value = null;
101:
102: // go over all the select child nodes to find the options tags
103: NodeList select_child_nodes = child_node
104: .getChildNodes();
105: for (int j = 0; j < select_child_nodes
106: .getLength(); j++) {
107: Node select_child_node = select_child_nodes
108: .item(j);
109: String select_node_name = select_child_node
110: .getNodeName();
111:
112: // process each select option
113: if ("option".equals(select_node_name)) {
114: // obtain the option value
115: String option_value = ParsedHtml
116: .getNodeAttribute(
117: select_child_node,
118: "value", null);
119: if (null == option_value) {
120: option_value = select_child_node
121: .getTextContent();
122: }
123:
124: // remember the first option value
125: if (null == first_option_value) {
126: first_option_value = option_value;
127: }
128:
129: // select the indicated options
130: boolean option_selected = ParsedHtml
131: .getNodeAttribute(
132: select_child_node,
133: "selected", null) != null;
134: if (option_selected) {
135: if (!select_multiple) {
136: selected_options.clear();
137: }
138:
139: selected_options.add(option_value);
140: }
141: }
142: }
143:
144: // if no options were selected and the select is not multiple,
145: // the first option should be automatically selected
146: if (0 == selected_options.size()
147: && !select_multiple
148: && select_child_nodes.getLength() > 0) {
149: selected_options.add(first_option_value);
150: }
151:
152: // add the selected values to the parameters
153: for (String value : selected_options) {
154: addParameterValue(node_name_attribute,
155: value);
156: }
157: }
158: }
159:
160: NodeList planned_child_nodes = child_node
161: .getChildNodes();
162: if (planned_child_nodes != null
163: && planned_child_nodes.getLength() > 0) {
164: node_lists.push(planned_child_nodes);
165: }
166: }
167: }
168: }
169:
170: /**
171: * Retrieves the DOM XML node that this form corresponds to.
172: *
173: * @return the corresponding DOM XML node
174: * @since 1.0
175: */
176: public Node getNode() {
177: return mNode;
178: }
179:
180: /**
181: * Creates a new {@link MockRequest} that contains the method, the
182: * parameters and the files of this form.
183: *
184: * @return the created <code>MockRequest</code>
185: * @since 1.0
186: */
187: public MockRequest getRequest() {
188: return new MockRequest().method(
189: RequestMethod.getMethod(getMethod())).parameters(
190: mParameters).files(mFiles);
191: }
192:
193: /**
194: * Submit this form with its current parameters and files; and returns the
195: * response.
196: *
197: * @return the resulting {@link MockResponse}
198: * @since 1.0
199: */
200: public MockResponse submit() {
201: return mResponse.getMockConversation().doRequest(getAction(),
202: getRequest());
203: }
204:
205: private void addParameterValue(String name, String value) {
206: if (null == value) {
207: value = "";
208: }
209:
210: String[] values = mParameters.get(name);
211: if (null == values) {
212: values = new String[] { value };
213: } else {
214: values = ArrayUtils.join(values, value);
215: }
216:
217: mParameters.put(name, values);
218: }
219:
220: /**
221: * Retrieves all the parameters of this form.
222: *
223: * @return a <code>Map</code> of the parameters with the names as the keys
224: * and their value arrays as the values
225: * @see #getParameterNames
226: * @see #hasParameter
227: * @see #getParameterValue
228: * @see #getParameterValues
229: * @see #setParameter(String, String[])
230: * @see #setParameter(String, String)
231: * @since 1.1
232: */
233: public Map<String, String[]> getParameters() {
234: return mParameters;
235: }
236:
237: /**
238: * Retrieves all the parameter names of this form.
239: *
240: * @return a <code>Collection</code> of the parameter names
241: * @see #getParameters
242: * @see #hasParameter
243: * @see #getParameterValue
244: * @see #getParameterValues
245: * @see #setParameter(String, String[])
246: * @see #setParameter(String, String)
247: * @since 1.1
248: */
249: public Collection<String> getParameterNames() {
250: return mParameters.keySet();
251: }
252:
253: /**
254: * Checks whether a named parameter is present in this form.
255: *
256: * @param name the name of the parameter to check
257: * @return <code>true</code> if the parameter is present; or
258: * <p><code>false</code> otherwise
259: * @see #getParameters
260: * @see #getParameterNames
261: * @see #getParameterValue
262: * @see #getParameterValues
263: * @see #setParameter(String, String[])
264: * @see #setParameter(String, String)
265: * @since 1.1
266: */
267: public boolean hasParameter(String name) {
268: return mParameters.containsKey(name);
269: }
270:
271: /**
272: * Retrieves the first value of a parameter in this form.
273: *
274: * @param name the name of the parameter
275: * @return the first value of the parameter; or
276: * <p><code>null</code> if no such parameter could be found
277: * @see #getParameters
278: * @see #getParameterNames
279: * @see #hasParameter
280: * @see #getParameterValues
281: * @see #setParameter(String, String[])
282: * @see #setParameter(String, String)
283: * @since 1.1
284: */
285: public String getParameterValue(String name) {
286: String[] values = getParameterValues(name);
287: if (null == values || 0 == values.length) {
288: return null;
289: }
290:
291: return values[0];
292: }
293:
294: /**
295: * Retrieves the values of a parameter in this form.
296: *
297: * @param name the name of the parameter
298: * @return the values of the parameter; or
299: * <p><code>null</code> if no such parameter could be found
300: * @see #getParameters
301: * @see #getParameterNames
302: * @see #hasParameter
303: * @see #getParameterValue
304: * @see #setParameter(String, String[])
305: * @see #setParameter(String, String)
306: * @since 1.1
307: */
308: public String[] getParameterValues(String name) {
309: return mParameters.get(name);
310: }
311:
312: /**
313: * Sets a parameter in this form.
314: *
315: * @param name the name of the parameter
316: * @param value the value of the parameter
317: * @see #getParameters
318: * @see #getParameterNames
319: * @see #hasParameter
320: * @see #getParameterValue
321: * @see #getParameterValues
322: * @see #setParameter(String, String[])
323: * @since 1.1
324: */
325: public void setParameter(String name, String value) {
326: if (null == name || null == value) {
327: return;
328: }
329:
330: mParameters.put(name, new String[] { value });
331: }
332:
333: /**
334: * Sets a parameter in this form.
335: *
336: * @param name the name of the parameter
337: * @param value the value of the parameter
338: * @return this <code>MockForm</code> instance
339: * @see #getParameters
340: * @see #getParameterNames
341: * @see #hasParameter
342: * @see #getParameterValue
343: * @see #getParameterValues
344: * @see #setParameter(String, String[])
345: * @see #setParameter(String, String)
346: * @since 1.1
347: */
348: public MockForm parameter(String name, String value) {
349: setParameter(name, value);
350:
351: return this ;
352: }
353:
354: /**
355: * Sets a parameter in this form.
356: *
357: * @param name the name of the parameter
358: * @param values the value array of the parameter
359: * @see #getParameters
360: * @see #getParameterNames
361: * @see #hasParameter
362: * @see #getParameterValue
363: * @see #getParameterValues
364: * @see #setParameter(String, String)
365: * @since 1.1
366: */
367: public void setParameter(String name, String[] values) {
368: if (null == name) {
369: return;
370: }
371:
372: if (null == values) {
373: mParameters.remove(name);
374: } else {
375: mParameters.put(name, values);
376: }
377: }
378:
379: /**
380: * Sets a parameter in this form.
381: *
382: * @param name the name of the parameter
383: * @param values the value array of the parameter
384: * @return this <code>MockForm</code> instance
385: * @see #getParameters
386: * @see #getParameterNames
387: * @see #hasParameter
388: * @see #getParameterValue
389: * @see #getParameterValues
390: * @see #setParameter(String, String[])
391: * @see #setParameter(String, String)
392: * @since 1.1
393: */
394: public MockForm parameter(String name, String[] values) {
395: setParameter(name, values);
396:
397: return this ;
398: }
399:
400: /**
401: * Sets a file in this form.
402: *
403: * @param name the parameter name of the file
404: * @param file the file specification that will be uploaded
405: * @see #setFiles(String, MockFileUpload[])
406: * @since 1.1
407: */
408: public void setFile(String name, MockFileUpload file) {
409: if (null == name || null == file) {
410: return;
411: }
412:
413: mFiles.put(name, new MockFileUpload[] { file });
414: }
415:
416: /**
417: * Sets a file in this form.
418: *
419: * @param name the parameter name of the file
420: * @param file the file specification that will be uploaded
421: * @return this <code>MockForm</code> instance
422: * @see #setFiles(String, MockFileUpload[])
423: * @since 1.1
424: */
425: public MockForm file(String name, MockFileUpload file) {
426: setFile(name, file);
427:
428: return this ;
429: }
430:
431: /**
432: * Sets files in this request.
433: *
434: * @param name the parameter name of the file
435: * @param files the file specifications that will be uploaded
436: * @see #setFile(String, MockFileUpload)
437: * @since 1.1
438: */
439: public void setFiles(String name, MockFileUpload[] files) {
440: if (null == name) {
441: return;
442: }
443:
444: if (null == files) {
445: mFiles.remove(name);
446: } else {
447: mFiles.put(name, files);
448: }
449: }
450:
451: /**
452: * Sets files in this request.
453: *
454: * @param name the parameter name of the file
455: * @param files the file specifications that will be uploaded
456: * @return this <code>MockForm</code> instance
457: * @see #setFile(String, MockFileUpload)
458: * @since 1.1
459: */
460: public MockForm files(String name, MockFileUpload[] files) {
461: setFiles(name, files);
462:
463: return this ;
464: }
465:
466: /**
467: * Retrieves the content of this form's <code>id</code> attribute.
468: *
469: * @return the content of the <code>id</code> attribute; or
470: * <p>null if no such attribute could be found
471: * @since 1.0
472: */
473: public String getId() {
474: return getAttribute("id");
475: }
476:
477: /**
478: * Retrieves the content of this form's <code>class</code> attribute.
479: *
480: * @return the content of the <code>class</code> attribute; or
481: * <p>null if no such attribute could be found
482: * @since 1.0
483: */
484: public String getClassName() {
485: return getAttribute("class");
486: }
487:
488: /**
489: * Retrieves the content of this form's <code>title</code> attribute.
490: *
491: * @return the content of the <code>title</code> attribute; or
492: * <p>null if no such attribute could be found
493: * @since 1.0
494: */
495: public String getTitle() {
496: return getAttribute("title");
497: }
498:
499: /**
500: * Retrieves the content of this form's <code>action</code> attribute.
501: *
502: * @return the content of the <code>action</code> attribute; or
503: * <p>null if no such attribute could be found
504: * @since 1.0
505: */
506: public String getAction() {
507: return getAttribute("action");
508: }
509:
510: /**
511: * Retrieves the content of this form's <code>method</code> attribute.
512: *
513: * @return the content of the <code>method</code> attribute; or
514: * <p>null if no such attribute could be found
515: * @since 1.0
516: */
517: public String getMethod() {
518: return getAttribute("method");
519: }
520:
521: /**
522: * Retrieves the content of this form's <code>name</code> attribute.
523: *
524: * @return the content of the <code>name</code> attribute; or
525: * <p>null if no such attribute could be found
526: * @since 1.0
527: */
528: public String getName() {
529: return getAttribute("name");
530: }
531:
532: private String getAttribute(String attributeName) {
533: return ParsedHtml.getNodeAttribute(mNode, attributeName, null);
534: }
535: }
|