1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.exoplatform.wiki.rendering.render.confluence;
18
19 import java.util.Collections;
20 import java.util.LinkedList;
21 import java.util.List;
22 import java.util.Map;
23
24 import org.apache.commons.lang.StringUtils;
25 import org.xwiki.rendering.listener.Format;
26 import org.xwiki.rendering.listener.HeaderLevel;
27 import org.xwiki.rendering.listener.ListType;
28 import org.xwiki.rendering.listener.MetaData;
29 import org.xwiki.rendering.listener.chaining.BlockStateChainingListener;
30 import org.xwiki.rendering.listener.chaining.ListenerChain;
31 import org.xwiki.rendering.listener.chaining.StackableChainingListener;
32 import org.xwiki.rendering.listener.reference.ResourceReference;
33 import org.xwiki.rendering.listener.reference.ResourceType;
34 import org.xwiki.rendering.renderer.AbstractChainingPrintRenderer;
35 import org.xwiki.rendering.renderer.printer.DefaultWikiPrinter;
36 import org.xwiki.rendering.renderer.printer.VoidWikiPrinter;
37 import org.xwiki.rendering.renderer.printer.WikiPrinter;
38 import org.xwiki.rendering.renderer.reference.ResourceReferenceSerializer;
39 import org.xwiki.rendering.transformation.icon.IconTransformationConfiguration;
40
41
42
43
44 public class ConfluenceSyntaxChainingRenderer extends AbstractChainingPrintRenderer implements StackableChainingListener {
45
46 private ConfluenceSyntaxLinkRenderer linkRenderer;
47
48 private ConfluenceSyntaxImageRenderer imageRenderer;
49
50 private ConfluenceSyntaxIconRenderer iconRenderer;
51
52 private ConfluenceSyntaxMacroRenderer macroPrinter;
53
54 private ResourceReferenceSerializer linkReferenceSerializer;
55
56
57
58 private boolean isFirstElementRendered = false;
59
60 private StringBuffer listStyle = new StringBuffer();
61
62 private Map<String, String> previousFormatParameters;
63
64 private IconTransformationConfiguration iconTransformationConfiguration;
65
66 public ConfluenceSyntaxChainingRenderer(ListenerChain listenerChain,
67 ResourceReferenceSerializer linkReferenceSerializer,
68 IconTransformationConfiguration iconTransformationConfiguration) {
69
70 setListenerChain(listenerChain);
71
72 this.linkReferenceSerializer = linkReferenceSerializer;
73 this.iconTransformationConfiguration = iconTransformationConfiguration;
74 this.linkRenderer = new ConfluenceSyntaxLinkRenderer(getConfluenceSyntaxListenerChain(), linkReferenceSerializer);
75 this.imageRenderer = new ConfluenceSyntaxImageRenderer();
76 this.iconRenderer = new ConfluenceSyntaxIconRenderer(iconTransformationConfiguration);
77 this.macroPrinter = new ConfluenceSyntaxMacroRenderer();
78 }
79
80
81
82 private BlockStateChainingListener getBlockState() {
83 return getConfluenceSyntaxListenerChain().getBlockStateChainingListener();
84 }
85
86
87
88
89
90
91 public StackableChainingListener createChainingListenerInstance() {
92 ConfluenceSyntaxChainingRenderer renderer = new ConfluenceSyntaxChainingRenderer(getListenerChain(),
93 this.linkReferenceSerializer,
94 this.iconTransformationConfiguration);
95 renderer.setPrinter(getPrinter());
96 return renderer;
97 }
98
99 private ConfluenceSyntaxListenerChain getConfluenceSyntaxListenerChain() {
100 return (ConfluenceSyntaxListenerChain) getListenerChain();
101 }
102
103 private ConfluenceSyntaxLinkRenderer getLinkRenderer() {
104 return this.linkRenderer;
105 }
106
107 private ConfluenceSyntaxImageRenderer getImageRenderer() {
108 return this.imageRenderer;
109 }
110
111 private ConfluenceSyntaxIconRenderer getIconRenderer() {
112 return this.iconRenderer;
113 }
114
115 private ConfluenceSyntaxMacroRenderer getMacroPrinter() {
116 return this.macroPrinter;
117 }
118
119
120
121
122
123
124 @Override
125 public void beginGroup(Map<String, String> parameters) {
126 if (!getBlockState().isInLine()) {
127 printEmptyLine();
128 }
129
130 if (parameters.size() > 0) {
131 printBeginParameters(parameters, true);
132 }
133
134
135
136 getListenerChain().pushAllStackableListeners();
137 }
138
139
140
141
142
143
144 @Override
145 public void endDocument(MetaData metaData) {
146
147 getConfluencePrinter().flush();
148 }
149
150
151
152
153
154
155 @Override
156 public void endGroup(Map<String, String> parameters) {
157
158
159 getListenerChain().popAllStackableListeners();
160 }
161
162
163
164
165
166
167 @Override
168 public void beginLink(ResourceReference link, boolean isFreeStandingURI, Map<String, String> parameters) {
169
170
171
172 getConfluencePrinter().setBeforeLink(true);
173
174 if (getLinkRenderer().forceFullSyntax(getConfluencePrinter(), isFreeStandingURI, parameters)
175 && getConfluencePrinter().getBuffer().length() > 0
176 && getConfluencePrinter().getBuffer()
177 .charAt(getConfluencePrinter().getBuffer().length() - 1) == '[') {
178 getConfluencePrinter().setEscapeLastChar(true);
179 }
180 getConfluencePrinter().flush();
181 getConfluencePrinter().setBeforeLink(false);
182
183 int linkDepth = getBlockState().getLinkDepth();
184
185
186
187 if (linkDepth < 2) {
188 getLinkRenderer().beginRenderLink(getConfluencePrinter(), link, isFreeStandingURI, parameters);
189
190 ConfluenceSyntaxEscapeWikiPrinter linkLabelPrinter = new ConfluenceSyntaxEscapeWikiPrinter(new DefaultWikiPrinter(),
191 getConfluenceSyntaxListenerChain());
192
193
194 linkLabelPrinter.setOnNewLine(getConfluencePrinter().isOnNewLine());
195
196
197
198 pushPrinter(linkLabelPrinter);
199 } else if (isFreeStandingURI) {
200 print(getLinkRenderer().serialize(link));
201 }
202 }
203
204
205
206
207
208
209 @Override
210 public void endLink(ResourceReference link, boolean isFreeStandingURI, Map<String, String> parameters) {
211
212
213 if (getBlockState().getLinkDepth() == 1) {
214 ConfluenceSyntaxEscapeWikiPrinter linkBlocksPrinter = getConfluencePrinter();
215 linkBlocksPrinter.flush();
216 String content = linkBlocksPrinter.toString();
217 popPrinter();
218
219 getLinkRenderer().renderLinkContent(getConfluencePrinter(), content);
220 getLinkRenderer().endRenderLink(getConfluencePrinter(), link, isFreeStandingURI, parameters);
221 }
222 }
223
224
225
226
227
228
229
230 @Override
231 public void beginFormat(Format format, Map<String, String> parameters) {
232
233
234 if (this.previousFormatParameters != null) {
235 if (parameters.isEmpty()) {
236
237
238 } else if (!this.previousFormatParameters.equals(parameters)) {
239 this.previousFormatParameters = null;
240 printBeginParameters(parameters, false);
241 } else {
242 this.previousFormatParameters = null;
243 }
244 } else if (this.previousFormatParameters == null) {
245 printBeginParameters(parameters, false);
246 }
247
248 switch (format) {
249 case BOLD:
250
251 if (this.previousFormatParameters != null) {
252 getPrinter().print("(%%)");
253 this.previousFormatParameters = null;
254 }
255
256 getConfluencePrinter().printBeginBold();
257 break;
258 case ITALIC:
259
260 if (this.previousFormatParameters != null) {
261 getPrinter().print("(%%)");
262 this.previousFormatParameters = null;
263 }
264
265 getConfluencePrinter().printBeginItalic();
266 break;
267 case STRIKEDOUT:
268 print("-");
269 break;
270 case UNDERLINED:
271 print("+");
272 break;
273 case SUPERSCRIPT:
274 print("^");
275 break;
276 case SUBSCRIPT:
277 print("~");
278 break;
279 case MONOSPACE:
280 print("{{");
281 break;
282 }
283
284 }
285
286
287
288
289
290
291
292 @Override
293 public void endFormat(Format format, Map<String, String> parameters) {
294 switch (format) {
295 case BOLD:
296 print("*");
297 break;
298 case ITALIC:
299 getConfluencePrinter().printEndItalic();
300 break;
301 case STRIKEDOUT:
302 print("-");
303 break;
304 case UNDERLINED:
305 print("+");
306 break;
307 case SUPERSCRIPT:
308 print("^");
309 break;
310 case SUBSCRIPT:
311 print("~");
312 break;
313 case MONOSPACE:
314 print("}}");
315 break;
316 }
317
318 StringBuffer parametersStr = new StringBuffer();
319 for (Map.Entry<String, String> entry : parameters.entrySet()) {
320 String value = entry.getValue();
321 String key = entry.getKey();
322
323 if (key != null && value != null) {
324 if ("style".equals(key))
325 parametersStr.append("{span}");
326 }
327 }
328 print(parametersStr.toString());
329 if (!parameters.isEmpty()) {
330 this.previousFormatParameters = parameters;
331 }
332 }
333
334
335
336
337
338
339 @Override
340 public void beginParagraph(Map<String, String> parameters) {
341 printEmptyLine();
342 printBeginParameters(parameters);
343 }
344
345
346
347
348
349
350 @Override
351 public void endParagraph(Map<String, String> parameters) {
352 this.previousFormatParameters = null;
353 StringBuffer parametersStr = new StringBuffer();
354 for (Map.Entry<String, String> entry : parameters.entrySet()) {
355 String value = entry.getValue();
356 String key = entry.getKey();
357
358 if (key != null && value != null) {
359 if ("style".equals(key))
360 parametersStr.append("{div}");
361 }
362 }
363 print(parametersStr.toString());
364
365
366 getConfluencePrinter().flush();
367 }
368
369
370
371
372
373
374 @Override
375 public void onNewLine() {
376
377
378
379
380
381
382
383
384 if (getBlockState().isInLine()) {
385 if (getBlockState().isInTableCell()) {
386 print("\\\\");
387 } else if (getConfluenceSyntaxListenerChain().getConsecutiveNewLineStateChainingListener()
388 .getNewLineCount() > 1) {
389 print("\\\\");
390 } else if (getConfluenceSyntaxListenerChain().getLookaheadChainingListener().getNextEvent().eventType.isInlineEnd()) {
391 print("\\\\");
392 } else {
393 print("\n");
394 }
395 } else {
396 print("\n");
397 }
398 }
399
400
401
402
403
404
405
406 @Override
407 public void onMacro(String id, Map<String, String> parameters, String content, boolean isInline) {
408 if (!isInline) {
409 printEmptyLine();
410 print(getMacroPrinter().renderMacro(id, parameters, content, isInline));
411 } else {
412 getConfluencePrinter().printInlineMacro(getMacroPrinter().renderMacro(id, parameters, content, isInline));
413 }
414 }
415
416
417
418
419
420
421
422 @Override
423 public void beginHeader(HeaderLevel level, String id, Map<String, String> parameters) {
424 printEmptyLine();
425 print("h" + level.getAsInt() + ". ");
426 printBeginParameters(parameters, false);
427 }
428
429
430
431
432
433
434
435 @Override
436 public void endHeader(HeaderLevel level, String id, Map<String, String> parameters) {
437 printEndParameters(parameters, false);
438 }
439
440
441
442
443
444
445 @Override
446 public void onWord(String word) {
447 printDelayed(word);
448 }
449
450
451
452
453
454
455 @Override
456 public void onSpace() {
457 printDelayed(" ");
458 }
459
460
461
462
463
464
465 @Override
466 public void onSpecialSymbol(char symbol) {
467 printDelayed("" + symbol);
468 }
469
470
471
472
473
474
475
476 @Override
477 public void beginList(ListType listType, Map<String, String> parameters) {
478 if (getBlockState().getListDepth() == 1) {
479 if (!getBlockState().isInLine()) {
480 print("\n");
481 } else
482 printEmptyLine();
483 } else {
484 getPrinter().print("\n");
485 }
486
487 if (listType == ListType.BULLETED) {
488 this.listStyle.append("*");
489 } else {
490 this.listStyle.append("#");
491 }
492 printBeginParameters(parameters);
493 }
494
495
496
497
498
499
500 @Override
501 public void beginListItem() {
502 if (getBlockState().getListItemIndex() > 0) {
503 getPrinter().print("\n");
504 }
505
506 print(this.listStyle.toString());
507 if (StringUtils.contains(this.listStyle.toString(), '#')) {
508
509 }
510 print(" ");
511 }
512
513
514
515
516
517
518
519 @Override
520 public void endList(ListType listType, Map<String, String> parameters) {
521 this.listStyle.setLength(this.listStyle.length() - 1);
522
523
524
525 getConfluencePrinter().flush();
526 }
527
528
529
530
531
532
533 @Override
534 public void endListItem() {
535 this.previousFormatParameters = null;
536 }
537
538
539
540
541
542
543
544 @Override
545 public void beginMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline) {
546 if (!isInline) {
547 printEmptyLine();
548 }
549
550
551
552 pushPrinter(new ConfluenceSyntaxEscapeWikiPrinter(VoidWikiPrinter.VOIDWIKIPRINTER, getConfluenceSyntaxListenerChain()));
553 }
554
555
556
557
558
559
560
561 @Override
562 public void endMacroMarker(String name, Map<String, String> parameters, String content, boolean isInline) {
563
564 this.previousFormatParameters = null;
565
566 popPrinter();
567
568 print(getMacroPrinter().renderMacro(name, parameters, content, isInline));
569 }
570
571
572
573
574
575
576 @Override
577 public void onId(String name) {
578 print("{{id name=\"" + name + "\"}}");
579 }
580
581
582
583
584
585
586 @Override
587 public void onHorizontalLine(Map<String, String> parameters) {
588 printEmptyLine();
589 printBeginParameters(parameters);
590 print("----");
591 }
592
593
594
595
596
597
598 @Override
599 public void onVerbatim(String protectedString, boolean isInline, Map<String, String> parameters) {
600 if (!isInline) {
601 printEmptyLine();
602 }
603 print("\\");
604 getConfluencePrinter().printVerbatimContent(protectedString);
605 }
606
607
608
609
610
611
612 @Override
613 public void onEmptyLines(int count) {
614 print(StringUtils.repeat("\n", count));
615 }
616
617
618
619
620
621
622 @Override
623 public void beginDefinitionList(Map<String, String> parameters) {
624 if (getBlockState().getDefinitionListDepth() == 1 && !getBlockState().isInList()) {
625 printEmptyLine();
626 } else {
627 print("\n");
628 }
629 printBeginParameters(parameters);
630 }
631
632
633
634
635
636
637 @Override
638 public void beginDefinitionTerm() {
639 if (getBlockState().getDefinitionListItemIndex() > 0) {
640 getPrinter().print("\n");
641 }
642
643 if (this.listStyle.length() > 0) {
644 print(this.listStyle.toString());
645 if (this.listStyle.charAt(0) == '#') {
646
647 }
648 }
649 print(StringUtils.repeat(":", getBlockState().getDefinitionListDepth() - 1));
650 print("; ");
651 }
652
653
654
655
656
657
658 @Override
659 public void beginDefinitionDescription() {
660 if (getBlockState().getDefinitionListItemIndex() > 0) {
661 getPrinter().print("\n");
662 }
663
664 if (this.listStyle.length() > 0) {
665 print(this.listStyle.toString());
666 if (this.listStyle.charAt(0) == '#') {
667
668 }
669 }
670 print(StringUtils.repeat(":", getBlockState().getDefinitionListDepth() - 1));
671 print(": ");
672 }
673
674
675
676
677
678
679 @Override
680 public void endDefinitionDescription() {
681 this.previousFormatParameters = null;
682
683 getConfluencePrinter().flush();
684 }
685
686
687
688
689
690
691 @Override
692 public void endDefinitionTerm() {
693 this.previousFormatParameters = null;
694
695 getConfluencePrinter().flush();
696 }
697
698
699
700
701
702
703 @Override
704 public void beginQuotation(Map<String, String> parameters) {
705 if (!getBlockState().isInQuotationLine()) {
706 printEmptyLine();
707 }
708
709 if (!parameters.isEmpty()) {
710 printBeginParameters(parameters);
711 }
712 }
713
714
715
716
717
718
719 @Override
720 public void beginQuotationLine() {
721 if (getBlockState().getQuotationLineIndex() > 0) {
722 getPrinter().print("\n");
723 }
724 print("bq. ");
725 }
726
727
728
729
730
731
732 @Override
733 public void endQuotationLine() {
734 this.previousFormatParameters = null;
735 getConfluencePrinter().flush();
736 }
737
738
739
740
741
742
743 @Override
744 public void beginTable(Map<String, String> parameters) {
745 printEmptyLine();
746 if (!parameters.isEmpty()) {
747 printBeginParameters(parameters);
748 }
749 }
750
751
752
753
754
755
756 @Override
757 public void beginTableCell(Map<String, String> parameters) {
758 print("|");
759 printBeginParameters(parameters, false);
760 }
761
762
763
764
765
766
767 @Override
768 public void beginTableHeadCell(Map<String, String> parameters) {
769 print("||");
770 printBeginParameters(parameters, false);
771 }
772
773
774
775
776
777
778 @Override
779 public void beginTableRow(Map<String, String> parameters) {
780 if (getBlockState().getCellRow() > 0) {
781 print("\n");
782 }
783
784 printBeginParameters(parameters, false);
785 }
786
787
788
789
790
791
792 @Override
793 public void endTableCell(Map<String, String> parameters) {
794 this.previousFormatParameters = null;
795
796
797
798 getConfluencePrinter().flush();
799 }
800
801
802
803
804
805
806 @Override
807 public void endTableHeadCell(Map<String, String> parameters) {
808 this.previousFormatParameters = null;
809 }
810
811
812
813
814
815
816 @Override
817 public void onImage(ResourceReference image, boolean isFreeStandingURI, Map<String, String> parameters) {
818 if (ResourceType.ICON.equals(image.getType())) {
819 getIconRenderer().renderIcon(getConfluencePrinter(), image);
820 } else{
821 getImageRenderer().beginRenderImage(getConfluencePrinter());
822 getImageRenderer().renderImageContent(getConfluencePrinter(), getImageRenderer().renderImage(image));
823 getImageRenderer().endRenderImage(getConfluencePrinter(), parameters);
824 }
825 }
826
827 protected void printBeginParameters(Map<String, String> parameters) {
828 printBeginParameters(parameters, true);
829 }
830
831 protected void printEndParameters(Map<String, String> parameters) {
832 printEndParameters(parameters, true);
833 }
834
835 protected void printEndParameters(Map<String, String> parameters, boolean newLine) {
836 StringBuffer parametersStr = new StringBuffer();
837 List<Map.Entry<String, String>> list = new LinkedList<Map.Entry<String,String>>(parameters.entrySet());
838 Collections.reverse(list);
839 for (Map.Entry<String, String> entry : list) {
840 String value = entry.getValue();
841 String key = entry.getKey();
842 if (key != null && value != null) {
843 if ("style".equals(key))
844 if (!newLine) {
845 parametersStr.append("{span}");
846 }
847 else {
848 parametersStr.append("{div}");
849 }
850 }
851 }
852 print(parametersStr.toString());
853 }
854
855 protected void printBeginParameters(Map<String, String> parameters, boolean newLine) {
856 StringBuffer parametersStr = new StringBuffer();
857 for (Map.Entry<String, String> entry : parameters.entrySet()) {
858 String value = entry.getValue();
859 String key = entry.getKey();
860
861 if (key != null && value != null) {
862 if ("style".equals(key))
863 if (!newLine) {
864 parametersStr.append("{span:").append("style=\"").append(value).append("\"}");
865 }
866 else {
867 parametersStr.append("{div:").append("style=\"").append(value).append("\"}");
868 }
869 }
870 }
871 print(parametersStr.toString());
872
873 }
874
875 private void printDelayed(String text) {
876 print(text, true);
877 }
878
879 private void print(String text) {
880 print(text, false);
881 }
882
883 private void print(String text, boolean isDelayed) {
884
885 if (this.previousFormatParameters != null) {
886 this.previousFormatParameters = null;
887 }
888
889 if (isDelayed) {
890 getConfluencePrinter().printDelayed(text);
891 } else {
892 getPrinter().print(text);
893 }
894 }
895
896 private void printEmptyLine() {
897 if (this.isFirstElementRendered) {
898 print("\n\n");
899 } else {
900 this.isFirstElementRendered = true;
901 }
902 }
903
904
905
906
907
908
909 public void setPrinter(WikiPrinter printer) {
910
911
912
913 if (printer instanceof ConfluenceSyntaxEscapeWikiPrinter) {
914 super.setPrinter(printer);
915 } else {
916 super.setPrinter(new ConfluenceSyntaxEscapeWikiPrinter(printer, (ConfluenceSyntaxListenerChain) getListenerChain()));
917 }
918 }
919
920
921
922
923
924 public ConfluenceSyntaxEscapeWikiPrinter getConfluencePrinter() {
925 return (ConfluenceSyntaxEscapeWikiPrinter) super.getPrinter();
926 }
927
928 @Override
929 protected void popPrinter() {
930
931 getConfluencePrinter().flush();
932
933 super.popPrinter();
934 }
935
936 }