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
14package org.ccil.cowan.tagsoup;
15
16/**
17This class represents an element type in the schema.
18An element type has a name, a content model vector, a member-of vector,
19a flags vector, default attributes, and a schema to which it belongs.
20@see Schema
21*/
22
23public 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