001package com.hfg.xml; 002 003import org.w3c.dom.*; 004 005import com.hfg.util.StringUtil; 006 007//------------------------------------------------------------------------------ 008/** 009 010 @author J. Alex Taylor, hairyfatguy.com 011 */ 012//------------------------------------------------------------------------------ 013 014 015public class XMLAttribute implements Node, Cloneable, Comparable<XMLAttribute> 016{ 017 018 //########################################################################### 019 // PRIVATE FIELDS 020 //########################################################################### 021 022 private String mLocalName; 023 private String mValue; 024 private XMLNamespace mNamespace; 025 private XMLTag mElement; // Reference to the element to which this attribute belongs. 026 027 //########################################################################### 028 // CONSTRUCTORS 029 //########################################################################### 030 031 //--------------------------------------------------------------------------- 032 public XMLAttribute(String inName, Object inValue) 033 { 034 setName(inName); 035 setValue(inValue); 036 } 037 038 //--------------------------------------------------------------------------- 039 public XMLAttribute(String inName, Object inValue, XMLNamespace inNamespace) 040 { 041 this(inName, inValue); 042 mNamespace = inNamespace; 043 } 044 045 //--------------------------------------------------------------------------- 046 public XMLAttribute(XMLName inName, Object inValue) 047 { 048 setName(inName.getLocalName()); 049 mNamespace = inName.getNamespace(); 050 setValue(inValue); 051 } 052 053 054 055 //########################################################################### 056 // PUBLIC METHODS 057 //########################################################################### 058 059 060 //--------------------------------------------------------------------------- 061 @Override 062 public XMLAttribute clone() 063 { 064 XMLAttribute obj = null; 065 try 066 { 067 obj = (XMLAttribute) super.clone(); 068 } 069 catch (CloneNotSupportedException e) 070 { 071 throw new RuntimeException(e.toString()); 072 } 073 074 return obj; 075 } 076 077 //--------------------------------------------------------------------------- 078 /** 079 XMLAttribute equality and comparison is based on the name. 080 */ 081 public int compareTo(XMLAttribute inAttr2) 082 { 083 if (null == inAttr2) 084 { 085 return 1; 086 } 087 088 return getName().compareTo(inAttr2.getName()); 089 } 090 091 092 //--------------------------------------------------------------------------- 093 public String getName() 094 { 095 return mLocalName; 096 } 097 098 //-------------------------------------------------------------------------- 099 /** 100 Sets the attribute's local name 101 */ 102 public void setName(String inName) 103 { 104 if (null == inName) 105 { 106 throw new InvalidXMLNameException("XML attribute names cannot be set to null!"); 107 } 108 109 // Is there a namespace prefix on the name? 110 int index = inName.indexOf(":"); 111 if (index > 0) 112 { 113 setNamespace(XMLNamespace.getNamespace(inName.substring(0, index), null)); 114 inName = inName.substring(index + 1); 115 } 116 117 // Check the name for XML validity. 118 XMLUtil.checkXMLNameValidity(inName); 119 120 mLocalName = inName; 121 } 122 123 124 //--------------------------------------------------------------------------- 125 public String getQualifiedName() 126 { 127 return (mNamespace != null && StringUtil.isSet(mNamespace.getPrefix()) ? mNamespace.getPrefix() + ":" : "") + mLocalName; 128 } 129 130 //--------------------------------------------------------------------------- 131 public String getValue() 132 { 133 return mValue; 134 } 135 136 //--------------------------------------------------------------------------- 137 public void setValue(Object inValue) 138 { 139 mValue = null; 140 if (inValue != null) 141 { 142 mValue = inValue.toString(); 143 } 144 } 145 146 //--------------------------------------------------------------------------- 147 public String getUnscapedValue() 148 { 149 return XMLUtil.unescapeAttributeValue(mValue); 150 } 151 152 //--------------------------------------------------------------------------- 153 public String getEscapedValue() 154 { 155 return XMLUtil.escapeAttributeValue(mValue); 156 } 157 158 //--------------------------------------------------------------------------- 159 public XMLNamespace getNamespace() 160 { 161 // Dynamically look up the chain for the first namespace instance. XXXXXXXXXXXXX 162 return mNamespace; 163 } 164 165 //--------------------------------------------------------------------------- 166 public void setNamespace(XMLNamespace inNamespace) 167 { 168 // Dynamically look up the chain for the first namespace instance. XXXXXXXXXXXXX 169 mNamespace = inNamespace; 170 } 171 172 // Methods for the Node interface. 173 174 //--------------------------------------------------------------------------- 175 /** 176 Returns the attribute name. 177 */ 178 public String getNodeName() 179 { 180 return mLocalName; 181 } 182 183 //--------------------------------------------------------------------------- 184 public String getNodeValue() throws DOMException 185 { 186 return getValue(); 187 } 188 189 //--------------------------------------------------------------------------- 190 public void setNodeValue(String inValue) throws DOMException 191 { 192 setValue(inValue); 193 } 194 195 //--------------------------------------------------------------------------- 196 public short getNodeType() 197 { 198 return Node.ATTRIBUTE_NODE; 199 } 200 201 //--------------------------------------------------------------------------- 202 public Node getParentNode() 203 { 204 return null; 205 } 206 207 //--------------------------------------------------------------------------- 208 public NodeList getChildNodes() 209 { 210 return null; //TODO 211 } 212 213 //--------------------------------------------------------------------------- 214 public Node getFirstChild() 215 { 216 return null; 217 } 218 219 //--------------------------------------------------------------------------- 220 public Node getLastChild() 221 { 222 return null; 223 } 224 225 //--------------------------------------------------------------------------- 226 public Node getPreviousSibling() 227 { 228 return null; //TODO 229 } 230 231 //--------------------------------------------------------------------------- 232 public Node getNextSibling() 233 { 234 return null; //TODO 235 } 236 237 //--------------------------------------------------------------------------- 238 public NamedNodeMap getAttributes() 239 { 240 return null; 241 } 242 243 //--------------------------------------------------------------------------- 244 public Document getOwnerDocument() 245 { 246 return null; //TODO 247 } 248 249 //--------------------------------------------------------------------------- 250 public Node insertBefore(Node node, Node node1) throws DOMException 251 { 252 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 253 "insertBefore() cannot be used on an attribute node!"); 254 } 255 256 //--------------------------------------------------------------------------- 257 public Node replaceChild(Node node, Node node1) throws DOMException 258 { 259 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 260 "replaceChild() cannot be used on an attribute node!"); 261 } 262 263 //--------------------------------------------------------------------------- 264 public Node removeChild(Node node) throws DOMException 265 { 266 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 267 "removeChild() cannot be used on an attribute node!"); 268 } 269 270 //--------------------------------------------------------------------------- 271 public Node appendChild(Node node) throws DOMException 272 { 273 throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR, 274 "appendChild() cannot be used on an attribute node!"); 275 } 276 277 //--------------------------------------------------------------------------- 278 public boolean hasChildNodes() 279 { 280 return false; 281 } 282 283 //--------------------------------------------------------------------------- 284 public Node cloneNode(boolean b) 285 { 286 return clone(); 287 } 288 289 //--------------------------------------------------------------------------- 290 public void normalize() 291 { 292 293 } 294 295 //--------------------------------------------------------------------------- 296 public boolean isSupported(String inFeature, String inVersion) 297 { 298 return false; 299 } 300 301 //--------------------------------------------------------------------------- 302 /** 303 Convenience method to get the namespace URI 304 */ 305 public String getNamespaceURI() 306 { 307 String uri = null; 308 309 XMLNamespace namespace = getNamespace(); 310 if (namespace != null) 311 { 312 uri = namespace.getURI(); 313 } 314 315 return uri; 316 } 317 318 //--------------------------------------------------------------------------- 319 /** 320 The namespace prefix of this attribute, or null if it is unspecified. 321 */ 322 public String getPrefix() 323 { 324 String prefix = null; 325 326 XMLNamespace namespace = getNamespace(); 327 if (namespace != null) 328 { 329 prefix = namespace.getPrefix(); 330 } 331 332 return prefix; 333 } 334 335 //--------------------------------------------------------------------------- 336 /** 337 The namespace prefix of this attribute, or null if it is unspecified. 338 */ 339 public void setPrefix(String inValue) throws DOMException 340 { 341 XMLNamespace namespace = (inValue != null ? XMLNamespace.getNamespaceViaPrefix(inValue) : null); 342 setNamespace(namespace); 343 } 344 345 //--------------------------------------------------------------------------- 346 /** 347 Returns the local part of the qualified name of this node. 348 */ 349 public String getLocalName() 350 { 351 return mLocalName; 352 } 353 354 //--------------------------------------------------------------------------- 355 public boolean hasAttributes() 356 { 357 return false; 358 } 359 360 //--------------------------------------------------------------------------- 361 public String getBaseURI() 362 { 363 return null; // TODO 364 } 365 366 //--------------------------------------------------------------------------- 367 public short compareDocumentPosition(Node node) throws DOMException 368 { 369 return 0; // TODO 370 } 371 372 //--------------------------------------------------------------------------- 373 public String getTextContent() throws DOMException 374 { 375 return null; 376 } 377 378 //--------------------------------------------------------------------------- 379 public void setTextContent(String string) throws DOMException 380 { 381 382 } 383 384 //--------------------------------------------------------------------------- 385 public boolean isSameNode(Node node) 386 { 387 return false; 388 } 389 390 //--------------------------------------------------------------------------- 391 public String lookupPrefix(String string) 392 { 393 return null; 394 } 395 396 //--------------------------------------------------------------------------- 397 public boolean isDefaultNamespace(String string) 398 { 399 return false; 400 } 401 402 //--------------------------------------------------------------------------- 403 /** 404 Look up the namespace URI associated to the given prefix, starting from this node. 405 */ 406 public String lookupNamespaceURI(String inPrefix) 407 { 408 return null; 409 } 410 411 //--------------------------------------------------------------------------- 412 public boolean isEqualNode(Node node) 413 { 414 return false; 415 } 416 417 //--------------------------------------------------------------------------- 418 public Object getFeature(String string, String string1) 419 { 420 return null; 421 } 422 423 //--------------------------------------------------------------------------- 424 public Object setUserData(String string, Object object, UserDataHandler userDataHandler) 425 { 426 return null; 427 } 428 429 //--------------------------------------------------------------------------- 430 public Object getUserData(String string) 431 { 432 return null; 433 } 434 435 //########################################################################### 436 // PROTECTED METHODS 437 //########################################################################### 438 439 //--------------------------------------------------------------------------- 440 protected void setElement(XMLTag inOwner) 441 { 442 mElement = inOwner; 443 } 444 445 //--------------------------------------------------------------------------- 446 protected XMLTag getElement() 447 { 448 return mElement; 449 } 450 451}