| 1 package org.sapia.util.xml.idefix; 2 3 4 import org.sapia.util.xml.Attribute; 7 import org.sapia.util.xml.CData; 8 import org.sapia.util.xml.Namespace; 9 10 import java.util.HashMap ; 13 import java.util.Iterator ; 14 import java.util.LinkedList ; 15 import java.util.Map ; 16 17 18 28 public class XmlBuffer { 29 33 34 public static final String DEFAULT_CHARACTER_ENCODING = "UTF-8"; 35 36 40 41 private XmlScribe _theScribe; 42 43 44 private StringBuffer _theBuffer; 45 46 47 private boolean _useXmlDeclaration; 48 49 50 private String _theCharacterEncoding; 51 52 53 private Map _theNamespaceByURI; 54 55 56 private LinkedList _theStates; 57 58 62 65 public XmlBuffer() { 66 this(false); 67 } 68 69 72 public XmlBuffer(boolean insertXmlDeclaration) { 73 this(DEFAULT_CHARACTER_ENCODING); 74 _useXmlDeclaration = insertXmlDeclaration; 75 } 76 77 80 public XmlBuffer(String aCharacterEncoding) { 81 _theScribe = new XmlScribe(aCharacterEncoding); 82 _theBuffer = new StringBuffer (); 83 _useXmlDeclaration = true; 84 _theCharacterEncoding = aCharacterEncoding; 85 _theNamespaceByURI = new HashMap (); 86 _theStates = new LinkedList (); 87 } 88 89 93 99 public String getNamespacePrefix(String aNamespaceURI) { 100 LinkedList someNamespaces = (LinkedList ) _theNamespaceByURI.get(aNamespaceURI); 101 102 if (someNamespaces == null) { 103 return null; 104 } else { 105 NamespaceReference aNamespaceRef = (NamespaceReference) someNamespaces.getFirst(); 106 107 return aNamespaceRef.getNamespace().getPrefix(); 108 } 109 } 110 111 117 public boolean isEmpty() { 118 return ((_theBuffer.length() == 0) && _theStates.isEmpty()); 119 } 120 121 125 136 public XmlBuffer addNamespace(String aNamespaceURI, String aNamespacePrefix) { 137 if (aNamespaceURI == null) { 139 throw new IllegalArgumentException ("The namespace URI passed in null"); 140 } 141 142 LinkedList someNamespaces = (LinkedList ) _theNamespaceByURI.get(aNamespaceURI); 144 145 if (someNamespaces == null) { 146 someNamespaces = new LinkedList (); 147 _theNamespaceByURI.put(aNamespaceURI, someNamespaces); 148 } 149 150 if (aNamespacePrefix == null) { 152 aNamespacePrefix = ""; 153 } 154 155 Namespace aNamespace = new Namespace(aNamespaceURI, aNamespacePrefix); 156 157 if (someNamespaces.isEmpty()) { 159 someNamespaces.addFirst(new NamespaceReference(aNamespace)); 160 } else { 161 NamespaceReference aNamespaceRef = (NamespaceReference) someNamespaces.getFirst(); 162 163 if (aNamespace.equals(aNamespaceRef.getNamespace())) { 165 aNamespaceRef.addReference(); 166 } else { 167 someNamespaces.addFirst(new NamespaceReference(aNamespace)); 168 } 169 } 170 171 return this; 172 } 173 174 182 public XmlBuffer removeNamespace(String aNamespaceURI) { 183 if (aNamespaceURI == null) { 185 throw new IllegalArgumentException ("The namespace URI passed in null"); 186 } 187 188 LinkedList someNamespaces = (LinkedList ) _theNamespaceByURI.get(aNamespaceURI); 190 191 if (someNamespaces == null) { 192 throw new IllegalStateException ("No namespace found for the URI " + 193 aNamespaceURI); 194 } 195 196 NamespaceReference aNamespaceRef = (NamespaceReference) someNamespaces.getFirst(); 198 199 if (aNamespaceRef.getReferenceCount() == 1) { 200 someNamespaces.removeFirst(); 201 } else { 202 aNamespaceRef.removeReference(); 203 } 204 205 return this; 206 } 207 208 215 public XmlBuffer startElement(String anElementName) { 216 return startElement(null, anElementName); 217 } 218 219 227 public XmlBuffer startElement(String aNamespaceURI, String anElementName) { 228 if (anElementName == null) { 229 throw new IllegalArgumentException ("The element name passed in is null"); 230 } 231 232 BufferState aParentState = null; 233 234 if (!_theStates.isEmpty()) { 235 aParentState = (BufferState) _theStates.getFirst(); 236 } 237 238 validateStartingXmlGeneration(aParentState); 239 240 String aPrefix = getNamespacePrefix(aNamespaceURI); 241 Namespace aNamespace = new Namespace(aNamespaceURI, aPrefix); 242 BufferState aState = new BufferState(aParentState, aNamespace, 243 anElementName); 244 aState.addDeclaredNamespace(aNamespace); 245 _theStates.addFirst(aState); 246 247 return this; 248 } 249 250 257 public XmlBuffer addContent(String aContent) { 258 if (_theStates.isEmpty()) { 259 throw new IllegalStateException ("Could not add content [" + aContent + 260 "] there is no element started"); 261 } 262 263 BufferState aState = (BufferState) _theStates.getFirst(); 264 validateStartingXmlGeneration(aState); 265 _theScribe.xmlEncode(aContent, aState.getContent()); 266 267 return this; 268 } 269 270 277 public XmlBuffer addContent(CData aCData) { 278 if (_theStates.isEmpty()) { 279 throw new IllegalStateException ("Could not add CData [" + aCData + 280 "] there is no element started"); 281 } 282 283 BufferState aState = (BufferState) _theStates.getFirst(); 284 validateStartingXmlGeneration(aState); 285 _theScribe.composeCData(aCData.toString(), aState.getContent()); 286 287 return this; 288 } 289 290 299 public XmlBuffer endElement(String anElementName) { 300 return endElement(null, anElementName); 301 } 302 303 313 public XmlBuffer endElement(String aNamespaceURI, String anElementName) { 314 if (anElementName == null) { 315 throw new IllegalArgumentException ("The element name passed in is null"); 316 } else if (_theStates.isEmpty()) { 317 throw new IllegalStateException ("Could not end the element [" + 318 anElementName + "] on an empty xml buffer"); 319 } 320 321 BufferState aState = (BufferState) _theStates.removeFirst(); 322 323 if (!anElementName.equals(aState.getElementName())) { 324 throw new IllegalArgumentException ("The element name to end [" + 325 anElementName + "] does not match the starting tag [" + 326 aState.getElementName() + "]"); 327 } else if (((aNamespaceURI != null) && 328 !aNamespaceURI.equals(aState.getElementNamespace().getURI())) || 329 ((aNamespaceURI == null) && 330 (aState.getElementNamespace().getURI() != null))) { 331 throw new IllegalArgumentException ("The namespace URI to end [" + 332 aNamespaceURI + "] does not match the starting namespace URI [" + 333 aState.getElementNamespace().getURI() + "]"); 334 } 335 336 if (_theStates.isEmpty()) { 337 generateCompleteXmlFor(aState, _theBuffer); 338 } else { 339 BufferState aParentState = (BufferState) _theStates.getFirst(); 340 generateCompleteXmlFor(aState, aParentState.getNestedXmlString()); 341 } 342 343 return this; 344 } 345 346 355 public XmlBuffer addAttribute(String aName, String aValue) { 356 return addAttribute(null, aName, aValue); 357 } 358 359 369 public XmlBuffer addAttribute(String aNamespaceURI, String aName, 370 String aValue) { 371 if (_theStates.isEmpty()) { 372 throw new IllegalStateException ("Could not add the attribute [" + aName + 373 "] on an empty xml buffer"); 374 } 375 376 BufferState aState = (BufferState) _theStates.getFirst(); 377 378 if (!aState.isGettingMoreAttribute()) { 379 throw new IllegalStateException ("Could not add the attribute [" + aName + 380 "] on element for which the endAttribute() methos was previously called"); 381 } 382 383 String aPrefix = getNamespacePrefix(aNamespaceURI); 384 Attribute anAttribute = new Attribute(aPrefix, aName, aValue); 385 aState.addAttribute(anAttribute); 386 387 Namespace aNamespace = new Namespace(aNamespaceURI, aPrefix); 388 aState.addDeclaredNamespace(aNamespace); 389 390 return this; 391 } 392 393 400 public XmlBuffer endAttribute() { 401 if (_theStates.isEmpty()) { 404 throw new IllegalStateException ("There is no current element"); 405 } 406 407 BufferState aState = (BufferState) _theStates.getFirst(); 408 aState.setIsGettingMoreAttribute(false); 409 410 return this; 411 } 412 413 419 private void generateCompleteXmlFor(BufferState aState, StringBuffer aBuffer) { 420 if (!aState.isStartElementGenerated()) { 421 generateStartingXmlFor(aState, aBuffer, true); 422 423 if (!aState.isElementEmpty()) { 424 if (!aState.isNestedXMLEmpty()) { 425 aBuffer.append(aState.getNestedXmlString().toString()); 426 } 427 428 if (!aState.isContentEmpty()) { 429 aBuffer.append(aState.getContent().toString()); 430 } 431 432 _theScribe.composeEndingElement(aState.getElementNamespace().getPrefix(), 433 aState.getElementName(), aBuffer); 434 } 435 } else if (!aState.isElementEmpty()) { 436 if (!aState.isContentEmpty()) { 437 aBuffer.append(aState.getContent().toString()); 438 } 439 440 _theScribe.composeEndingElement(aState.getElementNamespace().getPrefix(), 441 aState.getElementName(), aBuffer); 442 } 443 } 444 445 452 private void validateStartingXmlGeneration(BufferState aState) { 453 if ((aState != null) && !aState.isGettingMoreAttribute() && 454 !aState.isStartElementGenerated()) { 455 if (aState.getParent() == null) { 456 generateStartingXmlFor(aState, _theBuffer, false); 457 aState.setNestedXmlString(_theBuffer); 458 } else { 459 generateStartingXmlFor(aState, aState.getParent().getNestedXmlString(), 460 false); 461 aState.setNestedXmlString(aState.getParent().getNestedXmlString()); 462 } 463 } 464 } 465 466 472 private void generateStartingXmlFor(BufferState aState, StringBuffer aBuffer, 473 boolean isClosingElement) { 474 int anIndex = 0; 475 476 for (Iterator it = aState.getDeclaredNamespaces().iterator(); it.hasNext(); 477 anIndex++) { 478 Namespace aNamespace = (Namespace) it.next(); 479 480 if ((aNamespace.getPrefix() == null) || 481 (aNamespace.getPrefix().length() == 0)) { 482 Attribute anAttribute = new Attribute("xmlns", aNamespace.getURI()); 483 aState.addAttribute(anIndex, anAttribute); 484 } else { 485 Attribute anAttribute = new Attribute("xmlns", aNamespace.getPrefix(), 486 aNamespace.getURI()); 487 aState.addAttribute(anIndex, anAttribute); 488 } 489 } 490 491 if (isClosingElement && aState.isElementEmpty()) { 492 _theScribe.composeStartingElement(aState.getElementNamespace().getPrefix(), 493 aState.getElementName(), aState.getAttributes(), true, aBuffer); 494 } else { 495 _theScribe.composeStartingElement(aState.getElementNamespace().getPrefix(), 496 aState.getElementName(), aState.getAttributes(), false, aBuffer); 497 } 498 499 aState.setIsStartElementGenerated(true); 500 } 501 502 506 511 public String toString() { 512 if (_useXmlDeclaration) { 513 StringBuffer aBuffer = new StringBuffer (); 514 _theScribe.composeXmlDeclaration(_theCharacterEncoding, aBuffer); 515 aBuffer.append(_theBuffer.toString()); 516 517 return aBuffer.toString(); 518 } else { 519 return _theBuffer.toString(); 520 } 521 } 522 523 public static class NamespaceReference { 524 private Namespace _theNamespace; 525 private int _theReferenceCount; 526 527 public NamespaceReference(Namespace aNamespace) { 528 _theNamespace = aNamespace; 529 _theReferenceCount = 1; 530 } 531 532 public int getReferenceCount() { 533 return _theReferenceCount; 534 } 535 536 public Namespace getNamespace() { 537 return _theNamespace; 538 } 539 540 public void addReference() { 541 _theReferenceCount++; 542 } 543 544 public void removeReference() { 545 _theReferenceCount--; 546 } 547 } 548 } 549 | Popular Tags |