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