1993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira/** 2993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Copyright (c) 2004, Google Inc. 3993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 4993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Licensed under the Apache License, Version 2.0 (the "License"); 5993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * you may not use this file except in compliance with the License. 6993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * You may obtain a copy of the License at 7993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 8993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * http://www.apache.org/licenses/LICENSE-2.0 9993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 10993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Unless required by applicable law or agreed to in writing, software 11993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * distributed under the License is distributed on an "AS IS" BASIS, 12993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * See the License for the specific language governing permissions and 14993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * limitations under the License. 15993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 16993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 171bdbfefe4b144c7b031a1d9242a0fa061a0ae6b5Scott Kennedypackage com.google.android.mail.common.html.parser; 18993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 191bdbfefe4b144c7b031a1d9242a0fa061a0ae6b5Scott Kennedyimport com.google.android.mail.common.base.Preconditions; 20993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 21993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereiraimport java.util.Set; 22993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 23993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira/** 24993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * HTML class defines Element and Attribute classes. 25993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 26993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @author jlim@google.com (Jing Yee Lim) 27993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 28993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereirapublic final class HTML { 29993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 30993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 31993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Html element 32993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 33993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final class Element { 34993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 35993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira // TODO(ptucker) other candidate types are list and form elements. Better for this to be 36993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira // enumerated type. 37993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Types */ 38993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int NO_TYPE = 0; 39993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int TABLE_TYPE = 1; 40993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 41993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 42993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * INLINE - charater level elements and text strings 43993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * BLOCK - block-like elements; e.g., paragraphs and lists 44993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * NONE - everything else 45993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 46993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public enum Flow { 47993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira INLINE, 48993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira BLOCK, 49993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira NONE 50993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 51993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 52993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final String name; 53993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final int type; 54993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final boolean empty; 55993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final boolean optionalEndTag; 56993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final boolean breaksFlow; 57993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final Flow flow; 58993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 59993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 60993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Construct an Element. 61993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 62993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * NOTE: Even though breaksFlow and flow are named similarly, they're not quite the same thing. 63993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Flow refers to whether the element is inherently character or block level. Breaks flow 64993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * refers to whether it forces a line break. 65993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 66993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @throws IllegalArgumentException if name or flow is null. 67993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 68993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Element(String name, int type, boolean empty, 69993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira boolean optionalEndTag, boolean breaksFlow, Flow flow) { 70993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira Preconditions.checkNotNull(name, "Element name can not be null"); 71993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira Preconditions.checkNotNull(flow, "Element flow can not be null"); 72993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.name = name; 73993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.type = type; 74993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.empty = empty; 75993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.optionalEndTag = optionalEndTag; 76993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.breaksFlow = breaksFlow; 77993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.flow = flow; 78993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 79993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 80993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 81993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Construct an Element with inline=true. 82993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 83993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Element(String name, int type, boolean empty, 84993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira boolean optionalEndTag, boolean breaksFlow) { 85993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this(name, type, empty, optionalEndTag, breaksFlow, Flow.NONE); 86993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 87993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 88993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Name of the element, in lowercase, e.g. "a", "br" */ 89993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public String getName() { 90993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return name; 91993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 92993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 93993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Type, e.g. TABLE_TYPE */ 94993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public int getType() { 95993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return type; 96993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 97993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 98993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** True if it's empty, has no inner elements or end tag */ 99993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public boolean isEmpty() { 100993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return empty; 101993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 102993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 103993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** True if the end tag is optional */ 104993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public boolean isEndTagOptional() { 105993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return optionalEndTag; 106993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 107993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 108993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 109993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * True if it breaks the flow, and may force a new line before/after the 110993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * tag. 111993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 112993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public boolean breaksFlow() { 113993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return breaksFlow; 114993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 115993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 116993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Flow type. */ 117993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Flow getFlow() { 118993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return flow; 119993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 120993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 121993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 122993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @return just name, not proper HTML 123993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 124993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 125993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public String toString() { 126993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return name; 127993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 128993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 129993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 130993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public boolean equals(Object o) { 131993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira if (o == this) { 132993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return true; 133993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 134993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira if (o instanceof HTML.Element) { 135993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira HTML.Element that = (HTML.Element) o; 136993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return this.name.equals(that.name); 137993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 138993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return false; 139993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 140993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 141993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 142993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public int hashCode() { 143993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return this.name.hashCode(); 144993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 145993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 146993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 147993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 148993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Html attribute 149993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 150993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final class Attribute { 151993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Value types */ 152993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int NO_TYPE = 0; 153993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int URI_TYPE = 1; 154993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int SCRIPT_TYPE = 2; 155993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int ENUM_TYPE = 3; 156993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public static final int BOOLEAN_TYPE = 4; 157993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 158993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Name of the element, e.g. "HREF" */ 159993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final String name; 160993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 161993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Type of the attribute value, e.g. URI_TYPE */ 162993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final int type; 163993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 164993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** The list of allowed values, or null if any value is allowed */ 165993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira private final Set<String> values; 166993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 167993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 168993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Construct an Attribute 169993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @throws IllegalArgumentException if name is null 170993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 171993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Attribute(String name, int type) { 172993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this(name, type, null); 173993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 174993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 175993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 176993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * Construct an Attribute 177993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @throws IllegalArgumentException if name is null 178993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * or if Attribute is of type ENUM_TYPE and the values are null 179993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 180993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Attribute(String name, int type, Set<String> values) { 181993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira Preconditions.checkNotNull(name, "Attribute name can not be null"); 182993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira Preconditions.checkArgument((values == null) ^ (type == ENUM_TYPE), 183993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira "Only ENUM_TYPE can have values != null"); 184993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.name = name; 185993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.type = type; 186993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira this.values = values; 187993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 188993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 189993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Gets the name of the attribute, in lowercase */ 190993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public String getName() { 191993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return name; 192993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 193993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 194993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** Gets the type, e.g. URI_TYPE */ 195993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public int getType() { 196993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return type; 197993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 198993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 199993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 200993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * When called on an attribute of ENUM_TYPE, returns a Set of Strings 201993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * containing the allowed attribute values. The return set is guaranteed to 202993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * only contain lower case Strings. 203993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * 204993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @return a Set of Strings, in lower case, for the allowed attribute 205993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * values. 206993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @throws IllegalStateException if attribute type is not ENUM_TYPE 207993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 208993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public Set<String> getEnumValues() { 209993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira Preconditions.checkState(type == ENUM_TYPE); 210993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return values; 211993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 212993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 213993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira /** 214993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira * @return Element name (name only, not proper HTML). 215993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira */ 216993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 217993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public String toString() { 218993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return name; 219993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 220993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 221993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 222993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public boolean equals(Object o) { 223993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira if (o == this) { 224993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return true; 225993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 226993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira if (o instanceof HTML.Attribute) { 227993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira HTML.Attribute that = (HTML.Attribute) o; 228993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return this.name.equals(that.name); 229993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 230993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return false; 231993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 232993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira 233993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira @Override 234993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira public int hashCode() { 235993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira return this.name.hashCode(); 236993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 237993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira } 238993ef2674bf860a84c5c17e51a7a9e13e5d56504Mindy Pereira}