⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 formcontrol.java

📁 HTML解析器是一个Java库
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
// Jericho HTML Parser - Java based library for analysing and manipulating HTML
// Version 3.0
// Copyright (C) 2007 Martin Jericho
// http://jerichohtml.sourceforge.net/
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of either one of the following licences:
//
// 1. The Eclipse Public License (EPL) version 1.0,
// included in this distribution in the file licence-epl-1.0.html
// or available at http://www.eclipse.org/legal/epl-v10.html
//
// 2. The GNU Lesser General Public License (LGPL) version 2.1 or later,
// included in this distribution in the file licence-lgpl-2.1.txt
// or available at http://www.gnu.org/licenses/lgpl.txt
//
// This library is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied.
// See the individual licence texts for more details.

package net.htmlparser.jericho;

import java.util.*;
import java.io.*;

/**
 * Represents an HTML form <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#form-controls">control</a>.
 * <p>
 * A <code>FormControl</code> consists of a single {@linkplain #getElement() element}
 * that matches one of the {@linkplain FormControlType form control types}.
 * <p>
 * The term <i><a name="OutputElement">output element</a></i> is used to describe the element that is
 * {@linkplain OutputSegment#writeTo(Writer) output} if this form control is {@linkplain OutputDocument#replace(FormControl) replaced}
 * in an {@link OutputDocument}.
 * <p>
 * A <i><a name="PredefinedValueControl">predefined value control</a></i> is a form control for which
 * {@link #getFormControlType()}.{@link FormControlType#hasPredefinedValue() hasPredefinedValue()}
 * returns <code>true</code>.  It has a {@linkplain #getFormControlType() control type} of
 * {@link FormControlType#CHECKBOX CHECKBOX}, {@link FormControlType#RADIO RADIO}, {@link FormControlType#BUTTON BUTTON},
 * {@link FormControlType#SUBMIT SUBMIT}, {@link FormControlType#IMAGE IMAGE}, {@link FormControlType#SELECT_SINGLE SELECT_SINGLE}
 * or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
 * <p>
 * A <i><a name="UserValueControl">user value control</a></i> is a form control for which
 * {@link #getFormControlType()}.{@link FormControlType#hasPredefinedValue() hasPredefinedValue()}
 * returns <code>false</code>.  It has a {@linkplain #getFormControlType() control type} of
 * {@link FormControlType#FILE FILE}, {@link FormControlType#HIDDEN HIDDEN}, {@link FormControlType#PASSWORD PASSWORD},
 * {@link FormControlType#TEXT TEXT} or {@link FormControlType#TEXTAREA TEXTAREA}.
 * <p>
 * The functionality of most significance to users of this class relates to the
 * <i><a name="DisplayCharacteristics">display characteristics</a></i> of the <a href="#OutputElement">output element</a>,
 * manipulated using the {@link #setDisabled(boolean)} and {@link #setOutputStyle(FormControlOutputStyle)} methods.
 * <p>
 * As a general rule, the operations dealing with the control's <a href="#SubmissionValue">submission values</a>
 * are better performed on a {@link FormFields} or {@link FormField} object, which provide a more
 * intuitive interface by grouping form controls of the same {@linkplain #getName() name} together.
 * The higher abstraction level of these classes means they can automatically ensure that the
 * <a href="#SubmissionValue">submission values</a> of their constituent controls are consistent with each other,
 * for example by ensuring that only one {@link FormControlType#RADIO RADIO} control with a given name is
 * {@link #isChecked() checked} at a time.
 * <p>
 * A {@link FormFields} object can be directly {@linkplain FormFields#FormFields(Collection) constructed} from
 * a collection of <code>FormControl</code> objects.
 * <p>
 * <code>FormControl</code> instances are obtained using the {@link Element#getFormControl()} method or are created automatically
 * with the creation of a {@link FormFields} object via the {@link Segment#getFormFields()} method.
 *
 * @see FormControlType
 * @see FormFields
 * @see FormField
 */
public abstract class FormControl extends Segment {
	FormControlType formControlType;
	String name;
	ElementContainer elementContainer;
	FormControlOutputStyle outputStyle=FormControlOutputStyle.NORMAL;

	private static final String CHECKBOX_NULL_DEFAULT_VALUE="on";
	private static Comparator<FormControl> COMPARATOR=new PositionComparator();

	static FormControl construct(final Element element) {
		final String tagName=element.getStartTag().getName();
		if (tagName==HTMLElementName.INPUT) {
			final String typeAttributeValue=element.getAttributes().getRawValue(Attribute.TYPE);
			if (typeAttributeValue==null) return new InputFormControl(element,FormControlType.TEXT);
			FormControlType formControlType=FormControlType.getFromInputElementType(typeAttributeValue);
			if (formControlType==null) {
				if (formControlType.isNonFormControl(typeAttributeValue)) return null;
				if (element.source.logger.isInfoEnabled()) element.source.logger.info(element.source.getRowColumnVector(element.begin).appendTo(new StringBuilder(200)).append(": INPUT control with unrecognised type \"").append(typeAttributeValue).append("\" assumed to be type \"text\"").toString());
				formControlType=FormControlType.TEXT;
			}
			switch (formControlType) {
				case TEXT:
					return new InputFormControl(element,formControlType);
				case CHECKBOX: case RADIO:
					return new RadioCheckboxFormControl(element,formControlType);
				case SUBMIT:
					return new SubmitFormControl(element,formControlType);
				case IMAGE:
					return new ImageSubmitFormControl(element);
				case HIDDEN: case PASSWORD: case FILE:
					return new InputFormControl(element,formControlType);
				default:
					throw new AssertionError(formControlType);
			}
		} else if (tagName==HTMLElementName.SELECT) {
			return new SelectFormControl(element);
		} else if (tagName==HTMLElementName.TEXTAREA) {
			return new TextAreaFormControl(element);
		} else if (tagName==HTMLElementName.BUTTON) {
			return "submit".equalsIgnoreCase(element.getAttributes().getRawValue(Attribute.TYPE)) ? new SubmitFormControl(element,FormControlType.BUTTON) : null;
		} else {
			return null;
		}
	}

	private FormControl(final Element element, final FormControlType formControlType, final boolean loadPredefinedValue) {
		super(element.source,element.begin,element.end);
		elementContainer=new ElementContainer(element,loadPredefinedValue);
		this.formControlType=formControlType;
		name=element.getAttributes().getValue(Attribute.NAME);
		verifyName();
	}

	/**
	 * Returns the {@linkplain FormControlType type} of this form control.
	 * @return the {@linkplain FormControlType type} of this form control.
	 */
	public final FormControlType getFormControlType() {
		return formControlType;
	}

	/**
	 * Returns the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#control-name">name</a> of the control.
	 * <p>
	 * The name comes from the value of the <code>name</code> {@linkplain Attribute attribute} of the
	 * {@linkplain #getElement() form control's element}, not the {@linkplain Element#getName() name of the element} itself.
	 * <p>
	 * Since a {@link FormField} is simply a group of controls with the same name, the terms <i>control name</i> and
	 * <i>field name</i> are for the most part synonymous, with only a possible difference in case differentiating them.
	 * <p>
	 * In contrast to the {@link FormField#getName()} method, this method always returns the name using the original case
	 * from the source document, regardless of the current setting of the static
	 * {@link Config#CurrentCompatibilityMode}<code>.</code>{@link Config.CompatibilityMode#isFormFieldNameCaseInsensitive() FormFieldNameCaseInsensitive} property.
	 *
	 * @return the <a target="_blank" href="http://www.w3.org/TR/html401/interact/forms.html#control-name">name</a> of the control.
	 */
	public final String getName() {
		return name;
	}

	/**
	 * Returns the {@linkplain Element element} representing this form control in the source document.
	 * <p>
	 * The {@linkplain Element#getAttributes() attributes} of this source element should correspond with the
	 * <a href="#OutputAttributes">output attributes</a> if the
	 * <a href="#DisplayCharacteristics">display characteristics</a> or <a href="FormField.html#SubmissionValue">submission values</a>
	 * have not been modified.
	 *
	 * @return the {@linkplain Element element} representing this form control in the source document.
	 */
	public final Element getElement() {
		return elementContainer.element;
	}

	/**
	 * Returns an iterator over the {@link HTMLElementName#OPTION OPTION} {@linkplain Element elements} contained within this control, in order of appearance.
	 * <p>
	 * This method is only relevant to form controls with a {@linkplain #getFormControlType() type} of 
	 * {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
	 *
	 * @return an iterator over the {@link HTMLElementName#OPTION OPTION} {@linkplain Element elements} contained within this control, in order of appearance.
	 * @throws UnsupportedOperationException if the {@linkplain #getFormControlType() type} of this control is not {@link FormControlType#SELECT_SINGLE SELECT_SINGLE} or {@link FormControlType#SELECT_MULTIPLE SELECT_MULTIPLE}.
	 */
	public Iterator<Element> getOptionElementIterator() {
		// overridden in SelectFormControl
		throw new UnsupportedOperationException("Only SELECT controls contain OPTION elements");
	}

	/**
	 * Returns the current {@linkplain FormControlOutputStyle output style} of this form control.
	 * <p>
	 * This property affects how this form control is displayed if it has been {@linkplain OutputDocument#replace(FormControl) replaced}
	 * in an {@link OutputDocument}.
	 * See the documentation of the {@link FormControlOutputStyle} class for information on the available output styles.
	 * <p>
	 * The default output style for every form control is {@link FormControlOutputStyle#NORMAL}.
	 *
	 * @return the current {@linkplain FormControlOutputStyle output style} of this form control.
	 * @see #setOutputStyle(FormControlOutputStyle)
	 */
	public FormControlOutputStyle getOutputStyle() {
		return outputStyle;
	}

	/**
	 * Sets the {@linkplain FormControlOutputStyle output style} of this form control.
	 * <p>
	 * See the {@link #getOutputStyle()} method for a full description of this property.
	 *
	 * @param outputStyle  the new {@linkplain FormControlOutputStyle output style} of this form control.
	 */
	public void setOutputStyle(final FormControlOutputStyle outputStyle) {
		this.outputStyle=outputStyle;
	}

	/**
	 * Returns a map of the names and values of this form control's <a href="#OutputAttributes">output attributes</a>.
	 * <p>
	 * The term <i><a name="OutputAttributes">output attributes</a></i> is used in this library to refer to the
	 * <a target="_blank" href="http://www.w3.org/TR/html401/intro/sgmltut.html#h-3.2.2">attributes</a> of a form control's
	 * <a href="#OutputElement">output element</a>.
	 * <p>
	 * The map keys are the <code>String</code> attribute names, which should all be in lower case.
	 * The map values are the corresponding <code>String</code> attribute values, with a <code>null</code> value given
	 * to an attribute that {@linkplain Attribute#hasValue() has no value}.
	 * <p>
	 * Direct manipulation of the returned map affects the attributes of this form control's <a href="#OutputElement">output element</a>.
	 * It is the responsibility of the user to ensure that all entries added to the map use the correct key and value types,
	 * and that all keys (attribute names) are in lower case.
	 * <p>
	 * It is recommended that the <a href="#SubmissionValueModificationMethods">submission value modification methods</a>
	 * are used to modify attributes that affect the <a href="#SubmissionValue">submission value</a> of the control
	 * rather than manipulating the attributes map directly.
	 * <p>
	 * An iteration over the map entries will return the attributes in the same order as they appeared in the source document, or
	 * at the end if the attribute was not present in the source document.
	 * <p>
	 * The returned attributes only correspond with those of the {@linkplain #getElement() source element} if the control's
	 * <a href="#DisplayCharacteristics">display characteristics</a> and <a href="#SubmissionValue">submission values</a>
	 * have not been modified.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -