// 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); } }