1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.annotation.internal.renderer

File AnnotationMarkersXHTMLPrinter.java

 

Coverage histogram

../../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

18
42
8
1
217
94
19
0.45
5.25
8
2.38

Classes

Class Line # Actions
AnnotationMarkersXHTMLPrinter 44 42 0% 19 3
0.955882495.6%
 

Contributing tests

This file is covered by 124 tests. .

Source view

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.annotation.internal.renderer;
21   
22    import java.util.LinkedHashMap;
23    import java.util.LinkedList;
24    import java.util.List;
25    import java.util.Map;
26    import java.util.SortedMap;
27   
28    import org.xwiki.annotation.Annotation;
29    import org.xwiki.annotation.renderer.AnnotationEvent;
30    import org.xwiki.rendering.renderer.printer.WikiPrinter;
31    import org.xwiki.rendering.renderer.printer.XHTMLWikiPrinter;
32   
33    /**
34    * XHTML Printer to handle printing annotations markers in the rendered XHTML. It is able to generate the annotation
35    * start marker and end marker and to store information about the annotations state: which ones are being currently
36    * rendered, which markers are opened, etc. To be used by the XHTML renderers to render annotations on the XHTML. <br>
37    * Note that, although this class could aggregate a XHTMLWikiPrinter, and be used to wrap the default XHTMLWikiPrinter
38    * in a XHTML Renderer, it extends it so that it can replace. TODO: in a future improved implementation, this could
39    * handle annotations rendering alone, just using state information from the renderer.
40    *
41    * @version $Id: 05605c3889f761453e43604b056f4d46c52bcedf $
42    * @since 2.3M1
43    */
 
44    public class AnnotationMarkersXHTMLPrinter extends XHTMLWikiPrinter
45    {
46   
47    /**
48    * The annotation marker element in HTML.
49    */
50    private static final String ANNOTATION_MARKER = "span";
51   
52    /**
53    * Flag to signal if the annotations in the openAnnotations stack are actually opened in the printed XHTML. Namely
54    * this will become true when a text event will occur (like a word or space or ...) and will become false when and
55    * end event will occur.
56    */
57    private boolean open;
58   
59    /**
60    * The list of annotations being currently rendered, in the order in which they were opened (i.e. for which
61    * beginAnnotation was signaled but not endAnnotation). Used for correctly nesting the annotations markers with
62    * other XHTML elements. <br>
63    */
64    private List<Annotation> renderedAnnotations = new LinkedList<Annotation>();
65   
66    /**
67    * Builds an XHTML markers annotations printer which uses the underlying wiki printer.
68    *
69    * @param printer the wiki printer used by this XHTML printer
70    */
 
71  132 toggle public AnnotationMarkersXHTMLPrinter(WikiPrinter printer)
72    {
73  132 super(printer);
74    }
75   
76    /**
77    * Handles the beginning of a new annotation.
78    *
79    * @param annotation the annotation that begins
80    */
 
81  88 toggle public void beginAnnotation(Annotation annotation)
82    {
83    // and put it in the stack of open annotations
84  88 renderedAnnotations.add(annotation);
85    // if all other annotations are opened, open this one too. Otherwise it will be opened whenever all the others
86    // are opened.
87  88 if (open) {
88  88 printAnnotationStartMarker(annotation);
89    }
90    }
91   
92    /**
93    * Handles the end of an annotation.
94    *
95    * @param annotation the annotation that ends
96    */
 
97  88 toggle public void endAnnotation(Annotation annotation)
98    {
99    // all annotations which are opened after this one must be closed before this close and reopened after
100  88 int annIndex = renderedAnnotations.indexOf(annotation);
101    // close all annotations opened after this one, in reverse order
102  93 for (int i = renderedAnnotations.size() - 1; i > annIndex; i--) {
103  5 printAnnotationEndMarker(renderedAnnotations.get(i));
104    }
105    // close this annotation
106  88 printAnnotationEndMarker(annotation);
107    // open all previously closed annotations in the order they were initially opened
108  93 for (int i = annIndex + 1; i < renderedAnnotations.size(); i++) {
109  5 printAnnotationStartMarker(renderedAnnotations.get(i));
110    }
111    // and remove it from the list of open annotations
112  88 renderedAnnotations.remove(annotation);
113    }
114   
115    /**
116    * Prints the start marker for the passed annotation.
117    *
118    * @param annotation the annotation to print the start marker for
119    */
 
120  122 toggle private void printAnnotationStartMarker(Annotation annotation)
121    {
122  122 Map<String, String> attributes = new LinkedHashMap<String, String>();
123   
124  122 attributes.put("class", "annotation ID" + annotation.getId());
125  122 printXMLStartElement(ANNOTATION_MARKER, attributes);
126    }
127   
128    /**
129    * Prints the end marker for the passed annotation.
130    *
131    * @param annotation the annotation to print end marker for
132    */
 
133  122 toggle private void printAnnotationEndMarker(Annotation annotation)
134    {
135  122 printXMLEndElement(ANNOTATION_MARKER);
136    }
137   
138    /**
139    * Helper function to handle closing all annotations. To be called either when elements close or when an element
140    * opens (all annotation spans will only wrap text, not inner elements). It will close all opened annotations
141    * markers and set the flag to specify that annotations are closed and they should be opened at next text element.
142    */
 
143  628 toggle public void closeAllAnnotationMarkers()
144    {
145    // if the annotations are opened
146  628 if (open) {
147    // for each annotation from the last opened to the first opened
148  295 for (int i = renderedAnnotations.size() - 1; i >= 0; i--) {
149    // close it
150  29 printAnnotationEndMarker(renderedAnnotations.get(i));
151    }
152    // set the flag so that next end event doesn't close them as well
153  266 open = false;
154    }
155    }
156   
157    /**
158    * Helper function to handle opening all annotations. If the annotations are not already opened, it should open them
159    * all and set the flag to opened so that next text event doesn't do the same.
160    */
 
161  3746 toggle public void openAllAnnotationMarkers()
162    {
163    // if annotations are not opened
164  3746 if (!open) {
165    // for each annotation in the order in which they were opened
166  295 for (int i = 0; i < renderedAnnotations.size(); i++) {
167    // re-open it
168  29 printAnnotationStartMarker(renderedAnnotations.get(i));
169    }
170    // and mark the annotations as opened
171  266 open = true;
172    }
173    }
174   
175    /**
176    * Helper function to help render a piece of text with annotation events inside it, at the specified offsets. To be
177    * used for the events which generate text and need to generate annotation markers inside them.
178    *
179    * @param text the text to render
180    * @param annotations the map of indexes and annotation events to render in this text
181    */
 
182  144 toggle public void printXMLWithAnnotations(String text, SortedMap<Integer, List<AnnotationEvent>> annotations)
183    {
184    // iterate through the indexes of annotations events, print the chunks in between and then handle the annotation
185    // events
186  144 int previous = 0;
187  144 for (int index : annotations.keySet()) {
188    // create the current chunk
189  173 String currentChunk = text.substring(previous, index);
190    // print the current chunk
191  173 if (currentChunk.length() > 0) {
192  96 printXML(currentChunk);
193    }
194    // handle all annotations at this position
195  173 for (AnnotationEvent evt : annotations.get(index)) {
196  176 switch (evt.getType()) {
197  88 case START:
198  88 beginAnnotation(evt.getAnnotation());
199  88 break;
200  88 case END:
201  88 endAnnotation(evt.getAnnotation());
202  88 break;
203  0 default:
204    // nothing
205  0 break;
206    }
207    }
208    // and prepare next iteration
209  173 previous = index;
210    }
211    // print the last chunk of text
212  144 String chunk = text.substring(previous);
213  144 if (chunk.length() > 0) {
214  65 printXML(chunk);
215    }
216    }
217    }