Clover Coverage Report - XWiki Rendering - Parent POM 4.0-SNAPSHOT (Aggregated)
Coverage timestamp: Mon Mar 12 2012 18:03:13 CET
../../../../../../img/srcFileCovDistChart0.png 90% of files have more coverage
209   652   83   4.35
62   468   0.4   12
48     1.73  
4    
 
  XWikiSerializer2       Line # 51 197 0% 74 297 0% 0.0
  XWikiSerializer2.ListOrdering       Line # 568 0 - 0 0 - -1.0
  XWikiSerializer2.XWiki2ReferenzeHandler       Line # 577 8 0% 5 14 0% 0.0
  XWikiSerializer2.Table       Line # 614 4 0% 4 8 0% 0.0
 
No Tests
 
1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.rendering.wikimodel.xwiki.xwiki20;
21   
22    import java.util.Stack;
23    import java.util.logging.Logger;
24   
25    import org.xwiki.rendering.wikimodel.IWemConstants;
26    import org.xwiki.rendering.wikimodel.IWikiPrinter;
27    import org.xwiki.rendering.wikimodel.PrintTextListener;
28    import org.xwiki.rendering.wikimodel.ReferenceHandler;
29    import org.xwiki.rendering.wikimodel.WikiFormat;
30    import org.xwiki.rendering.wikimodel.WikiPageUtil;
31    import org.xwiki.rendering.wikimodel.WikiParameter;
32    import org.xwiki.rendering.wikimodel.WikiParameters;
33    import org.xwiki.rendering.wikimodel.WikiReference;
34   
35    /**
36    * Serializing XWiki 2.0 syntax ... <br>
37    * <br>
38    * Implementation hints:
39    * <ul>
40    * <li>This serializer is only tested with transformed MediaWiki sources</li>
41    * <li>To support nested tables, we're using a stack of tables.</li>
42    * <li>To get the table caption in front of a table definition, we're using a
43    * simple model for --> see nested Table class</li>
44    * <li>Nested definition lists are NOT supported</li>
45    * </ul>
46    *
47    * @version $Id: a1e22e9a7561b1f293efd12c73340063c6ab0b67 $
48    * @since 4.0M1
49    * @see {@link org.xwiki.rendering.wikimodel.xwiki.xwiki10.XWikiSerializer}
50    */
 
51    public class XWikiSerializer2 extends PrintTextListener
52    {
53    private static final String[] HEADERS = {"", "=", "==", "===", "====", "=====", "======"};
54   
55    private Stack<ListOrdering> listOrdering = new Stack<ListOrdering>();
56   
57    private Stack<Table> tables = new Stack<Table>();
58   
59    private boolean listItemWritten = false;
60   
61    private boolean firstTableRow = false;
62   
63    private boolean withinTableCell = false;
64   
65    private Logger logger;
66   
 
67  0 toggle public XWikiSerializer2(IWikiPrinter printer)
68    {
69  0 super(printer);
70  0 logger = Logger.getLogger(this.getClass().getCanonicalName());
71    }
72   
73    // ------------------------------------------------------------------------
74   
 
75  0 toggle @Override
76    public void beginHeader(int headerLevel, WikiParameters params)
77    {
78  0 println();
79  0 print(HEADERS[headerLevel] + " ");
80    }
81   
 
82  0 toggle @Override
83    public void endHeader(int headerLevel, WikiParameters params)
84    {
85  0 print(" " + HEADERS[headerLevel]);
86  0 println();
87    }
88   
89    // ------------------------------------------------------------------------
90   
 
91  0 toggle @Override
92    public void beginList(WikiParameters params, boolean ordered)
93    {
94  0 if (ordered) {
95  0 listOrdering.push(ListOrdering.ORDERED);
96    } else {
97  0 listOrdering.push(ListOrdering.UNORDERED);
98    }
99  0 if (listItemWritten) { // new line for each new list
100  0 println();
101    }
102    }
103   
 
104  0 toggle @Override
105    public void endList(WikiParameters params, boolean ordered)
106    {
107  0 listOrdering.pop();
108  0 listItemWritten = false;
109    }
110   
 
111  0 toggle @Override
112    public void beginListItem()
113    {
114  0 final ListOrdering[] orders = listOrdering.toArray(new ListOrdering[listOrdering.size()]);
115  0 StringBuilder sb = new StringBuilder();
116  0 boolean isordered = false;
117  0 for (int i = 0; i < orders.length; i++) {
118  0 if (orders[i] == ListOrdering.ORDERED) {
119  0 sb.append("1");
120  0 isordered = true;
121    } else {
122  0 sb.append("*");
123    }
124    }
125  0 if (isordered) {
126  0 sb.append(".");
127    }
128  0 sb.append(" ");
129  0 print(sb.toString());
130  0 listItemWritten = true;
131    }
132   
 
133  0 toggle @Override
134    public void endListItem()
135    {
136  0 if (listItemWritten) { // don't split related lists
137  0 println();
138    }
139    }
140   
141    // ------------------------------------------------------------------------
142   
 
143  0 toggle @Override
144    public void onImage(String ref)
145    {
146  0 throw new UnsupportedOperationException("Not implemented yet!");
147    }
148   
 
149  0 toggle @Override
150    public void onImage(WikiReference ref)
151    {
152  0 WikiParameters params = ref.getParameters();
153  0 final WikiParameter format = params.getParameter("format");
154  0 if (format != null && "thumb".equals(format.getValue())) {
155  0 onImageThumbnail(ref);
156    } else {
157  0 print("[[image:");
158  0 String link = ref.getLink();
159  0 final int dotidx = link.indexOf(':');
160  0 if (dotidx > 0) {
161  0 link = link.substring(dotidx + 1);
162    }
163  0 link = clearName(link);
164  0 print(link);
165    // add title attribute - the easy way ;-)
166  0 if (ref.getLabel() != null) {
167  0 params = params.addParameter("title", ref.getLabel());
168    }
169    // put the parameters
170  0 if (params != null && params.getSize() > 0) {
171    // print parameters ...
172  0 print("||");
173  0 for (int i = 0, len = params.getSize(); i < len; i++) {
174  0 print(" ");
175  0 final WikiParameter param = params.getParameter(i);
176  0 String val = WikiPageUtil.escapeXmlAttribute(param.getValue());
177  0 print(param.getKey() + "=\"" + val + "\"");
178    }
179    }
180  0 print("]]");
181    }
182    }
183   
184    /**
185    * Special case when detected, that there are image thumbnail. Thus it's
186    * possible to insert something like XWiki "LightBox" macro. (Default
187    * implementation will set "width:200px")
188    */
 
189  0 toggle protected void onImageThumbnail(WikiReference ref)
190    {
191  0 WikiParameters params = ref.getParameters();
192  0 final WikiParameter oldstyle = params.getParameter("style");
193  0 if (oldstyle != null) {
194    // remove existing
195  0 params.remove("style");
196  0 params = params.addParameter("style", oldstyle.getValue() + ";" + "float: right; width:"
197    + getImageThumbwidth());
198    } else {
199  0 params = params.addParameter("style", "float: right; width:" + getImageThumbwidth());
200    }
201  0 params = params.remove("format");
202  0 WikiReference newimgref = new WikiReference(ref.getLink(), ref.getLabel(), params);
203  0 onImage(newimgref);
204    }
205   
206    // ------------------------------------------------------------------------
207   
 
208  0 toggle @Override
209    public void onVerbatimBlock(String str, WikiParameters params)
210    {
211  0 print("{{code language=none}}");
212  0 print(str);
213  0 print("{{/code}}");
214    }
215   
 
216  0 toggle @Override
217    public void onVerbatimInline(String str, WikiParameters params)
218    {
219  0 println("{{code language=none}}");
220  0 println(str);
221  0 println("{{/code}}");
222    }
223   
224    // ------------------------------------------------------------------------
225   
 
226  0 toggle @Override
227    public void onTableCaption(String str)
228    {
229  0 tables.peek().setCaption(str);
230    }
231   
 
232  0 toggle @Override
233    public void beginTable(WikiParameters params)
234    {
235  0 Table t = new Table();
236  0 if (params != null && params.getSize() > 0) {
237  0 t.appendText("(% style=\"");
238  0 for (WikiParameter param : params) {
239  0 t.appendText(param.getKey() + ":" + param.getValue() + ";");
240    }
241  0 t.appendText("\" %)");
242  0 t.appendText(getEol());
243    }
244  0 tables.push(t);
245  0 firstTableRow = true;
246    }
247   
 
248  0 toggle @Override
249    public void endTable(WikiParameters params)
250    {
251  0 final Table table = tables.pop();
252  0 if (table.getCaption() != null) {
253  0 print("**");
254  0 print(table.getCaption());
255  0 print("**");
256  0 println();
257    }
258  0 println(table.getText());
259    }
260   
 
261  0 toggle @Override
262    public void beginTableCell(boolean tableHead, WikiParameters params)
263    {
264  0 final Table t = tables.peek();
265  0 if (firstTableRow) {
266  0 t.appendText("|= ");
267    } else {
268  0 t.appendText("| ");
269    }
270  0 withinTableCell = true;
271    }
272   
 
273  0 toggle @Override
274    public void endTableCell(boolean tableHead, WikiParameters params)
275    {
276  0 final Table t = tables.peek();
277  0 t.appendText(" ");
278  0 withinTableCell = false;
279    }
280   
 
281  0 toggle @Override
282    public void beginTableRow(WikiParameters params)
283    {
284    // nothing
285    }
286   
 
287  0 toggle @Override
288    public void endTableRow(WikiParameters params)
289    {
290  0 final Table t = tables.peek();
291  0 t.appendText(getEol());
292  0 firstTableRow = false;
293    }
294   
295    // ------------------------------------------------------------------------
296   
 
297  0 toggle @Override
298    public void beginFormat(WikiFormat format)
299    {
300  0 if (format.hasStyle(IWemConstants.STRONG)) {
301  0 print("**");
302  0 } else if (format.hasStyle(IWemConstants.EM)) {
303  0 print("//");
304  0 } else if (format.hasStyle(IWemConstants.MONO)) {
305  0 print("##");
306  0 } else if (format.hasStyle(IWemConstants.TT)) {
307  0 print("##");
308    } else {
309  0 super.beginFormat(format);
310    }
311    }
312   
 
313  0 toggle @Override
314    public void endFormat(WikiFormat format)
315    {
316  0 if (format.hasStyle(IWemConstants.TT)) {
317  0 print("##");
318  0 } else if (format.hasStyle(IWemConstants.MONO)) {
319  0 print("##");
320  0 } else if (format.hasStyle(IWemConstants.EM)) {
321  0 print("//");
322  0 } else if (format.hasStyle(IWemConstants.STRONG)) {
323  0 print("**");
324    } else {
325  0 super.beginFormat(format);
326    }
327    }
328   
329    // ------------------------------------------------------------------------
330   
 
331  0 toggle @Override
332    public void endParagraph(WikiParameters params)
333    {
334  0 println();
335  0 println();
336    }
337   
 
338  0 toggle @Override
339    protected void endBlock()
340    {
341  0 println();
342    }
343   
 
344  0 toggle protected String getEol()
345    {
346  0 return "\n";
347    }
348   
 
349  0 toggle @Override
350    public void onLineBreak()
351    {
352  0 print("\\\\");
353    }
354   
 
355  0 toggle @Override
356    public void onNewLine()
357    {
358  0 super.onNewLine();
359    }
360   
 
361  0 toggle @Override
362    public void onSpecialSymbol(String str)
363    {
364  0 if (withinTableCell && "|".equals(str)) {
365  0 print("~");
366    }
367  0 print(str);
368    }
369   
370    // ------------------------------------------------------------------------
371   
 
372  0 toggle @Override
373    public void beginDefinitionTerm()
374    {
375  0 print("; ");
376    }
377   
 
378  0 toggle @Override
379    public void endDefinitionTerm()
380    {
381  0 println();
382    }
383   
 
384  0 toggle @Override
385    public void beginDefinitionDescription()
386    {
387  0 print(": ");
388    }
389   
 
390  0 toggle @Override
391    public void endDefinitionDescription()
392    {
393  0 println();
394    }
395   
396    /*
397    * ========================================================================
398    */
399   
400    /**
401    * @return The wisth information for a thumbnail image
402    */
 
403  0 toggle protected String getImageThumbwidth()
404    {
405  0 return "200px";
406    }
407   
 
408  0 toggle @Override
409    protected void print(String str)
410    {
411  0 if (!tables.isEmpty()) {
412  0 tables.peek().appendText(str);
413    } else {
414  0 super.print(str);
415    }
416    }
417   
 
418  0 toggle @Override
419    protected void println()
420    {
421  0 if (!tables.isEmpty()) {
422  0 tables.peek().appendText(getEol());
423    } else {
424  0 super.println();
425    }
426    }
427   
 
428  0 toggle @Override
429    protected void println(String str)
430    {
431  0 if (!tables.isEmpty()) {
432  0 tables.peek().appendText(str + getEol());
433    } else {
434  0 super.println(str);
435    }
436    }
437   
438    /*
439    * (non-Javadoc)
440    *
441    * @see PrintTextListener#newReferenceHandler()
442    */
 
443  0 toggle @Override
444    protected ReferenceHandler newReferenceHandler()
445    {
446  0 return new XWiki2ReferenzeHandler();
447    }
448   
449    /*
450    * ========================================================================
451    */
452   
453    /**
454    * @return the logger
455    */
 
456  0 toggle public Logger getLogger()
457    {
458  0 return logger;
459    }
460   
461    /**
462    * @param logger the logger to set
463    */
 
464  0 toggle public void setLogger(Logger logger)
465    {
466  0 this.logger = logger;
467    }
468   
469    /**
470    * @see {@link #clearName(String)}
471    */
 
472  0 toggle public final static String clearName(String name, boolean stripDots, boolean ascii)
473    {
474  0 String temp = name;
475  0 temp = temp.replaceAll(
476    "[\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u0100\u0102\u0104\u01cd\u01de\u01e0\u01fa\u0200\u0202\u0226]", "A");
477  0 temp = temp.replaceAll(
478    "[\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u0101\u0103\u0105\u01ce\u01df\u01e1\u01fb\u0201\u0203\u0227]", "a");
479  0 temp = temp.replaceAll("[\u00c6\u01e2\u01fc]", "AE");
480  0 temp = temp.replaceAll("[\u00e6\u01e3\u01fd]", "ae");
481  0 temp = temp.replaceAll("[\u008c\u0152]", "OE");
482  0 temp = temp.replaceAll("[\u009c\u0153]", "oe");
483  0 temp = temp.replaceAll("[\u00c7\u0106\u0108\u010a\u010c]", "C");
484  0 temp = temp.replaceAll("[\u00e7\u0107\u0109\u010b\u010d]", "c");
485  0 temp = temp.replaceAll("[\u00d0\u010e\u0110]", "D");
486  0 temp = temp.replaceAll("[\u00f0\u010f\u0111]", "d");
487  0 temp = temp.replaceAll("[\u00c8\u00c9\u00ca\u00cb\u0112\u0114\u0116\u0118\u011a\u0204\u0206\u0228]", "E");
488  0 temp = temp.replaceAll("[\u00e8\u00e9\u00ea\u00eb\u0113\u0115\u0117\u0119\u011b\u01dd\u0205\u0207\u0229]", "e");
489  0 temp = temp.replaceAll("[\u011c\u011e\u0120\u0122\u01e4\u01e6\u01f4]", "G");
490  0 temp = temp.replaceAll("[\u011d\u011f\u0121\u0123\u01e5\u01e7\u01f5]", "g");
491  0 temp = temp.replaceAll("[\u0124\u0126\u021e]", "H");
492  0 temp = temp.replaceAll("[\u0125\u0127\u021f]", "h");
493  0 temp = temp.replaceAll("[\u00cc\u00cd\u00ce\u00cf\u0128\u012a\u012c\u012e\u0130\u01cf\u0208\u020a]", "I");
494  0 temp = temp.replaceAll("[\u00ec\u00ed\u00ee\u00ef\u0129\u012b\u012d\u012f\u0131\u01d0\u0209\u020b]", "i");
495  0 temp = temp.replaceAll("[\u0132]", "IJ");
496  0 temp = temp.replaceAll("[\u0133]", "ij");
497  0 temp = temp.replaceAll("[\u0134]", "J");
498  0 temp = temp.replaceAll("[\u0135]", "j");
499  0 temp = temp.replaceAll("[\u0136\u01e8]", "K");
500  0 temp = temp.replaceAll("[\u0137\u0138\u01e9]", "k");
501  0 temp = temp.replaceAll("[\u0139\u013b\u013d\u013f\u0141]", "L");
502  0 temp = temp.replaceAll("[\u013a\u013c\u013e\u0140\u0142\u0234]", "l");
503  0 temp = temp.replaceAll("[\u00d1\u0143\u0145\u0147\u014a\u01f8]", "N");
504  0 temp = temp.replaceAll("[\u00f1\u0144\u0146\u0148\u0149\u014b\u01f9\u0235]", "n");
505  0 temp = temp.replaceAll(
506    "[\u00d2\u00d3\u00d4\u00d5\u00d6\u00d8\u014c\u014e\u0150\u01d1\u01ea\u01ec\u01fe\u020c\u020e\u022a\u022c"
507    + "\u022e\u0230]", "O");
508  0 temp = temp.replaceAll(
509    "[\u00f2\u00f3\u00f4\u00f5\u00f6\u00f8\u014d\u014f\u0151\u01d2\u01eb\u01ed\u01ff\u020d\u020f\u022b\u022d"
510    + "\u022f\u0231]", "o");
511  0 temp = temp.replaceAll("[\u0156\u0158\u0210\u0212]", "R");
512  0 temp = temp.replaceAll("[\u0157\u0159\u0211\u0213]", "r");
513  0 temp = temp.replaceAll("[\u015a\u015c\u015e\u0160\u0218]", "S");
514  0 temp = temp.replaceAll("[\u015b\u015d\u015f\u0161\u0219]", "s");
515  0 temp = temp.replaceAll("[\u00de\u0162\u0164\u0166\u021a]", "T");
516  0 temp = temp.replaceAll("[\u00fe\u0163\u0165\u0167\u021b\u0236]", "t");
517  0 temp = temp.replaceAll(
518    "[\u00d9\u00da\u00db\u00dc\u0168\u016a\u016c\u016e\u0170\u0172\u01d3\u01d5\u01d7\u01d9\u01db\u0214\u0216]",
519    "U");
520  0 temp = temp.replaceAll(
521    "[\u00f9\u00fa\u00fb\u00fc\u0169\u016b\u016d\u016f\u0171\u0173\u01d4\u01d6\u01d8\u01da\u01dc\u0215\u0217]",
522    "u");
523  0 temp = temp.replaceAll("[\u0174]", "W");
524  0 temp = temp.replaceAll("[\u0175]", "w");
525  0 temp = temp.replaceAll("[\u00dd\u0176\u0178\u0232]", "Y");
526  0 temp = temp.replaceAll("[\u00fd\u00ff\u0177\u0233]", "y");
527  0 temp = temp.replaceAll("[\u0179\u017b\u017d]", "Z");
528  0 temp = temp.replaceAll("[\u017a\u017c\u017e]", "z");
529  0 temp = temp.replaceAll("[\u00df]", "SS");
530  0 temp = temp.replaceAll("[_':,;\\\\/]", " ");
531  0 name = temp;
532  0 name = name.replaceAll("\\s+", "");
533  0 name = name.replaceAll("[\\(\\)]", " ");
534   
535  0 if (stripDots) {
536  0 name = name.replaceAll("[\\.]", "");
537    }
538   
539  0 if (ascii) {
540  0 name = name.replaceAll("[^a-zA-Z0-9\\-_\\.]", "");
541    }
542   
543  0 if (name.length() > 250) {
544  0 name = name.substring(0, 250);
545    }
546   
547  0 return name;
548    }
549   
550    /**
551    * Clears the name of files; used while uploading attachments within XWiki
552    *
553    * RECOMMENDED FOR NAMES OF UPLOADED FILES. (boolean stripDots = false;
554    * boolean ascii = true;)
555    *
556    * @see {@link com.xpn.xwiki.XWiki#clearName(String, boolean, boolean, com.xpn.xwiki.XWikiContext)}
557    */
 
558  0 toggle public final static String clearName(String name)
559    {
560  0 boolean stripDots = false;
561  0 boolean ascii = true;
562  0 return clearName(name, stripDots, ascii);
563    }
564   
565    /*
566    * ========================================================================
567    */
 
568    private static enum ListOrdering
569    {
570    ORDERED, UNORDERED
571    }
572   
573    /*
574    * ========================================================================
575    */
576   
 
577    private class XWiki2ReferenzeHandler extends ReferenceHandler
578    {
 
579  0 toggle protected XWiki2ReferenzeHandler()
580    {
581  0 this(false, false);
582    }
583   
 
584  0 toggle protected XWiki2ReferenzeHandler(boolean supportImage, boolean supportDownload)
585    {
586  0 super(supportImage, supportDownload);
587    }
588   
 
589  0 toggle @Override
590    protected void handleImage(String ref, String label, WikiParameters params)
591    {
592  0 handleReference("image:" + ref, label, params); // TODO: testing ...
593    }
594   
 
595  0 toggle @Override
596    protected void handleReference(String ref, String label, WikiParameters params)
597    {
598  0 print("[[");
599  0 if (label != null) {
600  0 print(label + ">>");
601    }
602  0 print(ref);
603  0 print("]]");
604    }
605    }
606   
607    /*
608    * ========================================================================
609    */
610   
611    /**
612    * Workaround to put a caption in front of a table.
613    */
 
614    private static class Table
615    {
616    private StringBuilder text = new StringBuilder();
617   
618    private String caption;
619   
620    /**
621    * @param caption the caption to set
622    */
 
623  0 toggle public void setCaption(String caption)
624    {
625  0 this.caption = caption;
626    }
627   
628    /**
629    * @see java.lang.StringBuilder#append(java.lang.CharSequence)
630    */
 
631  0 toggle public StringBuilder appendText(CharSequence s)
632    {
633  0 return text.append(s);
634    }
635   
636    /**
637    * @see java.lang.StringBuilder#toString()
638    */
 
639  0 toggle public String getText()
640    {
641  0 return text.toString();
642    }
643   
644    /**
645    * @return the caption
646    */
 
647  0 toggle public String getCaption()
648    {
649  0 return caption;
650    }
651    }
652    }