001package org.apache.maven.doxia.module.apt; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one 005 * or more contributor license agreements. See the NOTICE file 006 * distributed with this work for additional information 007 * regarding copyright ownership. The ASF licenses this file 008 * to you under the Apache License, Version 2.0 (the 009 * "License"); you may not use this file except in compliance 010 * with the License. You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, 015 * software distributed under the License is distributed on an 016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 017 * KIND, either express or implied. See the License for the 018 * specific language governing permissions and limitations 019 * under the License. 020 */ 021 022import java.io.PrintWriter; 023import java.io.Writer; 024import java.util.ArrayList; 025import java.util.List; 026import java.util.Stack; 027 028import org.apache.maven.doxia.sink.SinkEventAttributes; 029import org.apache.maven.doxia.sink.impl.AbstractTextSink; 030import org.apache.maven.doxia.sink.impl.SinkEventAttributeSet; 031import org.codehaus.plexus.util.StringUtils; 032 033/** 034 * APT generator implementation. 035 * <br> 036 * <b>Note</b>: The encoding used is UTF-8. 037 * 038 * @author eredmond 039 * @since 1.0 040 */ 041public class AptSink 042 extends AbstractTextSink 043 implements AptMarkup 044{ 045 // ---------------------------------------------------------------------- 046 // Instance fields 047 // ---------------------------------------------------------------------- 048 049 /** A buffer that holds the current text when headerFlag or bufferFlag set to <code>true</code>. */ 050 private StringBuffer buffer; 051 052 /** A buffer that holds the table caption. */ 053 private StringBuilder tableCaptionBuffer; 054 055 /** author. */ 056 private String author; 057 058 /** title. */ 059 private String title; 060 061 /** date. */ 062 private String date; 063 064 /** startFlag. */ 065 private boolean startFlag; 066 067 /** tableCaptionFlag. */ 068 private boolean tableCaptionFlag; 069 070 /** tableCellFlag. */ 071 private boolean tableCellFlag; 072 073 /** headerFlag. */ 074 private boolean headerFlag; 075 076 /** bufferFlag. */ 077 private boolean bufferFlag; 078 079 /** itemFlag. */ 080 private boolean itemFlag; 081 082 /** verbatimFlag. */ 083 private boolean verbatimFlag; 084 085 /** boxed verbatim. */ 086 private boolean isBoxed; 087 088 /** gridFlag for tables. */ 089 private boolean gridFlag; 090 091 /** number of cells in a table. */ 092 private int cellCount; 093 094 /** The writer to use. */ 095 private final PrintWriter writer; 096 097 /** justification of table cells. */ 098 private int[] cellJustif; 099 100 /** a line of a row in a table. */ 101 private String rowLine; 102 103 /** listNestingIndent. */ 104 private String listNestingIndent; 105 106 /** listStyles. */ 107 private final Stack<String> listStyles; 108 109 /** Keep track of the closing tags for inline events. */ 110 protected Stack<List<String>> inlineStack = new Stack<>(); 111 112 // ---------------------------------------------------------------------- 113 // Public protected methods 114 // ---------------------------------------------------------------------- 115 116 /** 117 * Constructor, initialize the Writer and the variables. 118 * 119 * @param writer not null writer to write the result. <b>Should</b> be an UTF-8 Writer. 120 * You could use <code>newWriter</code> methods from {@link org.codehaus.plexus.util.WriterFactory}. 121 */ 122 protected AptSink( Writer writer ) 123 { 124 this.writer = new PrintWriter( writer ); 125 this.listStyles = new Stack<>(); 126 127 init(); 128 } 129 130 /** 131 * Returns the buffer that holds the current text. 132 * 133 * @return A StringBuffer. 134 */ 135 protected StringBuffer getBuffer() 136 { 137 return buffer; 138 } 139 140 /** 141 * Used to determine whether we are in head mode. 142 * 143 * @param headFlag True for head mode. 144 */ 145 protected void setHeadFlag( boolean headFlag ) 146 { 147 this.headerFlag = headFlag; 148 } 149 150 /** 151 * Reset all variables. 152 * 153 * @deprecated since 1.1.2, use {@link #init()} instead of. 154 */ 155 protected void resetState() 156 { 157 init(); 158 } 159 160 /** 161 * {@inheritDoc} 162 */ 163 protected void init() 164 { 165 super.init(); 166 167 resetBuffer(); 168 169 this.tableCaptionBuffer = new StringBuilder(); 170 this.listNestingIndent = ""; 171 172 this.author = null; 173 this.title = null; 174 this.date = null; 175 this.startFlag = true; 176 this.tableCaptionFlag = false; 177 this.tableCellFlag = false; 178 this.headerFlag = false; 179 this.bufferFlag = false; 180 this.itemFlag = false; 181 this.verbatimFlag = false; 182 this.isBoxed = false; 183 this.gridFlag = false; 184 this.cellCount = 0; 185 this.cellJustif = null; 186 this.rowLine = null; 187 this.listStyles.clear(); 188 this.inlineStack.clear(); 189 } 190 191 /** 192 * Reset the StringBuilder. 193 */ 194 protected void resetBuffer() 195 { 196 buffer = new StringBuffer(); 197 } 198 199 /** 200 * Reset the TableCaptionBuffer. 201 */ 202 protected void resetTableCaptionBuffer() 203 { 204 tableCaptionBuffer = new StringBuilder(); 205 } 206 207 /** 208 * {@inheritDoc} 209 */ 210 public void head() 211 { 212 boolean startFlag = this.startFlag; 213 214 init(); 215 216 headerFlag = true; 217 this.startFlag = startFlag; 218 } 219 220 /** 221 * {@inheritDoc} 222 */ 223 public void head_() 224 { 225 headerFlag = false; 226 227 if ( ! startFlag ) 228 { 229 write( EOL ); 230 } 231 write( HEADER_START_MARKUP + EOL ); 232 if ( title != null ) 233 { 234 write( " " + title + EOL ); 235 } 236 write( HEADER_START_MARKUP + EOL ); 237 if ( author != null ) 238 { 239 write( " " + author + EOL ); 240 } 241 write( HEADER_START_MARKUP + EOL ); 242 if ( date != null ) 243 { 244 write( " " + date + EOL ); 245 } 246 write( HEADER_START_MARKUP + EOL ); 247 } 248 249 /** 250 * {@inheritDoc} 251 */ 252 public void title_() 253 { 254 if ( buffer.length() > 0 ) 255 { 256 title = buffer.toString(); 257 resetBuffer(); 258 } 259 } 260 261 /** 262 * {@inheritDoc} 263 */ 264 public void author_() 265 { 266 if ( buffer.length() > 0 ) 267 { 268 author = buffer.toString(); 269 resetBuffer(); 270 } 271 } 272 273 /** 274 * {@inheritDoc} 275 */ 276 public void date_() 277 { 278 if ( buffer.length() > 0 ) 279 { 280 date = buffer.toString(); 281 resetBuffer(); 282 } 283 } 284 285 /** 286 * {@inheritDoc} 287 */ 288 public void section1_() 289 { 290 write( EOL ); 291 } 292 293 /** 294 * {@inheritDoc} 295 */ 296 public void section2_() 297 { 298 write( EOL ); 299 } 300 301 /** 302 * {@inheritDoc} 303 */ 304 public void section3_() 305 { 306 write( EOL ); 307 } 308 309 /** 310 * {@inheritDoc} 311 */ 312 public void section4_() 313 { 314 write( EOL ); 315 } 316 317 /** 318 * {@inheritDoc} 319 */ 320 public void section5_() 321 { 322 write( EOL ); 323 } 324 325 /** 326 * {@inheritDoc} 327 */ 328 public void sectionTitle1() 329 { 330 write( EOL ); 331 } 332 333 /** 334 * {@inheritDoc} 335 */ 336 public void sectionTitle1_() 337 { 338 write( EOL + EOL ); 339 } 340 341 /** 342 * {@inheritDoc} 343 */ 344 public void sectionTitle2() 345 { 346 write( EOL + SECTION_TITLE_START_MARKUP ); 347 } 348 349 /** 350 * {@inheritDoc} 351 */ 352 public void sectionTitle2_() 353 { 354 write( EOL + EOL ); 355 } 356 357 /** 358 * {@inheritDoc} 359 */ 360 public void sectionTitle3() 361 { 362 write( EOL + StringUtils.repeat( SECTION_TITLE_START_MARKUP, 2 ) ); 363 } 364 365 /** 366 * {@inheritDoc} 367 */ 368 public void sectionTitle3_() 369 { 370 write( EOL + EOL ); 371 } 372 373 /** 374 * {@inheritDoc} 375 */ 376 public void sectionTitle4() 377 { 378 write( EOL + StringUtils.repeat( SECTION_TITLE_START_MARKUP, 3 ) ); 379 } 380 381 /** 382 * {@inheritDoc} 383 */ 384 public void sectionTitle4_() 385 { 386 write( EOL + EOL ); 387 } 388 389 /** 390 * {@inheritDoc} 391 */ 392 public void sectionTitle5() 393 { 394 write( EOL + StringUtils.repeat( SECTION_TITLE_START_MARKUP, 4 ) ); 395 } 396 397 /** 398 * {@inheritDoc} 399 */ 400 public void sectionTitle5_() 401 { 402 write( EOL + EOL ); 403 } 404 405 /** 406 * {@inheritDoc} 407 */ 408 public void list() 409 { 410 listNestingIndent += " "; 411 listStyles.push( LIST_START_MARKUP ); 412 write( EOL ); 413 } 414 415 /** 416 * {@inheritDoc} 417 */ 418 public void list_() 419 { 420 if ( listNestingIndent.length() <= 1 ) 421 { 422 write( EOL + listNestingIndent + LIST_END_MARKUP + EOL ); 423 } 424 else 425 { 426 write( EOL ); 427 } 428 listNestingIndent = StringUtils.chomp( listNestingIndent, " " ); 429 listStyles.pop(); 430 itemFlag = false; 431 } 432 433 /** 434 * {@inheritDoc} 435 */ 436 public void listItem() 437 { 438 //if ( !numberedList ) 439 //write( EOL + listNestingIndent + "*" ); 440 //else 441 numberedListItem(); 442 itemFlag = true; 443 } 444 445 /** 446 * {@inheritDoc} 447 */ 448 public void listItem_() 449 { 450 write( EOL ); 451 itemFlag = false; 452 } 453 454 /** {@inheritDoc} */ 455 public void numberedList( int numbering ) 456 { 457 listNestingIndent += " "; 458 write( EOL ); 459 460 String style; 461 switch ( numbering ) 462 { 463 case NUMBERING_UPPER_ALPHA: 464 style = String.valueOf( NUMBERING_UPPER_ALPHA_CHAR ); 465 break; 466 case NUMBERING_LOWER_ALPHA: 467 style = String.valueOf( NUMBERING_LOWER_ALPHA_CHAR ); 468 break; 469 case NUMBERING_UPPER_ROMAN: 470 style = String.valueOf( NUMBERING_UPPER_ROMAN_CHAR ); 471 break; 472 case NUMBERING_LOWER_ROMAN: 473 style = String.valueOf( NUMBERING_LOWER_ROMAN_CHAR ); 474 break; 475 case NUMBERING_DECIMAL: 476 default: 477 style = String.valueOf( NUMBERING ); 478 } 479 480 listStyles.push( style ); 481 } 482 483 /** 484 * {@inheritDoc} 485 */ 486 public void numberedList_() 487 { 488 if ( listNestingIndent.length() <= 1 ) 489 { 490 write( EOL + listNestingIndent + LIST_END_MARKUP + EOL ); 491 } 492 else 493 { 494 write( EOL ); 495 } 496 listNestingIndent = StringUtils.chomp( listNestingIndent, " " ); 497 listStyles.pop(); 498 itemFlag = false; 499 } 500 501 /** 502 * {@inheritDoc} 503 */ 504 public void numberedListItem() 505 { 506 String style = listStyles.peek(); 507 if ( style.equals( String.valueOf( STAR ) ) ) 508 { 509 write( EOL + listNestingIndent + STAR + SPACE ); 510 } 511 else 512 { 513 write( EOL + listNestingIndent + LEFT_SQUARE_BRACKET 514 + LEFT_SQUARE_BRACKET + style + RIGHT_SQUARE_BRACKET 515 + RIGHT_SQUARE_BRACKET + SPACE ); 516 } 517 itemFlag = true; 518 } 519 520 /** 521 * {@inheritDoc} 522 */ 523 public void numberedListItem_() 524 { 525 write( EOL ); 526 itemFlag = false; 527 } 528 529 /** 530 * {@inheritDoc} 531 */ 532 public void definitionList() 533 { 534 listNestingIndent += " "; 535 listStyles.push( "" ); 536 write( EOL ); 537 } 538 539 /** 540 * {@inheritDoc} 541 */ 542 public void definitionList_() 543 { 544 if ( listNestingIndent.length() <= 1 ) 545 { 546 write( EOL + listNestingIndent + LIST_END_MARKUP + EOL ); 547 } 548 else 549 { 550 write( EOL ); 551 } 552 listNestingIndent = StringUtils.chomp( listNestingIndent, " " ); 553 listStyles.pop(); 554 itemFlag = false; 555 } 556 557 /** 558 * {@inheritDoc} 559 */ 560 public void definedTerm() 561 { 562 write( EOL + " [" ); 563 } 564 565 /** 566 * {@inheritDoc} 567 */ 568 public void definedTerm_() 569 { 570 write( "] " ); 571 } 572 573 /** 574 * {@inheritDoc} 575 */ 576 public void definition() 577 { 578 itemFlag = true; 579 } 580 581 /** 582 * {@inheritDoc} 583 */ 584 public void definition_() 585 { 586 write( EOL ); 587 itemFlag = false; 588 } 589 590 /** 591 * {@inheritDoc} 592 */ 593 public void pageBreak() 594 { 595 write( EOL + PAGE_BREAK + EOL ); 596 } 597 598 /** 599 * {@inheritDoc} 600 */ 601 public void paragraph() 602 { 603 if ( tableCellFlag ) 604 { 605 // ignore paragraphs in table cells 606 } 607 else if ( itemFlag ) 608 { 609 write( EOL + EOL + " " + listNestingIndent ); 610 } 611 else 612 { 613 write( EOL + " " ); 614 } 615 } 616 617 /** 618 * {@inheritDoc} 619 */ 620 public void paragraph_() 621 { 622 if ( tableCellFlag ) 623 { 624 // ignore paragraphs in table cells 625 } 626 else 627 { 628 write( EOL + EOL ); 629 } 630 } 631 632 /** {@inheritDoc} */ 633 public void verbatim( boolean boxed ) 634 { 635 verbatimFlag = true; 636 this.isBoxed = boxed; 637 write( EOL ); 638 if ( boxed ) 639 { 640 write( EOL + BOXED_VERBATIM_START_MARKUP + EOL ); 641 } 642 else 643 { 644 write( EOL + NON_BOXED_VERBATIM_START_MARKUP + EOL ); 645 } 646 } 647 648 /** 649 * {@inheritDoc} 650 */ 651 public void verbatim_() 652 { 653 if ( isBoxed ) 654 { 655 write( EOL + BOXED_VERBATIM_END_MARKUP + EOL ); 656 } 657 else 658 { 659 write( EOL + NON_BOXED_VERBATIM_END_MARKUP + EOL ); 660 } 661 isBoxed = false; 662 verbatimFlag = false; 663 } 664 665 /** 666 * {@inheritDoc} 667 */ 668 public void horizontalRule() 669 { 670 write( EOL + HORIZONTAL_RULE_MARKUP + EOL ); 671 } 672 673 /** 674 * {@inheritDoc} 675 */ 676 public void table() 677 { 678 write( EOL ); 679 } 680 681 /** 682 * {@inheritDoc} 683 */ 684 public void table_() 685 { 686 if ( rowLine != null ) 687 { 688 write( rowLine ); 689 } 690 rowLine = null; 691 692 if ( tableCaptionBuffer.length() > 0 ) 693 { 694 text( tableCaptionBuffer.toString() + EOL ); 695 } 696 697 resetTableCaptionBuffer(); 698 } 699 700 /** {@inheritDoc} */ 701 public void tableRows( int[] justification, boolean grid ) 702 { 703 cellJustif = justification; 704 gridFlag = grid; 705 } 706 707 /** 708 * {@inheritDoc} 709 */ 710 public void tableRows_() 711 { 712 cellJustif = null; 713 gridFlag = false; 714 } 715 716 /** 717 * {@inheritDoc} 718 */ 719 public void tableRow() 720 { 721 bufferFlag = true; 722 cellCount = 0; 723 } 724 725 /** 726 * {@inheritDoc} 727 */ 728 public void tableRow_() 729 { 730 bufferFlag = false; 731 732 // write out the header row first, then the data in the buffer 733 buildRowLine(); 734 735 write( rowLine ); 736 737 // TODO: This will need to be more clever, for multi-line cells 738 if ( gridFlag ) 739 { 740 write( TABLE_ROW_SEPARATOR_MARKUP ); 741 } 742 743 write( buffer.toString() ); 744 745 resetBuffer(); 746 747 write( EOL ); 748 749 // only reset cell count if this is the last row 750 cellCount = 0; 751 } 752 753 /** Construct a table row. */ 754 private void buildRowLine() 755 { 756 StringBuilder rLine = new StringBuilder(); 757 rLine.append( TABLE_ROW_START_MARKUP ); 758 759 for ( int i = 0; i < cellCount; i++ ) 760 { 761 if ( cellJustif != null ) 762 { 763 switch ( cellJustif[i] ) 764 { 765 case 1: 766 rLine.append( TABLE_COL_LEFT_ALIGNED_MARKUP ); 767 break; 768 case 2: 769 rLine.append( TABLE_COL_RIGHT_ALIGNED_MARKUP ); 770 break; 771 default: 772 rLine.append( TABLE_COL_CENTERED_ALIGNED_MARKUP ); 773 } 774 } 775 else 776 { 777 rLine.append( TABLE_COL_CENTERED_ALIGNED_MARKUP ); 778 } 779 } 780 rLine.append( EOL ); 781 782 this.rowLine = rLine.toString(); 783 } 784 785 /** 786 * {@inheritDoc} 787 */ 788 public void tableCell() 789 { 790 tableCell( false ); 791 } 792 793 /** 794 * {@inheritDoc} 795 */ 796 public void tableHeaderCell() 797 { 798 tableCell( true ); 799 } 800 801 /** 802 * Starts a table cell. 803 * 804 * @param headerRow If this cell is part of a header row. 805 */ 806 public void tableCell( boolean headerRow ) 807 { 808 if ( headerRow ) 809 { 810 buffer.append( TABLE_CELL_SEPARATOR_MARKUP ); 811 } 812 tableCellFlag = true; 813 } 814 815 /** 816 * {@inheritDoc} 817 */ 818 public void tableCell_() 819 { 820 endTableCell(); 821 } 822 823 /** 824 * {@inheritDoc} 825 */ 826 public void tableHeaderCell_() 827 { 828 endTableCell(); 829 } 830 831 /** 832 * Ends a table cell. 833 */ 834 private void endTableCell() 835 { 836 tableCellFlag = false; 837 buffer.append( TABLE_CELL_SEPARATOR_MARKUP ); 838 cellCount++; 839 } 840 841 /** 842 * {@inheritDoc} 843 */ 844 public void tableCaption() 845 { 846 tableCaptionFlag = true; 847 } 848 849 /** 850 * {@inheritDoc} 851 */ 852 public void tableCaption_() 853 { 854 tableCaptionFlag = false; 855 } 856 857 /** 858 * {@inheritDoc} 859 */ 860 public void figureCaption_() 861 { 862 write( EOL ); 863 } 864 865 /** {@inheritDoc} */ 866 public void figureGraphics( String name ) 867 { 868 write( EOL + "[" + name + "] " ); 869 } 870 871 /** {@inheritDoc} */ 872 public void anchor( String name ) 873 { 874 write( ANCHOR_START_MARKUP ); 875 } 876 877 /** 878 * {@inheritDoc} 879 */ 880 public void anchor_() 881 { 882 write( ANCHOR_END_MARKUP ); 883 } 884 885 /** {@inheritDoc} */ 886 public void link( String name ) 887 { 888 if ( !headerFlag ) 889 { 890 write( LINK_START_1_MARKUP ); 891 text( name.startsWith( "#" ) ? name.substring( 1 ) : name ); 892 write( LINK_START_2_MARKUP ); 893 } 894 } 895 896 /** 897 * {@inheritDoc} 898 */ 899 public void link_() 900 { 901 if ( !headerFlag ) 902 { 903 write( LINK_END_MARKUP ); 904 } 905 } 906 907 /** 908 * A link with a target. 909 * 910 * @param name The name of the link. 911 * @param target The link target. 912 */ 913 public void link( String name, String target ) 914 { 915 if ( !headerFlag ) 916 { 917 write( LINK_START_1_MARKUP ); 918 text( target ); 919 write( LINK_START_2_MARKUP ); 920 text( name ); 921 } 922 } 923 924 /** 925 * {@inheritDoc} 926 */ 927 public void inline() 928 { 929 inline( null ); 930 } 931 932 /** {@inheritDoc} */ 933 public void inline( SinkEventAttributes attributes ) 934 { 935 if ( !headerFlag ) 936 { 937 List<String> tags = new ArrayList<>(); 938 939 if ( attributes != null ) 940 { 941 942 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "italic" ) ) 943 { 944 write( ITALIC_START_MARKUP ); 945 tags.add( 0, ITALIC_END_MARKUP ); 946 } 947 948 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "bold" ) ) 949 { 950 write( BOLD_START_MARKUP ); 951 tags.add( 0, BOLD_END_MARKUP ); 952 } 953 954 if ( attributes.containsAttribute( SinkEventAttributes.SEMANTICS, "code" ) ) 955 { 956 write( MONOSPACED_START_MARKUP ); 957 tags.add( 0, MONOSPACED_END_MARKUP ); 958 } 959 960 } 961 962 inlineStack.push( tags ); 963 } 964 } 965 966 /** 967 * {@inheritDoc} 968 */ 969 public void inline_() 970 { 971 if ( !headerFlag ) 972 { 973 for ( String tag: inlineStack.pop() ) 974 { 975 write( tag ); 976 } 977 } 978 } 979 980 /** 981 * {@inheritDoc} 982 */ 983 public void italic() 984 { 985 inline( SinkEventAttributeSet.Semantics.ITALIC ); 986 } 987 988 /** 989 * {@inheritDoc} 990 */ 991 public void italic_() 992 { 993 inline_(); 994 } 995 996 /** 997 * {@inheritDoc} 998 */ 999 public void bold() 1000 { 1001 inline( SinkEventAttributeSet.Semantics.BOLD ); 1002 } 1003 1004 /** 1005 * {@inheritDoc} 1006 */ 1007 public void bold_() 1008 { 1009 inline_(); 1010 } 1011 1012 /** 1013 * {@inheritDoc} 1014 */ 1015 public void monospaced() 1016 { 1017 inline( SinkEventAttributeSet.Semantics.CODE ); 1018 } 1019 1020 /** 1021 * {@inheritDoc} 1022 */ 1023 public void monospaced_() 1024 { 1025 inline_(); 1026 } 1027 1028 /** 1029 * {@inheritDoc} 1030 */ 1031 public void lineBreak() 1032 { 1033 if ( headerFlag || bufferFlag ) 1034 { 1035 buffer.append( EOL ); 1036 } 1037 else if ( verbatimFlag ) 1038 { 1039 write( EOL ); 1040 } 1041 else 1042 { 1043 write( "\\" + EOL ); 1044 } 1045 } 1046 1047 /** 1048 * {@inheritDoc} 1049 */ 1050 public void nonBreakingSpace() 1051 { 1052 if ( headerFlag || bufferFlag ) 1053 { 1054 buffer.append( NON_BREAKING_SPACE_MARKUP ); 1055 } 1056 else 1057 { 1058 write( NON_BREAKING_SPACE_MARKUP ); 1059 } 1060 } 1061 1062 /** {@inheritDoc} */ 1063 public void text( String text ) 1064 { 1065 if ( tableCaptionFlag ) 1066 { 1067 tableCaptionBuffer.append( text ); 1068 } 1069 else if ( headerFlag || bufferFlag ) 1070 { 1071 buffer.append( text ); 1072 } 1073 else if ( verbatimFlag ) 1074 { 1075 verbatimContent( text ); 1076 } 1077 else 1078 { 1079 content( text ); 1080 } 1081 } 1082 1083 /** {@inheritDoc} */ 1084 public void rawText( String text ) 1085 { 1086 write( text ); 1087 } 1088 1089 /** {@inheritDoc} */ 1090 public void comment( String comment ) 1091 { 1092 rawText( ( startFlag ? "" : EOL ) + COMMENT + COMMENT + comment ); 1093 } 1094 1095 /** 1096 * {@inheritDoc} 1097 * 1098 * Unkown events just log a warning message but are ignored otherwise. 1099 * @see org.apache.maven.doxia.sink.Sink#unknown(String,Object[],SinkEventAttributes) 1100 */ 1101 public void unknown( String name, Object[] requiredParams, SinkEventAttributes attributes ) 1102 { 1103 getLog().warn( "[Apt Sink] Unknown Sink event: '" + name + "', ignoring!" ); 1104 } 1105 1106 /** 1107 * Write text to output. 1108 * 1109 * @param text The text to write. 1110 */ 1111 protected void write( String text ) 1112 { 1113 startFlag = false; 1114 if ( tableCellFlag ) 1115 { 1116 buffer.append( text ); 1117 } 1118 else 1119 { 1120 writer.write( unifyEOLs( text ) ); 1121 } 1122 } 1123 1124 /** 1125 * Write Apt escaped text to output. 1126 * 1127 * @param text The text to write. 1128 */ 1129 protected void content( String text ) 1130 { 1131 write( escapeAPT( text ) ); 1132 } 1133 1134 /** 1135 * Write Apt escaped text to output. 1136 * 1137 * @param text The text to write. 1138 */ 1139 protected void verbatimContent( String text ) 1140 { 1141 write( escapeAPT( text ) ); 1142 } 1143 1144 /** 1145 * {@inheritDoc} 1146 */ 1147 public void flush() 1148 { 1149 writer.flush(); 1150 } 1151 1152 /** 1153 * {@inheritDoc} 1154 */ 1155 public void close() 1156 { 1157 writer.close(); 1158 1159 init(); 1160 } 1161 1162 // ---------------------------------------------------------------------- 1163 // Private methods 1164 // ---------------------------------------------------------------------- 1165 1166 /** 1167 * Escape special characters in a text in APT: 1168 * 1169 * <pre> 1170 * \~, \=, \-, \+, \*, \[, \], \<, \>, \{, \}, \\ 1171 * </pre> 1172 * 1173 * @param text the String to escape, may be null 1174 * @return the text escaped, "" if null String input 1175 */ 1176 private static String escapeAPT( String text ) 1177 { 1178 if ( text == null ) 1179 { 1180 return ""; 1181 } 1182 1183 int length = text.length(); 1184 StringBuilder buffer = new StringBuilder( length ); 1185 1186 for ( int i = 0; i < length; ++i ) 1187 { 1188 char c = text.charAt( i ); 1189 switch ( c ) 1190 { // 0080 1191 case '\\': 1192 case '~': 1193 case '=': 1194 case '-': 1195 case '+': 1196 case '*': 1197 case '[': 1198 case ']': 1199 case '<': 1200 case '>': 1201 case '{': 1202 case '}': 1203 buffer.append( '\\' ); 1204 buffer.append( c ); 1205 break; 1206 default: 1207 buffer.append( c ); 1208 } 1209 } 1210 1211 return buffer.toString(); 1212 } 1213}