// Jericho HTML Parser - Java based library for analysing and manipulating HTML
// Version 3.2
// Copyright (C) 2004-2009 Martin Jericho
// http://jericho.htmlparser.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.*;
/**
* Defines the syntax for an end tag type.
* <p>
* An end tag type is a {@link TagType} that {@linkplain #getStartDelimiter() starts} with the characters '<code></</code>'.
* <p>
* The singleton instances of all the <a href="TagType.html#Standard">standard</a> end tag types are available in this class as static
* <a href="#field_summary">fields</a>.
* <p>
* Because all <code>EndTagType</code> instaces must be singletons, the '<code>==</code>' operator can be used to test for a particular tag type
* instead of the <code>equals(Object)</code> method.
*
* @see StartTagType
*/
public abstract class EndTagType extends TagType {
static final String START_DELIMITER_PREFIX="</";
/**
* The tag type given to an {@linkplain Tag#isUnregistered() unregistered} {@linkplain EndTag end tag} (<code></<var> ... </var>></code>).
* <p>
* See the documentation of the {@link Tag#isUnregistered()} method for details.
* <p>
* <dl>
* <dt>Properties:</dt>
* <dd>
* <table class="bordered" style="margin: 15px" cellspacing="0">
* <tr><th>Property/Method<th>Value
* <tr><td>{@link #getDescription() Description}<td>/unregistered
* <tr><td>{@link #getStartDelimiter() StartDelimiter}<td><code></</code>
* <tr><td>{@link #getClosingDelimiter() ClosingDelimiter}<td><code>></code>
* <tr><td>{@link #isServerTag() IsServerTag}<td><code>false</code>
* <tr><td>{@link #getNamePrefix() NamePrefix}<td><i>(empty string)</i>
* <tr><td>{@link #getCorrespondingStartTagType() CorrespondingStartTagType}<td><code>null</code>
* <tr><td>{@link #generateHTML(String) generateHTML}<code>("<var>StartTagName</var>")</code><td><code></<var>StartTagName</var>></code>
* </table>
* <dt>Example:</dt>
* <dd><code></ "This is not recognised as any of the predefined end tag types in this library"></code></dd>
* </dl>
* @see StartTagType#UNREGISTERED
*/
public static final EndTagType UNREGISTERED=EndTagTypeUnregistered.INSTANCE;
/**
* The tag type given to a normal HTML or XML {@linkplain EndTag end tag} (<code></<var>name</var>></code>).
* <p>
* <dl>
* <dt>Properties:</dt>
* <dd>
* <table class="bordered" style="margin: 15px" cellspacing="0">
* <tr><th>Property/Method<th>Value
* <tr><td>{@link #getDescription() Description}<td>/normal
* <tr><td>{@link #getStartDelimiter() StartDelimiter}<td><code></</code>
* <tr><td>{@link #getClosingDelimiter() ClosingDelimiter}<td><code>></code>
* <tr><td>{@link #isServerTag() IsServerTag}<td><code>false</code>
* <tr><td>{@link #getNamePrefix() NamePrefix}<td><i>(empty string)</i>
* <tr><td>{@link #getCorrespondingStartTagType() CorrespondingStartTagType}<td>{@link StartTagType#NORMAL}
* <tr><td>{@link #generateHTML(String) generateHTML}<code>("<var>StartTagName</var>")</code><td><code></<var>StartTagName</var>></code>
* </table>
* <dt>Example:</dt>
* <dd><code></div></code></dd>
* </dl>
*/
public static final EndTagType NORMAL=EndTagTypeNormal.INSTANCE;
/**
* Constructs a new <code>EndTagType</code> object with the specified properties.
* <br />(<a href="TagType.html#ImplementationAssistance">implementation assistance</a> method)
* <p>
* As <code>EndTagType</code> is an abstract class, this constructor is only called from sub-class constructors.
*
* @param description a {@linkplain #getDescription() description} of the new end tag type useful for debugging purposes.
* @param startDelimiter the {@linkplain #getStartDelimiter() start delimiter} of the new end tag type.
* @param closingDelimiter the {@linkplain #getClosingDelimiter() closing delimiter} of the new end tag type.
* @param isServerTag indicates whether the new end tag type is a {@linkplain #isServerTag() server tag}.
*/
protected EndTagType(final String description, final String startDelimiter, final String closingDelimiter, final boolean isServerTag) {
super(description,startDelimiter.toLowerCase(),closingDelimiter,isServerTag,START_DELIMITER_PREFIX);
if (!getStartDelimiter().startsWith(START_DELIMITER_PREFIX)) throw new IllegalArgumentException("startDelimiter of an end tag must start with \""+START_DELIMITER_PREFIX+'"');
}
/**
* Returns the {@linkplain StartTagType type} of {@linkplain StartTag start tag} that is <i>usually</i> paired with an
* {@linkplain EndTag end tag} of this type to form an {@link Element}.
* <br />(<a href="TagType.html#DefaultImplementation">default implementation</a> method)
* <p>
* The default implementation returns <code>null</code>.
* <p>
* This property is informational only and is not used by the parser in any way.
* <p>
* The mapping of end tag type to the corresponding start tag type is in any case one-to-many, which is why the definition
* emphasises the word "usually".
* An example of this is the {@link PHPTagTypes#PHP_SCRIPT} start tag type,
* whose {@linkplain StartTagType#getCorrespondingEndTagType() corresponding end tag type} is {@link #NORMAL EndTagType.NORMAL},
* while the converse is not true.
* <p>
* The only <a href="TagType.html#Predefined">predefined</a> end tag type that returns <code>null</code> for this property is the
* special {@link #UNREGISTERED} end tag type.
* <p>
* Although this method is used like a <a href="TagType.html#Property">property</a> method, it is implemented as a
* <a href="TagType.html#DefaultImplementation">default implementation</a> method to avoid cyclic references between statically
* instantiated {@link StartTagType} and <code>EndTagType</code> objects.
* <p>
* <dl>
* <dt>Standard Tag Type Values:</dt>
* <dd>
* <table class="bordered" style="margin: 15px" cellspacing="0">
* <tr><th>End Tag Type<th>Corresponding Start Tag Type
* <tr><td>{@link EndTagType#UNREGISTERED}<td><code>null</code>
* <tr><td>{@link EndTagType#NORMAL}<td>{@link StartTagType#NORMAL}
* </table>
* </dl>
* <dl>
* <dt>Extended Tag Type Values:</dt>
* <dd>
* <table class="bordered" style="margin: 15px" cellspacing="0">
* <tr><th>End Tag Type<th>Corresponding Start Tag Type
* <tr><td>{@link MasonTagTypes#MASON_COMPONENT_CALLED_WITH_CONTENT_END}<td>{@link MasonTagTypes#MASON_COMPONENT_CALLED_WITH_CONTENT}
* <tr><td>{@link MasonTagTypes#MASON_NAMED_BLOCK_END}<td>{@link MasonTagTypes#MASON_NAMED_BLOCK}
* </table>
* </dl>
*
* @return the {@linkplain StartTagType type} of {@linkplain StartTag start tag} that is <i>usually</i> paired with an {@linkplain EndTag end tag} of this type to form an {@link Element}.
* @see StartTagType#getCorrespondingEndTagType()
*/
public StartTagType getCorrespondingStartTagType() {
return null;
}
/**
* Returns the end tag {@linkplain EndTag#getName() name} that is required to match a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag} with the specified {@linkplain StartTag#getName() name}.
* <br />(<a href="TagType.html#Property">property</a> method)
* <p>
* This default implementation simply returns <code>startTagName</code>.
* <p>
* Note that the <code>startTagName</code> parameter should include the start tag's {@linkplain TagType#getNamePrefix() name prefix} if it has one.
*
* @param startTagName the {@linkplain StartTag#getName() name} of a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag}, including its {@linkplain TagType#getNamePrefix() name prefix}.
* @return the end tag {@linkplain EndTag#getName() name} that is required to match a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag} with the specified {@linkplain StartTag#getName() name}.
*/
public String getEndTagName(final String startTagName) {
return startTagName;
}
/**
* Generates the HTML text of an {@linkplain EndTag end tag} of this type given the {@linkplain StartTag#getName() name} of a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag}.
* <br />(<a href="TagType.html#Property">property</a> method)
* <p>
* This default implementation returns <code>"</"+</code>{@link #getEndTagName(String) getEndTagName}<code>(startTagName)+</code>{@link #getClosingDelimiter()}.
* <p>
* Note that the <code>startTagName</code> parameter should include the start tag's {@linkplain TagType#getNamePrefix() name prefix} if it has one.
*
* @param startTagName the {@linkplain StartTag#getName() name} of a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag}, including its {@linkplain TagType#getNamePrefix() name prefix}.
* @return the HTML text of an {@linkplain EndTag end tag} of this type given the {@linkplain StartTag#getName() name} of a {@linkplain #getCorrespondingStartTagType() corresponding} {@linkplain StartTag start tag}.
*/
public String generateHTML(final String startTagName) {
return START_DELIMITER_PREFIX+getEndTagName(startTagName)+getClosingDelimiter();
}
/**
* Internal method for the construction of an {@link EndTag} object of this type.
* <br />(<a href="TagType.html#ImplementationAssistance">implementation assistance</a> method)
* <p>
* Intended for use from within the {@link #constructTagAt(Source,int) constructTagAt(Source, int pos)} method.
*
* @param source the {@link Source} document.
* @param begin the character position in the source document where this tag {@linkplain Segment#getBegin() begins}.
* @param end the character position in the source document where this tag {@linkplain Segment#getEnd() ends}.
* @param name the {@linkplain Tag#getName() name} of the tag.
* @return the new {@link EndTag} object.
*/
protected final EndTag constructEndTag(final Source source, final int begin, final int end, final String name) {
return new EndTag(source,begin,end,this,name);
}
}