1 16 package org.apache.commons.betwixt.io; 17 18 import java.beans.IntrospectionException ; 19 import java.io.BufferedWriter ; 20 import java.io.IOException ; 21 import java.io.OutputStream ; 22 import java.io.OutputStreamWriter ; 23 import java.io.UnsupportedEncodingException ; 24 import java.io.Writer ; 25 26 import org.apache.commons.betwixt.XMLUtils; 27 import org.apache.commons.betwixt.strategy.MixedContentEncodingStrategy; 28 import org.apache.commons.logging.Log; 29 import org.apache.commons.logging.LogFactory; 30 import org.xml.sax.Attributes ; 31 import org.xml.sax.SAXException ; 32 33 79 public class BeanWriter extends AbstractBeanWriter { 80 81 82 private Writer writer; 83 84 private static final String EOL = "\n"; 85 86 private String endOfLine = EOL; 87 88 private String indent; 89 90 91 private boolean autoFlush; 92 93 private Log log = LogFactory.getLog( BeanWriter.class ); 94 95 private boolean currentElementIsEmpty = false; 96 97 private boolean currentElementHasBodyText = false; 98 99 private boolean closedStartTag = true; 100 101 private boolean addEndTagForEmptyElement = false; 102 103 private int indentLevel; 104 105 private MixedContentEncodingStrategy mixedContentEncodingStrategy 106 = MixedContentEncodingStrategy.DEFAULT; 107 108 111 public BeanWriter() { 112 this( System.out ); 113 } 114 115 120 public BeanWriter(OutputStream out) { 121 this.writer = new BufferedWriter ( new OutputStreamWriter ( out ) ); 122 this.autoFlush = true; 123 } 124 125 134 public BeanWriter(OutputStream out, String enc) throws UnsupportedEncodingException { 135 this.writer = new BufferedWriter ( new OutputStreamWriter ( out, enc ) ); 136 this.autoFlush = true; 137 } 138 139 144 public BeanWriter(Writer writer) { 145 this.writer = writer; 146 } 147 148 157 public void writeXmlDeclaration(String xmlDeclaration) throws IOException { 158 writer.write( xmlDeclaration ); 159 printLine(); 160 } 161 162 167 public void flush() throws IOException { 168 writer.flush(); 169 } 170 171 176 public void close() throws IOException { 177 writer.close(); 178 } 179 180 188 public void write(Object bean) throws IOException , SAXException , IntrospectionException { 189 190 super.write(bean); 191 192 if ( autoFlush ) { 193 writer.flush(); 194 } 195 } 196 197 198 203 public void enablePrettyPrint() { 204 endOfLine = EOL; 205 indent = " "; 206 } 207 208 213 public String getEndOfLine() { 214 return endOfLine; 215 } 216 217 223 public void setEndOfLine(String endOfLine) { 224 this.endOfLine = endOfLine; 225 for (int i = 0; i < endOfLine.length(); i++) { 226 if (!Character.isWhitespace(endOfLine.charAt(i))) { 227 log.warn("Invalid EndOfLine character(s)"); 228 break; 229 } 230 } 231 232 } 233 234 239 public String getIndent() { 240 return indent; 241 } 242 243 247 public void setIndent(String indent) { 248 this.indent = indent; 249 } 250 251 256 public Log getLog() { 257 return log; 258 } 259 260 265 public void setLog( Log log ) { 266 this.log = log; 267 } 268 269 276 public MixedContentEncodingStrategy getMixedContentEncodingStrategy() { 277 return mixedContentEncodingStrategy; 278 } 279 280 288 public void setMixedContentEncodingStrategy(MixedContentEncodingStrategy strategy) { 289 mixedContentEncodingStrategy = strategy; 290 } 291 292 301 public boolean isEndTagForEmptyElement() { 302 return addEndTagForEmptyElement; 303 } 304 305 315 public void setEndTagForEmptyElement(boolean addEndTagForEmptyElement) { 316 this.addEndTagForEmptyElement = addEndTagForEmptyElement; 317 } 318 319 320 321 324 325 336 protected void startElement( 337 WriteContext context, 338 String uri, 339 String localName, 340 String qualifiedName, 341 Attributes attr) 342 throws 343 IOException , 344 SAXException { 345 if ( !closedStartTag ) { 346 writer.write( '>' ); 347 printLine(); 348 } 349 350 indentLevel++; 351 352 indent(); 353 writer.write( '<' ); 354 writer.write( qualifiedName ); 355 356 for ( int i=0; i< attr.getLength(); i++ ) { 357 writer.write( ' ' ); 358 writer.write( attr.getQName(i) ); 359 writer.write( "=\"" ); 360 writer.write( XMLUtils.escapeAttributeValue( attr.getValue(i) ) ); 361 writer.write( '\"' ); 362 } 363 closedStartTag = false; 364 currentElementIsEmpty = true; 365 currentElementHasBodyText = false; 366 } 367 368 379 protected void endElement( 380 WriteContext context, 381 String uri, 382 String localName, 383 String qualifiedName) 384 throws 385 IOException , 386 SAXException { 387 if ( 388 !addEndTagForEmptyElement 389 && !closedStartTag 390 && currentElementIsEmpty ) { 391 392 writer.write( "/>" ); 393 closedStartTag = true; 394 395 } else { 396 if (!currentElementHasBodyText) { 397 indent(); 398 } 399 if ( 400 addEndTagForEmptyElement 401 && !closedStartTag ) { 402 writer.write( ">" ); 403 closedStartTag = true; 404 } 405 writer.write( "</" ); 406 writer.write( qualifiedName ); 407 writer.write( '>' ); 408 409 } 410 411 indentLevel--; 412 printLine(); 413 414 currentElementHasBodyText = false; 415 } 416 417 424 protected void bodyText(WriteContext context, String text) throws IOException { 425 if ( text == null ) { 426 log.error( "[expressBodyText]Body text is null" ); 428 429 } else { 430 if ( !closedStartTag ) { 431 writer.write( '>' ); 432 closedStartTag = true; 433 } 434 writer.write( 435 mixedContentEncodingStrategy.encode( 436 text, 437 context.getCurrentDescriptor()) ); 438 currentElementIsEmpty = false; 439 currentElementHasBodyText = true; 440 } 441 } 442 443 448 private void printLine() throws IOException { 449 if ( endOfLine != null ) { 450 writer.write( endOfLine ); 451 } 452 } 453 454 459 private void indent() throws IOException { 460 if ( indent != null ) { 461 for ( int i = 0; i < indentLevel; i++ ) { 462 writer.write( getIndent() ); 463 } 464 } 465 } 466 467 470 471 477 protected void writePrintln() throws IOException { 478 if ( endOfLine != null ) { 479 writer.write( endOfLine ); 480 } 481 } 482 483 489 protected void writeIndent() throws IOException { 490 if ( indent != null ) { 491 for ( int i = 0; i < indentLevel; i++ ) { 492 writer.write( getIndent() ); 493 } 494 } 495 } 496 497 505 protected String escapeBodyValue(Object value) { 506 return XMLUtils.escapeBodyValue(value); 507 } 508 509 518 protected String escapeAttributeValue(Object value) { 519 return XMLUtils.escapeAttributeValue(value); 520 } 521 522 529 protected void expressElementStart(String qualifiedName) throws IOException { 530 if ( qualifiedName == null ) { 531 log.fatal( "[expressElementStart]Qualified name is null." ); 533 throw new RuntimeException ( "Qualified name is null." ); 534 } 535 536 writePrintln(); 537 writeIndent(); 538 writer.write( '<' ); 539 writer.write( qualifiedName ); 540 } 541 542 548 protected void expressTagClose() throws IOException { 549 writer.write( '>' ); 550 } 551 552 559 protected void expressElementEnd(String qualifiedName) throws IOException { 560 if (qualifiedName == null) { 561 log.fatal( "[expressElementEnd]Qualified name is null." ); 563 throw new RuntimeException ( "Qualified name is null." ); 564 } 565 566 writer.write( "</" ); 567 writer.write( qualifiedName ); 568 writer.write( '>' ); 569 } 570 571 577 protected void expressElementEnd() throws IOException { 578 writer.write( "/>" ); 579 } 580 581 588 protected void expressBodyText(String text) throws IOException { 589 if ( text == null ) { 590 log.error( "[expressBodyText]Body text is null" ); 592 593 } else { 594 writer.write( XMLUtils.escapeBodyValue(text) ); 595 } 596 } 597 598 606 protected void expressAttribute( 607 String qualifiedName, 608 String value) 609 throws 610 IOException { 611 if ( value == null ) { 612 log.error( "Null attribute value." ); 614 return; 615 } 616 617 if ( qualifiedName == null ) { 618 log.error( "Null attribute value." ); 620 return; 621 } 622 623 writer.write( ' ' ); 624 writer.write( qualifiedName ); 625 writer.write( "=\"" ); 626 writer.write( XMLUtils.escapeAttributeValue(value) ); 627 writer.write( '\"' ); 628 } 629 630 631 } 632 | Popular Tags |