comparison NGSrich_0.5.5/src/org/jdom/Attribute.java @ 0:89ad0a9cca52 default tip

Uploaded
author pfrommolt
date Mon, 21 Nov 2011 08:12:19 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:89ad0a9cca52
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
57 package org.jdom;
58
59 import java.io.*;
60
61 /**
62 * An XML attribute. Methods allow the user to obtain the value of the attribute
63 * as well as namespace and type information.
64 *
65 * @version $Revision: 1.56 $, $Date: 2007/11/10 05:28:58 $
66 * @author Brett McLaughlin
67 * @author Jason Hunter
68 * @author Elliotte Rusty Harold
69 * @author Wesley Biggs
70 * @author Victor Toni
71 */
72 public class Attribute implements Serializable, Cloneable {
73
74 private static final String CVS_ID =
75 "@(#) $RCSfile: Attribute.java,v $ $Revision: 1.56 $ $Date: 2007/11/10 05:28:58 $ $Name: jdom_1_1_1 $";
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 /** The type of the <code>Attribute</code> */
179 protected int type = UNDECLARED_TYPE;
180
181 /** Parent element, or null if none */
182 protected Element parent;
183
184 /**
185 * Default, no-args constructor for implementations to use if needed.
186 */
187 protected Attribute() {}
188
189 /**
190 * This will create a new <code>Attribute</code> with the
191 * specified (local) name and value, and in the provided
192 * <code>{@link Namespace}</code>.
193 *
194 * @param name <code>String</code> name of <code>Attribute</code>.
195 * @param value <code>String</code> value for new attribute.
196 * @param namespace <code>Namespace</code> namespace for new attribute.
197 * @throws IllegalNameException if the given name is illegal as an
198 * attribute name or if if the new namespace is the default
199 * namespace. Attributes cannot be in a default namespace.
200 * @throws IllegalDataException if the given attribute value is
201 * illegal character data (as determined by
202 * {@link org.jdom.Verifier#checkCharacterData}).
203 */
204 public Attribute(final String name, final String value, final Namespace namespace) {
205 this(name, value, UNDECLARED_TYPE, namespace);
206 }
207
208 /**
209 * This will create a new <code>Attribute</code> with the
210 * specified (local) name, value, and type, and in the provided
211 * <code>{@link Namespace}</code>.
212 *
213 * @param name <code>String</code> name of <code>Attribute</code>.
214 * @param value <code>String</code> value for new attribute.
215 * @param type <code>int</code> type for new attribute.
216 * @param namespace <code>Namespace</code> namespace for new attribute.
217 * @throws IllegalNameException if the given name is illegal as an
218 * attribute name or if if the new namespace is the default
219 * namespace. Attributes cannot be in a default namespace.
220 * @throws IllegalDataException if the given attribute value is
221 * illegal character data (as determined by
222 * {@link org.jdom.Verifier#checkCharacterData}) or
223 * if the given attribute type is not one of the
224 * supported types.
225 */
226 public Attribute(final String name, final String value, final int type, final Namespace namespace) {
227 setName(name);
228 setValue(value);
229 setAttributeType(type);
230 setNamespace(namespace);
231 }
232
233 /**
234 * This will create a new <code>Attribute</code> with the
235 * specified (local) name and value, and does not place
236 * the attribute in a <code>{@link Namespace}</code>.
237 * <p>
238 * <b>Note</b>: This actually explicitly puts the
239 * <code>Attribute</code> in the "empty" <code>Namespace</code>
240 * (<code>{@link Namespace#NO_NAMESPACE}</code>).
241 *
242 * @param name <code>String</code> name of <code>Attribute</code>.
243 * @param value <code>String</code> value for new attribute.
244 * @throws IllegalNameException if the given name is illegal as an
245 * attribute name.
246 * @throws IllegalDataException if the given attribute value is
247 * illegal character data (as determined by
248 * {@link org.jdom.Verifier#checkCharacterData}).
249 */
250 public Attribute(final String name, final String value) {
251 this(name, value, UNDECLARED_TYPE, Namespace.NO_NAMESPACE);
252 }
253
254 /**
255 * This will create a new <code>Attribute</code> with the
256 * specified (local) name, value and type, and does not place
257 * the attribute in a <code>{@link Namespace}</code>.
258 * <p>
259 * <b>Note</b>: This actually explicitly puts the
260 * <code>Attribute</code> in the "empty" <code>Namespace</code>
261 * (<code>{@link Namespace#NO_NAMESPACE}</code>).
262 *
263 * @param name <code>String</code> name of <code>Attribute</code>.
264 * @param value <code>String</code> value for new attribute.
265 * @param type <code>int</code> type for new attribute.
266 * @throws IllegalNameException if the given name is illegal as an
267 * attribute name.
268 * @throws IllegalDataException if the given attribute value is
269 * illegal character data (as determined by
270 * {@link org.jdom.Verifier#checkCharacterData}) or
271 * if the given attribute type is not one of the
272 * supported types.
273 */
274 public Attribute(final String name, final String value, final int type) {
275 this(name, value, type, Namespace.NO_NAMESPACE);
276 }
277
278 /**
279 * This will return the parent of this <code>Attribute</code>.
280 * If there is no parent, then this returns <code>null</code>.
281 *
282 * @return parent of this <code>Attribute</code>
283 */
284 public Element getParent() {
285 return parent;
286 }
287
288 /**
289 * This retrieves the owning <code>{@link Document}</code> for
290 * this Attribute, or null if not a currently a member of a
291 * <code>{@link Document}</code>.
292 *
293 * @return <code>Document</code> owning this Attribute, or null.
294 */
295 public Document getDocument() {
296 final Element parentElement = getParent();
297 if (parentElement != null) {
298 return parentElement.getDocument();
299 }
300
301 return null;
302 }
303
304 /**
305 * This will set the parent of this <code>Attribute</code>.
306 *
307 * @param parent <code>Element</code> to be new parent.
308 * @return this <code>Attribute</code> modified.
309 */
310 protected Attribute setParent(final Element parent) {
311 this.parent = parent;
312 return this;
313 }
314
315 /**
316 * This detaches the <code>Attribute</code> from its parent, or does
317 * nothing if the <code>Attribute</code> has no parent.
318 *
319 * @return <code>Attribute</code> - this <code>Attribute</code> modified.
320 */
321 public Attribute detach() {
322 final Element parentElement = getParent();
323 if (parentElement != null) {
324 parentElement.removeAttribute(getName(),getNamespace());
325 }
326
327 return this;
328 }
329
330 /**
331 * This will retrieve the local name of the
332 * <code>Attribute</code>. For any XML attribute
333 * which appears as
334 * <code>[namespacePrefix]:[attributeName]</code>,
335 * the local name of the attribute would be
336 * <code>[attributeName]</code>. When the attribute
337 * has no namespace, the local name is simply the attribute
338 * name.
339 * <p>
340 * To obtain the namespace prefix for this
341 * attribute, the
342 * <code>{@link #getNamespacePrefix()}</code>
343 * method should be used.
344 *
345 * @return <code>String</code> - name of this attribute,
346 * without any namespace prefix.
347 */
348 public String getName() {
349 return name;
350 }
351
352 /**
353 * This sets the local name of the <code>Attribute</code>.
354 *
355 * @param name the new local name to set
356 * @return <code>Attribute</code> - the attribute modified.
357 * @throws IllegalNameException if the given name is illegal as an
358 * attribute name.
359 */
360 public Attribute setName(final String name) {
361 final String reason = Verifier.checkAttributeName(name);
362 if (reason != null) {
363 throw new IllegalNameException(name, "attribute", reason);
364 }
365 this.name = name;
366 return this;
367 }
368
369 /**
370 * This will retrieve the qualified name of the <code>Attribute</code>.
371 * For any XML attribute whose name is
372 * <code>[namespacePrefix]:[elementName]</code>,
373 * the qualified name of the attribute would be
374 * everything (both namespace prefix and
375 * element name). When the attribute has no
376 * namespace, the qualified name is simply the attribute's
377 * local name.
378 * <p>
379 * To obtain the local name of the attribute, the
380 * <code>{@link #getName()}</code> method should be used.
381 * <p>
382 * To obtain the namespace prefix for this attribute,
383 * the <code>{@link #getNamespacePrefix()}</code>
384 * method should be used.
385 *
386 * @return <code>String</code> - full name for this element.
387 */
388 public String getQualifiedName() {
389 // Note: Any changes here should be reflected in
390 // XMLOutputter.printQualifiedName()
391 final String prefix = namespace.getPrefix();
392
393 // no prefix found
394 if ((prefix == null) || ("".equals(prefix))) {
395 return getName();
396 } else {
397 return new StringBuffer(prefix)
398 .append(':')
399 .append(getName())
400 .toString();
401 }
402 }
403
404 /**
405 * This will retrieve the namespace prefix of the
406 * <code>Attribute</code>. For any XML attribute
407 * which appears as
408 * <code>[namespacePrefix]:[attributeName]</code>,
409 * the namespace prefix of the attribute would be
410 * <code>[namespacePrefix]</code>. When the attribute
411 * has no namespace, an empty <code>String</code> is returned.
412 *
413 * @return <code>String</code> - namespace prefix of this
414 * attribute.
415 */
416 public String getNamespacePrefix() {
417 return namespace.getPrefix();
418 }
419
420 /**
421 * This returns the URI mapped to this <code>Attribute</code>'s
422 * prefix. If no mapping is found, an empty <code>String</code> is
423 * returned.
424 *
425 * @return <code>String</code> - namespace URI for this <code>Attribute</code>.
426 */
427 public String getNamespaceURI() {
428 return namespace.getURI();
429 }
430
431 /**
432 * This will return this <code>Attribute</code>'s
433 * <code>{@link Namespace}</code>.
434 *
435 * @return <code>Namespace</code> - Namespace object for this <code>Attribute</code>
436 */
437 public Namespace getNamespace() {
438 return namespace;
439 }
440
441 /**
442 * This sets this <code>Attribute</code>'s <code>{@link Namespace}</code>.
443 * If the provided namespace is null, the attribute will have no namespace.
444 * The namespace must have a prefix.
445 *
446 * @param namespace the new namespace
447 * @return <code>Element</code> - the element modified.
448 * @throws IllegalNameException if the new namespace is the default
449 * namespace. Attributes cannot be in a default namespace.
450 */
451 public Attribute setNamespace(Namespace namespace) {
452 if (namespace == null) {
453 namespace = Namespace.NO_NAMESPACE;
454 }
455
456 // Verify the attribute isn't trying to be in a default namespace
457 // Attributes can't be in a default namespace
458 if (namespace != Namespace.NO_NAMESPACE &&
459 "".equals(namespace.getPrefix())) {
460 throw new IllegalNameException("", "attribute namespace",
461 "An attribute namespace without a prefix can only be the " +
462 "NO_NAMESPACE namespace");
463 }
464 this.namespace = namespace;
465 return this;
466 }
467
468 /**
469 * This will return the actual textual value of this
470 * <code>Attribute</code>. This will include all text
471 * within the quotation marks.
472 *
473 * @return <code>String</code> - value for this attribute.
474 */
475 public String getValue() {
476 return value;
477 }
478
479 /**
480 * This will set the value of the <code>Attribute</code>.
481 *
482 * @param value <code>String</code> value for the attribute.
483 * @return <code>Attribute</code> - this Attribute modified.
484 * @throws IllegalDataException if the given attribute value is
485 * illegal character data (as determined by
486 * {@link org.jdom.Verifier#checkCharacterData}).
487 */
488 public Attribute setValue(final String value) {
489 final String reason = Verifier.checkCharacterData(value);
490 if (reason != null) {
491 throw new IllegalDataException(value, "attribute", reason);
492 }
493 this.value = value;
494 return this;
495 }
496
497 /**
498 * This will return the actual declared type of this
499 * <code>Attribute</code>.
500 *
501 * @return <code>int</code> - type for this attribute.
502 */
503 public int getAttributeType() {
504 return type;
505 }
506
507 /**
508 * This will set the type of the <code>Attribute</code>.
509 *
510 * @param type <code>int</code> type for the attribute.
511 * @return <code>Attribute</code> - this Attribute modified.
512 * @throws IllegalDataException if the given attribute type is
513 * not one of the supported types.
514 */
515 public Attribute setAttributeType(final int type) {
516 if ((type < UNDECLARED_TYPE) || (type > ENUMERATED_TYPE)) {
517 throw new IllegalDataException(String.valueOf(type),
518 "attribute", "Illegal attribute type");
519 }
520 this.type = type;
521 return this;
522 }
523
524 /**
525 * This returns a <code>String</code> representation of the
526 * <code>Attribute</code>, suitable for debugging.
527 *
528 * @return <code>String</code> - information about the
529 * <code>Attribute</code>
530 */
531 public String toString() {
532 return new StringBuffer()
533 .append("[Attribute: ")
534 .append(getQualifiedName())
535 .append("=\"")
536 .append(value)
537 .append("\"")
538 .append("]")
539 .toString();
540 }
541
542 /**
543 * This tests for equality of this <code>Attribute</code> to the supplied
544 * <code>Object</code>.
545 *
546 * @param ob <code>Object</code> to compare to.
547 * @return <code>boolean</code> - whether the <code>Attribute</code> is
548 * equal to the supplied <code>Object</code>.
549 */
550 public final boolean equals(final Object ob) {
551 return (ob == this);
552 }
553
554 /**
555 * This returns the hash code for this <code>Attribute</code>.
556 *
557 * @return <code>int</code> - hash code.
558 */
559 public final int hashCode() {
560 return super.hashCode();
561 }
562
563 /**
564 * This will return a clone of this <code>Attribute</code>.
565 *
566 * @return <code>Object</code> - clone of this <code>Attribute</code>.
567 */
568 public Object clone() {
569 Attribute attribute = null;
570 try {
571 attribute = (Attribute) super.clone();
572 }
573 catch (final CloneNotSupportedException ignore) {
574 // Won't happen
575 }
576
577 // Name, namespace, and value are references to imutable objects
578 // and are copied by super.clone() (aka Object.clone())
579
580 // super.clone() copies reference to set parent to null
581 attribute.parent = null;
582 return attribute;
583 }
584
585 /////////////////////////////////////////////////////////////////
586 // Convenience Methods below here
587 /////////////////////////////////////////////////////////////////
588
589 /**
590 * This gets the value of the attribute, in
591 * <code>int</code> form, and if no conversion
592 * can occur, throws a
593 * <code>{@link DataConversionException}</code>
594 *
595 * @return <code>int</code> value of attribute.
596 * @throws DataConversionException when conversion fails.
597 */
598 public int getIntValue() throws DataConversionException {
599 try {
600 return Integer.parseInt(value.trim());
601 } catch (final NumberFormatException e) {
602 throw new DataConversionException(name, "int");
603 }
604 }
605
606 /**
607 * This gets the value of the attribute, in
608 * <code>long</code> form, and if no conversion
609 * can occur, throws a
610 * <code>{@link DataConversionException}</code>
611 *
612 * @return <code>long</code> value of attribute.
613 * @throws DataConversionException when conversion fails.
614 */
615 public long getLongValue() throws DataConversionException {
616 try {
617 return Long.parseLong(value.trim());
618 } catch (final NumberFormatException e) {
619 throw new DataConversionException(name, "long");
620 }
621 }
622
623 /**
624 * This gets the value of the attribute, in
625 * <code>float</code> form, and if no conversion
626 * can occur, throws a
627 * <code>{@link DataConversionException}</code>
628 *
629 * @return <code>float</code> value of attribute.
630 * @throws DataConversionException when conversion fails.
631 */
632 public float getFloatValue() throws DataConversionException {
633 try {
634 // Avoid Float.parseFloat() to support JDK 1.1
635 return Float.valueOf(value.trim()).floatValue();
636 } catch (final NumberFormatException e) {
637 throw new DataConversionException(name, "float");
638 }
639 }
640
641 /**
642 * This gets the value of the attribute, in
643 * <code>double</code> form, and if no conversion
644 * can occur, throws a
645 * <code>{@link DataConversionException}</code>
646 *
647 * @return <code>double</code> value of attribute.
648 * @throws DataConversionException when conversion fails.
649 */
650 public double getDoubleValue() throws DataConversionException {
651 try {
652 // Avoid Double.parseDouble() to support JDK 1.1
653 return Double.valueOf(value.trim()).doubleValue();
654 } catch (final NumberFormatException e) {
655 // Specially handle INF and -INF that Double.valueOf doesn't do
656 String v = value.trim();
657 if ("INF".equals(v)) {
658 return Double.POSITIVE_INFINITY;
659 }
660 if ("-INF".equals(v)) {
661 return Double.NEGATIVE_INFINITY;
662 }
663 throw new DataConversionException(name, "double");
664 }
665 }
666
667 /**
668 * This gets the effective boolean value of the attribute, or throws a
669 * <code>{@link DataConversionException}</code> if a conversion can't be
670 * performed. True values are: "true", "on", "1", and "yes". False
671 * values are: "false", "off", "0", and "no". Values are trimmed before
672 * comparison. Values other than those listed here throw the exception.
673 *
674 * @return <code>boolean</code> value of attribute.
675 * @throws DataConversionException when conversion fails.
676 */
677 public boolean getBooleanValue() throws DataConversionException {
678 final String valueTrim = value.trim();
679 if (
680 (valueTrim.equalsIgnoreCase("true")) ||
681 (valueTrim.equalsIgnoreCase("on")) ||
682 (valueTrim.equalsIgnoreCase("1")) ||
683 (valueTrim.equalsIgnoreCase("yes"))) {
684 return true;
685 } else if (
686 (valueTrim.equalsIgnoreCase("false")) ||
687 (valueTrim.equalsIgnoreCase("off")) ||
688 (valueTrim.equalsIgnoreCase("0")) ||
689 (valueTrim.equalsIgnoreCase("no"))
690 ) {
691 return false;
692 } else {
693 throw new DataConversionException(name, "boolean");
694 }
695 }
696
697 // Support a custom Namespace serialization so no two namespace
698 // object instances may exist for the same prefix/uri pair
699 private void writeObject(final ObjectOutputStream out) throws IOException {
700
701 out.defaultWriteObject();
702
703 // We use writeObject() and not writeUTF() to minimize space
704 // This allows for writing pointers to already written strings
705 out.writeObject(namespace.getPrefix());
706 out.writeObject(namespace.getURI());
707 }
708
709 private void readObject(final ObjectInputStream in)
710 throws IOException, ClassNotFoundException {
711
712 in.defaultReadObject();
713
714 namespace = Namespace.getNamespace(
715 (String) in.readObject(), (String) in.readObject());
716 }
717 }