1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.rendering.block.match

File BlockNavigator.java

 

Coverage histogram

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

Code metrics

44
129
7
1
305
189
54
0.42
18.43
7
7.71

Classes

Class Line # Actions
BlockNavigator 35 129 0% 54 14
0.922222292.2%
 

Contributing tests

This file is covered by 462 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.block.match;
21   
22    import java.util.ArrayList;
23    import java.util.Collections;
24    import java.util.List;
25   
26    import org.xwiki.rendering.block.Block;
27    import org.xwiki.rendering.block.Block.Axes;
28   
29    /**
30    * Tool to navigate in a tree of blocks and extract them based on configurable criteria.
31    *
32    * @version $Id: e26c8beac34b7eb222b6cb8b1274e0cf20c98223 $
33    * @since 5.0M1
34    */
 
35    public class BlockNavigator
36    {
37    /**
38    * Used to filter the result of the various methods.
39    */
40    private BlockMatcher matcher;
41   
42    /**
43    * The default matcher does not filter anything.
44    */
 
45  2 toggle public BlockNavigator()
46    {
47  2 this.matcher = AnyBlockMatcher.ANYBLOCKMATCHER;
48    }
49   
50    /**
51    * @param matcher used to filter the result of the various methods
52    */
 
53  80679 toggle public BlockNavigator(BlockMatcher matcher)
54    {
55  80676 this.matcher = matcher;
56    }
57   
58    // Blocks
59   
60    /**
61    * Get all blocks following provided {@link BlockMatcher} and {@link Axes}.
62    *
63    * @param <T> the class of the Blocks to return
64    * @param currentBlock the block to start searching from
65    * @param currentAxes indicate the search axes
66    * @return the matched {@link Block}s, empty list of none was found
67    */
 
68  1346072 toggle public <T extends Block> List<T> getBlocks(Block currentBlock, Axes currentAxes)
69    {
70  1346074 List<T> blocks = new ArrayList<T>();
71   
72  1346075 Block block = currentBlock;
73  1346074 Axes axes = currentAxes;
74   
75  2708740 while (block != null) {
76  1362665 Block nextBlock = null;
77   
78  1362663 switch (axes) {
79    // SELF
80  2 case SELF:
81  2 addBlock(block, blocks);
82  2 break;
83    // ANCESTOR
84  7 case ANCESTOR_OR_SELF:
85  7 addBlock(block, blocks);
86  7 nextBlock = block.getParent();
87  7 break;
88  2 case ANCESTOR:
89  2 nextBlock = block.getParent();
90  2 axes = Axes.ANCESTOR_OR_SELF;
91  2 break;
92  1 case PARENT:
93  1 nextBlock = block.getParent();
94  1 axes = Axes.SELF;
95  1 break;
96    // DESCENDANT
97  26728 case CHILD:
98  26733 if (!block.getChildren().isEmpty()) {
99  14156 nextBlock = block.getChildren().get(0);
100  14151 axes = Axes.FOLLOWING_SIBLING;
101  14151 addBlock(nextBlock, blocks);
102    }
103  26729 break;
104  1311381 case DESCENDANT_OR_SELF:
105  1311381 addBlock(block, blocks);
106  1311381 blocks = getBlocks(block.getChildren(), Axes.DESCENDANT_OR_SELF, blocks);
107  1311381 break;
108  7955 case DESCENDANT:
109  7955 blocks = getBlocks(block.getChildren(), Axes.DESCENDANT_OR_SELF, blocks);
110  7955 break;
111    // FOLLOWING
112  16580 case FOLLOWING_SIBLING:
113  16580 nextBlock = block.getNextSibling();
114  16581 addBlock(nextBlock, blocks);
115  16583 break;
116  1 case FOLLOWING:
117  2 for (Block nextSibling = block.getNextSibling(); nextSibling != null;
118    nextSibling = nextSibling.getNextSibling()) {
119  1 blocks = getBlocks(nextSibling, Axes.DESCENDANT_OR_SELF, blocks);
120    }
121  1 break;
122    // PRECEDING
123  2 case PRECEDING_SIBLING:
124  2 nextBlock = block.getPreviousSibling();
125  2 addBlock(nextBlock, blocks);
126  2 break;
127  1 case PRECEDING:
128  2 for (Block previousSibling = block.getPreviousSibling(); previousSibling != null;
129    previousSibling = previousSibling.getPreviousSibling()) {
130  1 blocks = getBlocks(previousSibling, Axes.DESCENDANT_OR_SELF, blocks);
131    }
132  1 break;
133  0 default:
134  0 break;
135    }
136   
137  1362672 block = nextBlock;
138    }
139   
140  1346075 return blocks != null ? blocks : Collections.<T>emptyList();
141    }
142   
143    /**
144    * Add provided {@link Block} to provided list (or create list of null) if block validate the provided
145    * {@link BlockMatcher}.
146    *
147    * @param <T> the class of the Blocks to return
148    * @param currentBlock the block to search from
149    * @param blocks the list of blocks to fill
150    */
 
151  1342129 toggle private <T extends Block> void addBlock(Block currentBlock, List<T> blocks)
152    {
153  1342132 if (currentBlock != null && this.matcher.match(currentBlock)) {
154  3634 blocks.add((T) currentBlock);
155    }
156    }
157   
158    /**
159    * Add all blocks following provided {@link BlockMatcher} and {@link Axes} in the provide list (or create a new list
160    * of provided list is null).
161    *
162    * @param <T> the class of the Blocks to return
163    * @param blocks the blocks from where to search
164    * @param axes the axes
165    * @param blocksOut the list of blocks to fill
166    * @return the modified list, null if provided list is null and provided {@link Block} does not validate provided
167    * {@link BlockMatcher}
168    */
 
169  1319336 toggle private <T extends Block> List<T> getBlocks(List<Block> blocks, Axes axes, List<T> blocksOut)
170    {
171  1319336 List<T> newBlocks = blocksOut;
172   
173  1319336 for (Block block : blocks) {
174  1311378 newBlocks = getBlocks(block, axes, newBlocks);
175    }
176   
177  1319336 return newBlocks;
178    }
179   
180    /**
181    * Add all blocks following provided {@link BlockMatcher} and {@link Axes} in the provide list (or create a new list
182    * of provided list is null).
183    *
184    * @param <T> the class of the Blocks to return
185    * @param currentBlock the block to search from
186    * @param axes the axes
187    * @param blocksOut the list of blocks to fill
188    * @return the modified list, null if provided list is null and provided {@link Block} does not validate provided
189    * {@link BlockMatcher}
190    */
 
191  1311380 toggle private <T extends Block> List<T> getBlocks(Block currentBlock, Axes axes, List<T> blocksOut)
192    {
193  1311380 List<T> newBlocks = blocksOut;
194   
195  1311380 List<T> nextBlocks = getBlocks(currentBlock, axes);
196  1311380 if (!nextBlocks.isEmpty()) {
197  3176 if (newBlocks == null) {
198  0 newBlocks = nextBlocks;
199    } else {
200  3176 newBlocks.addAll(nextBlocks);
201    }
202    }
203   
204  1311380 return newBlocks;
205    }
206   
207    // First block
208   
209    /**
210    * Get the first matched block in the provided {@link Axes}.
211    *
212    * @param <T> the class of the Block to return
213    * @param currentBlock the block to start searching from
214    * @param currentAxes indicate the search axes
215    * @return the matched {@link Block}, null if none was found
216    */
 
217  1715617 toggle public <T extends Block> T getFirstBlock(Block currentBlock, Axes currentAxes)
218    {
219  1715617 Block block = currentBlock;
220  1715617 Axes axes = currentAxes;
221   
222  3442296 while (block != null) {
223  1738181 Block nextBlock = null;
224  1738181 switch (axes) {
225    // SELF
226  4 case SELF:
227  4 if (this.matcher.match(block)) {
228  2 return (T) block;
229    }
230  2 break;
231    // ANCESTOR
232  31787 case ANCESTOR_OR_SELF:
233  31785 if (this.matcher.match(block)) {
234  11471 return (T) block;
235    }
236  9973 case ANCESTOR:
237  2 case PARENT:
238  30290 axes = axes == Axes.PARENT ? Axes.SELF : Axes.ANCESTOR_OR_SELF;
239  30290 nextBlock = block.getParent();
240  30291 break;
241    // DESCENDANT
242  2 case CHILD:
243  2 List<Block> children = block.getChildren();
244  2 if (!children.isEmpty()) {
245  2 nextBlock = children.get(0);
246  2 axes = Axes.FOLLOWING_SIBLING;
247  2 if (this.matcher.match(nextBlock)) {
248  1 return (T) nextBlock;
249    }
250    }
251  1 break;
252  1669616 case DESCENDANT_OR_SELF:
253  1669614 if (this.matcher.match(block)) {
254  10 return (T) block;
255    }
256  26787 case DESCENDANT:
257  1696392 for (Block child : block.getChildren()) {
258  1669608 Block matchedBlock = getFirstBlock(child, Axes.DESCENDANT_OR_SELF);
259  1669610 if (matchedBlock != null) {
260  11 return (T) matchedBlock;
261    }
262    }
263  1696384 break;
264    // FOLLOWING
265  4 case FOLLOWING_SIBLING:
266  4 nextBlock = block.getNextSibling();
267  4 if (nextBlock != null && this.matcher.match(nextBlock)) {
268  2 return (T) nextBlock;
269    }
270  2 break;
271  2 case FOLLOWING:
272  2 for (Block nextSibling = block.getNextSibling(); nextSibling != null;
273    nextSibling = nextSibling.getNextSibling()) {
274  2 Block matchedBlock = getFirstBlock(nextSibling, Axes.DESCENDANT_OR_SELF);
275  2 if (matchedBlock != null) {
276  2 return (T) matchedBlock;
277    }
278    }
279  0 break;
280    // PRECEDING
281  3 case PRECEDING_SIBLING:
282  3 nextBlock = block.getPreviousSibling();
283  3 if (nextBlock != null && this.matcher.match(nextBlock)) {
284  1 return (T) nextBlock;
285    }
286  2 break;
287  2 case PRECEDING:
288  2 for (Block previousSibling = block.getPreviousSibling(); previousSibling != null;
289    previousSibling = previousSibling.getPreviousSibling()) {
290  2 Block matchedBlock = getFirstBlock(previousSibling, Axes.DESCENDANT_OR_SELF);
291  2 if (matchedBlock != null) {
292  2 return (T) matchedBlock;
293    }
294    }
295  0 break;
296  0 default:
297  0 break;
298    }
299   
300  1726680 block = nextBlock;
301    }
302   
303  1704114 return (T) block;
304    }
305    }