source: osm/applications/editors/josm/plugins/opendata/includes/org/jdom/Attribute.java@ 28000

Last change on this file since 28000 was 28000, checked in by donvip, 12 years ago

Import new "opendata" JOSM plugin

File size: 17.8 KB
Line 
1/*--
2
3 $Id: Attribute.java,v 1.56 2007/11/10 05:28:58 jhunter Exp $
4
5 Copyright (C) 2000-2007 Jason Hunter & Brett McLaughlin.
6 All rights reserved.
7
8 Redistribution and use in source and binary forms, with or without
9 modification, are permitted provided that the following conditions
10 are met:
11
12 1. Redistributions of source code must retain the above copyright
13 notice, this list of conditions, and the following disclaimer.
14
15 2. Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions, and the disclaimer that follows
17 these conditions in the documentation and/or other materials
18 provided with the distribution.
19
20 3. The name "JDOM" must not be used to endorse or promote products
21 derived from this software without prior written permission. For
22 written permission, please contact <request_AT_jdom_DOT_org>.
23
24 4. Products derived from this software may not be called "JDOM", nor
25 may "JDOM" appear in their name, without prior written permission
26 from the JDOM Project Management <request_AT_jdom_DOT_org>.
27
28 In addition, we request (but do not require) that you include in the
29 end-user documentation provided with the redistribution and/or in the
30 software itself an acknowledgement equivalent to the following:
31 "This product includes software developed by the
32 JDOM Project (http://www.jdom.org/)."
33 Alternatively, the acknowledgment may be graphical using the logos
34 available at http://www.jdom.org/images/logos.
35
36 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 DISCLAIMED. IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43 USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 SUCH DAMAGE.
48
49 This software consists of voluntary contributions made by many
50 individuals on behalf of the JDOM Project and was originally
51 created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52 Brett McLaughlin <brett_AT_jdom_DOT_org>. For more information
53 on the JDOM Project, please see <http://www.jdom.org/>.
54
55 */
56
57package org.jdom;
58
59import java.io.IOException;
60import java.io.ObjectInputStream;
61import java.io.ObjectOutputStream;
62import java.io.Serializable;
63
64/**
65 * An XML attribute. Methods allow the user to obtain the value of the attribute
66 * as well as namespace and type information.
67 *
68 * @version $Revision: 1.56 $, $Date: 2007/11/10 05:28:58 $
69 * @author Brett McLaughlin
70 * @author Jason Hunter
71 * @author Elliotte Rusty Harold
72 * @author Wesley Biggs
73 * @author Victor Toni
74 */
75public class Attribute implements Serializable, Cloneable {
76
77 /**
78 * Attribute type: the attribute has not been declared or type
79 * is unknown.
80 *
81 * @see #getAttributeType
82 */
83 public final static int UNDECLARED_TYPE = 0;
84
85 /**
86 * Attribute type: the attribute value is a string.
87 *
88 * @see #getAttributeType
89 */
90 public final static int CDATA_TYPE = 1;
91
92 /**
93 * Attribute type: the attribute value is a unique identifier.
94 *
95 * @see #getAttributeType
96 */
97 public final static int ID_TYPE = 2;
98
99 /**
100 * Attribute type: the attribute value is a reference to a
101 * unique identifier.
102 *
103 * @see #getAttributeType
104 */
105 public final static int IDREF_TYPE = 3;
106
107 /**
108 * Attribute type: the attribute value is a list of references to
109 * unique identifiers.
110 *
111 * @see #getAttributeType
112 */
113 public final static int IDREFS_TYPE = 4;
114
115 /**
116 * Attribute type: the attribute value is the name of an entity.
117 *
118 * @see #getAttributeType
119 */
120 public final static int ENTITY_TYPE = 5;
121
122 /**
123 * <p>
124 * Attribute type: the attribute value is a list of entity names.
125 * </p>
126 *
127 * @see #getAttributeType
128 */
129 public final static int ENTITIES_TYPE = 6;
130
131 /**
132 * Attribute type: the attribute value is a name token.
133 * <p>
134 * According to SAX 2.0 specification, attributes of enumerated
135 * types should be reported as "NMTOKEN" by SAX parsers. But the
136 * major parsers (Xerces and Crimson) provide specific values
137 * that permit to recognize them as {@link #ENUMERATED_TYPE}.
138 *
139 * @see #getAttributeType
140 */
141 public final static int NMTOKEN_TYPE = 7;
142
143 /**
144 * Attribute type: the attribute value is a list of name tokens.
145 *
146 * @see #getAttributeType
147 */
148 public final static int NMTOKENS_TYPE = 8;
149
150 /**
151 * Attribute type: the attribute value is the name of a notation.
152 *
153 * @see #getAttributeType
154 */
155 public final static int NOTATION_TYPE = 9;
156
157 /**
158 * Attribute type: the attribute value is a name token from an
159 * enumeration.
160 *
161 * @see #getAttributeType
162 */
163 public final static int ENUMERATED_TYPE = 10;
164
165 // Keep the old constant names for one beta cycle to help migration
166
167
168
169 /** The local name of the <code>Attribute</code> */
170 protected String name;
171
172 /** The <code>{@link Namespace}</code> of the <code>Attribute</code> */
173 protected transient Namespace namespace;
174
175 /** The value of the <code>Attribute</code> */
176 protected String value;
177
178 /** Parent element, or null if none */
179 protected Element parent;
180
181 /**
182 * Default, no-args constructor for implementations to use if needed.
183 */
184 protected Attribute() {}
185
186 /**
187 * This will create a new <code>Attribute</code> with the
188 * specified (local) name and value, and in the provided
189 * <code>{@link Namespace}</code>.
190 *
191 * @param name <code>String</code> name of <code>Attribute</code>.
192 * @param value <code>String</code> value for new attribute.
193 * @param namespace <code>Namespace</code> namespace for new attribute.
194 * @throws IllegalNameException if the given name is illegal as an
195 * attribute name or if if the new namespace is the default
196 * namespace. Attributes cannot be in a default namespace.
197 * @throws IllegalDataException if the given attribute value is
198 * illegal character data (as determined by
199 * {@link org.jdom.Verifier#checkCharacterData}).
200 */
201 public Attribute(final String name, final String value, final Namespace namespace) {
202 this(name, value, UNDECLARED_TYPE, namespace);
203 }
204
205 /**
206 * This will create a new <code>Attribute</code> with the
207 * specified (local) name, value, and type, and in the provided
208 * <code>{@link Namespace}</code>.
209 *
210 * @param name <code>String</code> name of <code>Attribute</code>.
211 * @param value <code>String</code> value for new attribute.
212 * @param type <code>int</code> type for new attribute.
213 * @param namespace <code>Namespace</code> namespace for new attribute.
214 * @throws IllegalNameException if the given name is illegal as an
215 * attribute name or if if the new namespace is the default
216 * namespace. Attributes cannot be in a default namespace.
217 * @throws IllegalDataException if the given attribute value is
218 * illegal character data (as determined by
219 * {@link org.jdom.Verifier#checkCharacterData}) or
220 * if the given attribute type is not one of the
221 * supported types.
222 */
223 public Attribute(final String name, final String value, final int type, final Namespace namespace) {
224 setName(name);
225 setValue(value);
226 setAttributeType(type);
227 setNamespace(namespace);
228 }
229
230 /**
231 * This will return the parent of this <code>Attribute</code>.
232 * If there is no parent, then this returns <code>null</code>.
233 *
234 * @return parent of this <code>Attribute</code>
235 */
236 public Element getParent() {
237 return parent;
238 }
239
240 /**
241 * This will set the parent of this <code>Attribute</code>.
242 *
243 * @param parent <code>Element</code> to be new parent.
244 * @return this <code>Attribute</code> modified.
245 */
246 protected Attribute setParent(final Element parent) {
247 this.parent = parent;
248 return this;
249 }
250
251 /**
252 * This detaches the <code>Attribute</code> from its parent, or does
253 * nothing if the <code>Attribute</code> has no parent.
254 *
255 * @return <code>Attribute</code> - this <code>Attribute</code> modified.
256 */
257 public Attribute detach() {
258 final Element parentElement = getParent();
259 if (parentElement != null) {
260 parentElement.removeAttribute(getName(),getNamespace());
261 }
262
263 return this;
264 }
265
266 /**
267 * This will retrieve the local name of the
268 * <code>Attribute</code>. For any XML attribute
269 * which appears as
270 * <code>[namespacePrefix]:[attributeName]</code>,
271 * the local name of the attribute would be
272 * <code>[attributeName]</code>. When the attribute
273 * has no namespace, the local name is simply the attribute
274 * name.
275 * <p>
276 * To obtain the namespace prefix for this
277 * attribute, the
278 * <code>{@link #getNamespacePrefix()}</code>
279 * method should be used.
280 *
281 * @return <code>String</code> - name of this attribute,
282 * without any namespace prefix.
283 */
284 public String getName() {
285 return name;
286 }
287
288 /**
289 * This sets the local name of the <code>Attribute</code>.
290 *
291 * @param name the new local name to set
292 * @return <code>Attribute</code> - the attribute modified.
293 * @throws IllegalNameException if the given name is illegal as an
294 * attribute name.
295 */
296 public Attribute setName(final String name) {
297 final String reason = Verifier.checkAttributeName(name);
298 if (reason != null) {
299 throw new IllegalNameException(name, "attribute", reason);
300 }
301 this.name = name;
302 return this;
303 }
304
305 /**
306 * This will retrieve the qualified name of the <code>Attribute</code>.
307 * For any XML attribute whose name is
308 * <code>[namespacePrefix]:[elementName]</code>,
309 * the qualified name of the attribute would be
310 * everything (both namespace prefix and
311 * element name). When the attribute has no
312 * namespace, the qualified name is simply the attribute's
313 * local name.
314 * <p>
315 * To obtain the local name of the attribute, the
316 * <code>{@link #getName()}</code> method should be used.
317 * <p>
318 * To obtain the namespace prefix for this attribute,
319 * the <code>{@link #getNamespacePrefix()}</code>
320 * method should be used.
321 *
322 * @return <code>String</code> - full name for this element.
323 */
324 public String getQualifiedName() {
325 // Note: Any changes here should be reflected in
326 // XMLOutputter.printQualifiedName()
327 final String prefix = namespace.getPrefix();
328
329 // no prefix found
330 if ((prefix == null) || ("".equals(prefix))) {
331 return getName();
332 } else {
333 return new StringBuffer(prefix)
334 .append(':')
335 .append(getName())
336 .toString();
337 }
338 }
339
340 /**
341 * This will retrieve the namespace prefix of the
342 * <code>Attribute</code>. For any XML attribute
343 * which appears as
344 * <code>[namespacePrefix]:[attributeName]</code>,
345 * the namespace prefix of the attribute would be
346 * <code>[namespacePrefix]</code>. When the attribute
347 * has no namespace, an empty <code>String</code> is returned.
348 *
349 * @return <code>String</code> - namespace prefix of this
350 * attribute.
351 */
352 public String getNamespacePrefix() {
353 return namespace.getPrefix();
354 }
355
356 /**
357 * This returns the URI mapped to this <code>Attribute</code>'s
358 * prefix. If no mapping is found, an empty <code>String</code> is
359 * returned.
360 *
361 * @return <code>String</code> - namespace URI for this <code>Attribute</code>.
362 */
363 public String getNamespaceURI() {
364 return namespace.getURI();
365 }
366
367 /**
368 * This will return this <code>Attribute</code>'s
369 * <code>{@link Namespace}</code>.
370 *
371 * @return <code>Namespace</code> - Namespace object for this <code>Attribute</code>
372 */
373 public Namespace getNamespace() {
374 return namespace;
375 }
376
377 /**
378 * This sets this <code>Attribute</code>'s <code>{@link Namespace}</code>.
379 * If the provided namespace is null, the attribute will have no namespace.
380 * The namespace must have a prefix.
381 *
382 * @param namespace the new namespace
383 * @return <code>Element</code> - the element modified.
384 * @throws IllegalNameException if the new namespace is the default
385 * namespace. Attributes cannot be in a default namespace.
386 */
387 public Attribute setNamespace(Namespace namespace) {
388 if (namespace == null) {
389 namespace = Namespace.NO_NAMESPACE;
390 }
391
392 // Verify the attribute isn't trying to be in a default namespace
393 // Attributes can't be in a default namespace
394 if (namespace != Namespace.NO_NAMESPACE &&
395 "".equals(namespace.getPrefix())) {
396 throw new IllegalNameException("", "attribute namespace",
397 "An attribute namespace without a prefix can only be the " +
398 "NO_NAMESPACE namespace");
399 }
400 this.namespace = namespace;
401 return this;
402 }
403
404 /**
405 * This will return the actual textual value of this
406 * <code>Attribute</code>. This will include all text
407 * within the quotation marks.
408 *
409 * @return <code>String</code> - value for this attribute.
410 */
411 public String getValue() {
412 return value;
413 }
414
415 /**
416 * This will set the value of the <code>Attribute</code>.
417 *
418 * @param value <code>String</code> value for the attribute.
419 * @return <code>Attribute</code> - this Attribute modified.
420 * @throws IllegalDataException if the given attribute value is
421 * illegal character data (as determined by
422 * {@link org.jdom.Verifier#checkCharacterData}).
423 */
424 public Attribute setValue(final String value) {
425 final String reason = Verifier.checkCharacterData(value);
426 if (reason != null) {
427 throw new IllegalDataException(value, "attribute", reason);
428 }
429 this.value = value;
430 return this;
431 }
432
433 /**
434 * This will set the type of the <code>Attribute</code>.
435 *
436 * @param type <code>int</code> type for the attribute.
437 * @return <code>Attribute</code> - this Attribute modified.
438 * @throws IllegalDataException if the given attribute type is
439 * not one of the supported types.
440 */
441 public Attribute setAttributeType(final int type) {
442 if ((type < UNDECLARED_TYPE) || (type > ENUMERATED_TYPE)) {
443 throw new IllegalDataException(String.valueOf(type),
444 "attribute", "Illegal attribute type");
445 }
446 return this;
447 }
448
449 /**
450 * This returns a <code>String</code> representation of the
451 * <code>Attribute</code>, suitable for debugging.
452 *
453 * @return <code>String</code> - information about the
454 * <code>Attribute</code>
455 */
456 public String toString() {
457 return new StringBuffer()
458 .append("[Attribute: ")
459 .append(getQualifiedName())
460 .append("=\"")
461 .append(value)
462 .append("\"")
463 .append("]")
464 .toString();
465 }
466
467 /**
468 * This tests for equality of this <code>Attribute</code> to the supplied
469 * <code>Object</code>.
470 *
471 * @param ob <code>Object</code> to compare to.
472 * @return <code>boolean</code> - whether the <code>Attribute</code> is
473 * equal to the supplied <code>Object</code>.
474 */
475 public final boolean equals(final Object ob) {
476 return (ob == this);
477 }
478
479 /**
480 * This returns the hash code for this <code>Attribute</code>.
481 *
482 * @return <code>int</code> - hash code.
483 */
484 public final int hashCode() {
485 return super.hashCode();
486 }
487
488 /**
489 * This will return a clone of this <code>Attribute</code>.
490 *
491 * @return <code>Object</code> - clone of this <code>Attribute</code>.
492 */
493 public Object clone() {
494 Attribute attribute = null;
495 try {
496 attribute = (Attribute) super.clone();
497 }
498 catch (final CloneNotSupportedException ignore) {
499 // Won't happen
500 }
501
502 // Name, namespace, and value are references to imutable objects
503 // and are copied by super.clone() (aka Object.clone())
504
505 // super.clone() copies reference to set parent to null
506 attribute.parent = null;
507 return attribute;
508 }
509
510 /////////////////////////////////////////////////////////////////
511 // Convenience Methods below here
512 /////////////////////////////////////////////////////////////////
513
514
515 // Support a custom Namespace serialization so no two namespace
516 // object instances may exist for the same prefix/uri pair
517 private void writeObject(final ObjectOutputStream out) throws IOException {
518
519 out.defaultWriteObject();
520
521 // We use writeObject() and not writeUTF() to minimize space
522 // This allows for writing pointers to already written strings
523 out.writeObject(namespace.getPrefix());
524 out.writeObject(namespace.getURI());
525 }
526
527 private void readObject(final ObjectInputStream in)
528 throws IOException, ClassNotFoundException {
529
530 in.defaultReadObject();
531
532 namespace = Namespace.getNamespace(
533 (String) in.readObject(), (String) in.readObject());
534 }
535}
Note: See TracBrowser for help on using the repository browser.