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

File DoxiaListener.java

 

Coverage histogram

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

Code metrics

14
37
7
1
173
86
14
0.38
5.29
7
2

Classes

Class Line # Actions
DoxiaListener 42 37 0% 14 5
0.913793191.4%
 

Contributing tests

This file is covered by 13 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.rendering.internal.renderer.doxia;
21   
22    import java.util.ArrayDeque;
23    import java.util.Deque;
24    import java.util.Map;
25   
26    import org.apache.maven.doxia.sink.Sink;
27    import org.xwiki.rendering.listener.Listener;
28    import org.xwiki.rendering.listener.QueueListener;
29    import org.xwiki.rendering.listener.WrappingListener;
30   
31    /**
32    * Bridge XWiki Rendering Events to Doxia Events. This allows rendering an XDOM using a Doxia Sink.
33    * <p>
34    * Note that the implementation is broken into this class and {@link DoxiaSinkListener} since we need to handle
35    * the special case of Tables: Doxia requires an extra event to be sent (tableRows()) which requires us to count
36    * the number of rows since we need to pass it as the number of justification elements.
37    * </p>
38    *
39    * @version $Id: 4b60892aadbf555203d121dedb7c96c82da0a662 $
40    * @since 4.3M1
41    */
 
42    public class DoxiaListener extends WrappingListener
43    {
44    /**
45    * The stack of Listener which allow to push some queue listener when we find some tables in order to count rows
46    * and send the tableRows event to the Doxia Sink.
47    */
48    private Deque<Listener> listenerStack = new ArrayDeque<Listener>();
49   
50    /**
51    * Count the number of rows. Note that we use a stack since we can have nested tables.
52    */
53    private Deque<Integer> rowCountStack = new ArrayDeque<Integer>();
54   
55    /**
56    * Number of tables being handled.
57    */
58    private int tableCount;
59   
60    /**
61    * If true then this listener is in unstacking mode and the stacked events are being unstacked.
62    */
63    private boolean unstacking;
64   
65    /**
66    * @see #DoxiaListener(org.apache.maven.doxia.sink.Sink)
67    */
68    private Sink sink;
69   
70    /**
71    * @param sink the underlying Doxia sink into which we emit the Table Rows events.
72    */
 
73  21 toggle public DoxiaListener(Sink sink)
74    {
75  21 this.sink = sink;
76  21 pushListener(new DoxiaSinkListener(sink));
77    }
78   
 
79  6 toggle @Override
80    public void beginTable(Map<String, String> parameters)
81    {
82  6 if (this.unstacking) {
83    // We need to send a begin table rows event to the Doxia Sink since it requires such an Event before the
84    // Row events.
85  3 int rowCount = this.rowCountStack.peek();
86  3 int[] justifications = new int[rowCount];
87  12 for (int i = 0; i < rowCount; i++) {
88  9 justifications[i] = Sink.JUSTIFY_CENTER;
89    }
90  3 super.beginTable(parameters);
91  3 this.sink.tableRows(justifications, true);
92    } else {
93    // Start stacking Events since we need to count the number of table rows
94  3 if (this.tableCount == 0) {
95  3 pushListener(new QueueListener());
96  3 this.rowCountStack.push(0);
97    }
98  3 this.tableCount++;
99  3 super.beginTable(parameters);
100    }
101    }
102   
 
103  6 toggle @Override
104    public void endTable(Map<String, String> parameters)
105    {
106  6 if (!this.unstacking) {
107  3 super.endTable(parameters);
108   
109  3 this.tableCount--;
110   
111    // Unstack if we're on the end table event of the first table
112  3 if (this.tableCount == 0) {
113    // Stop stacking Events
114  3 QueueListener queueListener = (QueueListener) popListener();
115   
116    // Send all stacked Events to the current listener so that we can handle nested tables.
117  3 this.unstacking = true;
118  3 queueListener.consumeEvents(this);
119  3 this.unstacking = false;
120    }
121    } else {
122  3 this.sink.tableRows_();
123  3 this.rowCountStack.pop();
124  3 super.endTable(parameters);
125    }
126    }
127   
 
128  18 toggle @Override
129    public void beginTableRow(Map<String, String> parameters)
130    {
131  18 super.beginTableRow(parameters);
132   
133    // Increase row count
134  18 if (!this.unstacking) {
135  9 int rowCount = this.rowCountStack.pop();
136  9 rowCount++;
137  9 this.rowCountStack.push(rowCount);
138    }
139    }
140   
141    /**
142    * Push a new Listener.
143    *
144    * @param listener the new listener that becomes the current active listener
145    */
 
146  24 toggle private void pushListener(Listener listener)
147    {
148  24 this.listenerStack.push(listener);
149  24 setWrappedListener(listener);
150    }
151   
152    /**
153    * Removes the last listener from the stack.
154    *
155    * @return the last listener that has been removed from the stack
156    */
 
157  3 toggle private Listener popListener()
158    {
159  3 Listener listener = this.listenerStack.pop();
160  3 if (!this.listenerStack.isEmpty()) {
161  3 setWrappedListener(this.listenerStack.peek());
162    }
163  3 return listener;
164    }
165   
166    /**
167    * @return the last listener in the stack
168    */
 
169  0 toggle private Listener peekListener()
170    {
171  0 return this.listenerStack.peek();
172    }
173    }