Home | History | Annotate | Download | only in tagsoup
      1 // This file is part of TagSoup and is Copyright 2002-2008 by John Cowan.
      2 //
      3 // TagSoup is licensed under the Apache License,
      4 // Version 2.0.  You may obtain a copy of this license at
      5 // http://www.apache.org/licenses/LICENSE-2.0 .  You may also have
      6 // additional legal rights not granted by this license.
      7 //
      8 // TagSoup is distributed in the hope that it will be useful, but
      9 // unless required by applicable law or agreed to in writing, TagSoup
     10 // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
     11 // OF ANY KIND, either express or implied; not even the implied warranty
     12 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
     13 
     14 package org.ccil.cowan.tagsoup;
     15 
     16 /**
     17 This class represents an element type in the schema.
     18 An element type has a name, a content model vector, a member-of vector,
     19 a flags vector, default attributes, and a schema to which it belongs.
     20 @see Schema
     21 */
     22 
     23 public class ElementType {
     24 
     25 	private String theName;		// element type name (Qname)
     26 	private String theNamespace;	// element type namespace name
     27 	private String theLocalName;	// element type local name
     28 	private int theModel;		// bitmap: what the element contains
     29 	private int theMemberOf;	// bitmap: what element is contained in
     30 	private int theFlags;		// bitmap: element flags
     31 	private AttributesImpl theAtts;	// default attributes
     32 	private ElementType theParent;	// parent of this element type
     33 	private Schema theSchema;	// schema to which this belongs
     34 
     35 	/**
     36 	Construct an ElementType:
     37 	but it's better to use Schema.element() instead.
     38 	The content model, member-of, and flags vectors are specified as ints.
     39 	@param name The element type name
     40 	@param model ORed-together bits representing the content models
     41 	   allowed in the content of this element type
     42 	@param memberOf ORed-together bits representing the content models
     43 	   to which this element type belongs
     44 	@param flags ORed-together bits representing the flags associated
     45 	   with this element type
     46 	@param schema The schema with which this element type will be
     47 	associated
     48 	*/
     49 
     50 	public ElementType(String name, int model, int memberOf, int flags, Schema schema) {
     51 		theName = name;
     52 		theModel = model;
     53 		theMemberOf = memberOf;
     54 		theFlags = flags;
     55 		theAtts = new AttributesImpl();
     56 		theSchema = schema;
     57 		theNamespace = namespace(name, false);
     58 		theLocalName = localName(name);
     59 		}
     60 
     61 	/**
     62 	Return a namespace name from a Qname.
     63 	The attribute flag tells us whether to return an empty namespace
     64 	name if there is no prefix, or use the schema default instead.
     65 	@param name The Qname
     66 	@param attribute True if name is an attribute name
     67 	@return The namespace name
     68 	**/
     69 	public String namespace(String name, boolean attribute) {
     70 		int colon = name.indexOf(':');
     71 		if (colon == -1) {
     72 			return attribute ? "" : theSchema.getURI();
     73 			}
     74 		String prefix = name.substring(0, colon);
     75 		if (prefix.equals("xml")) {
     76 			return "http://www.w3.org/XML/1998/namespace";
     77 			}
     78 		else {
     79 			return ("urn:x-prefix:" + prefix).intern();
     80 			}
     81 		}
     82 
     83 	/**
     84 	Return a local name from a Qname.
     85 	@param name The Qname
     86 	@return The local name
     87 	**/
     88 	public String localName(String name) {
     89 		int colon = name.indexOf(':');
     90 		if (colon == -1) {
     91 			return name;
     92 			}
     93 		else {
     94 			return name.substring(colon+1).intern();
     95 			}
     96 		}
     97 
     98 	/**
     99 	Returns the name of this element type.
    100 	@return The name of the element type
    101 	*/
    102 
    103 	public String name() { return theName; }
    104 
    105 	/**
    106 	Returns the namespace name of this element type.
    107 	@return The namespace name of the element type
    108 	*/
    109 
    110 	public String namespace() { return theNamespace; }
    111 
    112 	/**
    113 	Returns the local name of this element type.
    114 	@return The local name of the element type
    115 	*/
    116 
    117 	public String localName() { return theLocalName; }
    118 
    119 	/**
    120 	Returns the content models of this element type.
    121 	@return The content models of this element type as a vector of bits
    122 	*/
    123 
    124 	public int model() { return theModel; }
    125 
    126 	/**
    127 	Returns the content models to which this element type belongs.
    128 	@return The content models to which this element type belongs as a
    129 	   vector of bits
    130 	*/
    131 
    132 	public int memberOf() { return theMemberOf; }
    133 
    134 	/**
    135 	Returns the flags associated with this element type.
    136 	@return The flags associated with this element type as a vector of bits
    137 	*/
    138 
    139 	public int flags() { return theFlags; }
    140 
    141 	/**
    142 	Returns the default attributes associated with this element type.
    143 	Attributes of type CDATA that don't have default values are
    144 	typically not included.  Other attributes without default values
    145 	have an internal value of <tt>null</tt>.
    146 	The return value is an AttributesImpl to allow the caller to mutate
    147 	the attributes.
    148 	*/
    149 
    150 	public AttributesImpl atts() {return theAtts;}
    151 
    152 	/**
    153 	Returns the parent element type of this element type.
    154 	@return The parent element type
    155 	*/
    156 
    157 	public ElementType parent() {return theParent;}
    158 
    159 	/**
    160 	Returns the schema which this element type is associated with.
    161 	@return The schema
    162 	*/
    163 
    164 	public Schema schema() {return theSchema;}
    165 
    166 
    167 	/**
    168 	Returns true if this element type can contain another element type.
    169 	That is, if any of the models in this element's model vector
    170 	match any of the models in the other element type's member-of
    171 	vector.
    172 	@param other The other element type
    173 	*/
    174 
    175 	public boolean canContain(ElementType other) {
    176 		return (theModel & other.theMemberOf) != 0;
    177 		}
    178 
    179 
    180 	/**
    181 	Sets an attribute and its value into an AttributesImpl object.
    182 	Attempts to set a namespace declaration are ignored.
    183 	@param atts The AttributesImpl object
    184 	@param name The name (Qname) of the attribute
    185 	@param type The type of the attribute
    186 	@param value The value of the attribute
    187 	*/
    188 
    189 	public void setAttribute(AttributesImpl atts, String name, String type, String value) {
    190 		if (name.equals("xmlns") || name.startsWith("xmlns:")) {
    191 			return;
    192 			}
    193 ;
    194 		String namespace = namespace(name, true);
    195 		String localName = localName(name);
    196 		int i = atts.getIndex(name);
    197 		if (i == -1) {
    198 			name = name.intern();
    199 			if (type == null) type = "CDATA";
    200 			if (!type.equals("CDATA")) value = normalize(value);
    201 			atts.addAttribute(namespace, localName, name, type, value);
    202 			}
    203 		else {
    204 			if (type == null) type = atts.getType(i);
    205 			if (!type.equals("CDATA")) value=normalize(value);
    206 			atts.setAttribute(i, namespace, localName, name, type, value);
    207 			}
    208 		}
    209 
    210 	/**
    211 	Normalize an attribute value (ID-style).
    212 	CDATA-style attribute normalization is already done.
    213 	@param value The value to normalize
    214 	@return The normalized value
    215 	**/
    216 	public static String normalize(String value) {
    217 		if (value == null) return value;
    218 		value = value.trim();
    219 		if (value.indexOf("  ") == -1) return value;
    220 		boolean space = false;
    221 		int len = value.length();
    222 		StringBuffer b = new StringBuffer(len);
    223 		for (int i = 0; i < len; i++) {
    224 			char v = value.charAt(i);
    225 			if (v == ' ') {
    226 				if (!space) b.append(v);
    227 				space = true;
    228 				}
    229 			else {
    230 				b.append(v);
    231 				space = false;
    232 				}
    233 			}
    234 		return b.toString();
    235 		}
    236 
    237 	/**
    238 	Sets an attribute and its value into this element type.
    239 	@param name The name of the attribute
    240 	@param type The type of the attribute
    241 	@param value The value of the attribute
    242 	*/
    243 
    244 	public void setAttribute(String name, String type, String value) {
    245 		setAttribute(theAtts, name, type, value);
    246 		}
    247 
    248 	/**
    249 	Sets the models of this element type.
    250 	@param model The content models of this element type as a vector of bits
    251 	*/
    252 
    253 	public void setModel(int model) { theModel = model; }
    254 
    255 	/**
    256 	Sets the content models to which this element type belongs.
    257 	@param memberOf The content models to which this element type belongs as a vector of bits
    258 	*/
    259 
    260 	public void setMemberOf(int memberOf) { theMemberOf = memberOf; }
    261 
    262 	/**
    263 	Sets the flags of this element type.
    264 	@param flags associated with this element type The flags as a vector of bits
    265 	*/
    266 
    267 	public void setFlags(int flags) { theFlags = flags; }
    268 
    269 	/**
    270 	Sets the parent element type of this element type.
    271 	@param parent The parent element type
    272 	*/
    273 
    274 	public void setParent(ElementType parent) { theParent = parent; }
    275 
    276 	}
    277