1. Project Clover database Tue Dec 20 2016 21:24:09 CET
  2. Package org.xwiki.model.reference

File EntityReferenceSet.java

 

Coverage histogram

../../../../img/srcFileCovDistChart9.png
38% of files have more coverage

Code metrics

74
127
20
3
396
270
60
0.47
6.35
6.67
3

Classes

Class Line # Actions
EntityReferenceSet 41 57 0% 27 6
0.9494%
EntityReferenceSet.EntityReferenceEntryChildren 43 16 0% 6 7
0.730769273.1%
EntityReferenceSet.EntityReferenceEntry 87 54 0% 27 23
0.7578947575.8%
 

Contributing tests

This file is covered by 18 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.model.reference;
21   
22    import java.io.Serializable;
23    import java.util.ArrayList;
24    import java.util.Collections;
25    import java.util.HashMap;
26    import java.util.HashSet;
27    import java.util.List;
28    import java.util.Map;
29    import java.util.Objects;
30    import java.util.Set;
31   
32    import org.apache.commons.collections.CollectionUtils;
33    import org.xwiki.model.EntityType;
34   
35    /**
36    * A set of entities references.
37    *
38    * @version $Id: 0c462c78d7420c277617c7e165c2a423e62abfec $
39    * @since 5.2M2
40    */
 
41    public class EntityReferenceSet
42    {
 
43    private static class EntityReferenceEntryChildren
44    {
45    public EntityType childrenType;
46   
47    public Map<String, EntityReferenceEntry> children;
48   
 
49  74 toggle public EntityReferenceEntry add(String name, Map<String, Serializable> entityParameters)
50    {
51  74 if (this.children == null) {
52  53 this.children = new HashMap<String, EntityReferenceEntry>();
53    }
54   
55  74 EntityReferenceEntry entry = this.children.get(name);
56   
57  74 if (entry == null) {
58  58 entry = new EntityReferenceEntry(this.childrenType, name);
59   
60  58 if (entityParameters != null) {
61  58 entry.addParameters(entityParameters);
62    }
63   
64  58 this.children.put(name, entry);
65    } else {
66  16 if (!entry.matches(entityParameters)) {
67  3 entry.addParameters(entityParameters);
68    }
69    }
70   
71  74 return entry;
72    }
73   
 
74  0 toggle @Override
75    public String toString()
76    {
77  0 StringBuilder builder = new StringBuilder();
78   
79  0 builder.append(this.childrenType);
80  0 builder.append('(');
81  0 builder.append(this.children);
82   
83  0 return builder.toString();
84    }
85    }
86   
 
87    private static class EntityReferenceEntry
88    {
89    public EntityType type;
90   
91    public String name;
92   
93    public List<Map<String, Serializable>> parameters;
94   
95    public Map<EntityType, EntityReferenceEntryChildren> children;
96   
 
97  22 toggle public EntityReferenceEntry()
98    {
99    }
100   
 
101  58 toggle public EntityReferenceEntry(EntityType type, String name)
102    {
103  58 this.type = type;
104  58 this.name = name;
105    }
106   
 
107  0 toggle public EntityReferenceEntry add()
108    {
109  0 return add(null, null, null);
110    }
111   
 
112  86 toggle public EntityReferenceEntryChildren getChildren(EntityType entityType, boolean create)
113    {
114  86 if (this.children == null) {
115  51 if (!create) {
116  0 return null;
117    }
118   
119  51 this.children = new HashMap<>();
120    }
121   
122  86 EntityReferenceEntryChildren child = this.children.get(entityType);
123   
124  86 if (child == null) {
125  55 if (!create) {
126  2 return null;
127    }
128   
129  53 child = new EntityReferenceEntryChildren();
130  53 child.childrenType = entityType;
131  53 this.children.put(entityType, child);
132    }
133   
134  84 return child;
135    }
136   
 
137  12 toggle public EntityReferenceEntryChildren getClosestChildren(EntityType entityType)
138    {
139  12 EntityReferenceEntryChildren typedChildren = getChildren(entityType, false);
140   
141  12 if (typedChildren != null) {
142  10 return typedChildren;
143    }
144   
145    // Search for the closest
146   
147  2 if (this.children == null) {
148  0 return null;
149    }
150   
151  2 for (Map.Entry<EntityType, EntityReferenceEntryChildren> entry : this.children.entrySet()) {
152  2 EntityReferenceEntryChildren typedChilrendEntry = entry.getValue();
153   
154  2 if (typedChilrendEntry.childrenType.ordinal() > entityType.ordinal()) {
155    // Only return a potential child of the passed type
156  2 if (typedChildren == null
157    || typedChildren.childrenType.ordinal() > typedChilrendEntry.childrenType.ordinal()) {
158  2 typedChildren = typedChilrendEntry;
159    }
160    }
161    }
162   
163  2 return typedChildren;
164    }
165   
 
166  74 toggle public EntityReferenceEntry add(EntityType entityType, String entityName,
167    Map<String, Serializable> entityParameters)
168    {
169  74 EntityReferenceEntryChildren child = getChildren(entityType, true);
170   
171  74 return child.add(entityName, entityParameters);
172    }
173   
 
174  61 toggle private void addParameters(Map<String, Serializable> entityParameters)
175    {
176  61 if (!entityParameters.isEmpty()) {
177  10 if (this.parameters == null) {
178  7 this.parameters = new ArrayList<Map<String, Serializable>>();
179    }
180   
181  10 this.parameters.add(entityParameters);
182    }
183    }
184   
 
185  213 toggle public boolean matches(EntityReference reference)
186    {
187  213 return matches(reference.getParameters());
188    }
189   
 
190  229 toggle public boolean matches(Map<String, Serializable> referenceParameters)
191    {
192  229 if (parameters == null) {
193  187 return true;
194    }
195   
196  42 boolean matches = parameters.isEmpty();
197   
198  42 for (Map<String, Serializable> parametersMap : parameters) {
199  54 matches |= matches(referenceParameters, parametersMap);
200    }
201   
202  42 return matches;
203    }
204   
 
205  54 toggle private boolean matches(Map<String, Serializable> referenceParameters, Map<String, Serializable> map)
206    {
207  54 for (Map.Entry<String, Serializable> entry : map.entrySet()) {
208  54 if (referenceParameters.containsKey(entry.getKey())) {
209  45 if (!Objects.equals(entry.getValue(), referenceParameters.get(entry.getKey()))) {
210  20 return false;
211    }
212    }
213    }
214   
215  34 return true;
216    }
217   
 
218  0 toggle @Override
219    public String toString()
220    {
221  0 StringBuilder builder = new StringBuilder();
222   
223  0 if (this.type != null) {
224  0 builder.append(this.type);
225  0 builder.append(':');
226  0 builder.append(this.name);
227    }
228   
229  0 if (this.children != null) {
230  0 builder.append('(');
231  0 builder.append(this.children);
232  0 builder.append(')');
233    }
234   
235  0 return builder.toString();
236    }
237    }
238   
239    private EntityReferenceEntry includes;
240   
241    private EntityReferenceEntry excludes;
242   
 
243  32 toggle private void add(EntityReference reference, EntityReferenceEntry entry)
244    {
245  32 EntityReferenceEntry currentEntry = entry;
246   
247  32 for (EntityReference element : reference.getReversedReferenceChain()) {
248    // Move the first element to the right level in the tree
249  74 if (currentEntry == entry) {
250  32 while (currentEntry.children != null && currentEntry.getClosestChildren(element.getType()) == null) {
251  0 currentEntry = currentEntry.add();
252    }
253    }
254   
255  74 currentEntry = currentEntry.add(element.getType(), element.getName(), element.getParameters());
256    }
257    }
258   
259    /**
260    * @param reference the reference
261    * @return the entity reference set
262    */
 
263  24 toggle public EntityReferenceSet includes(EntityReference reference)
264    {
265  24 if (this.includes == null) {
266  16 this.includes = new EntityReferenceEntry();
267    }
268   
269  24 add(reference, this.includes);
270   
271  24 return this;
272    }
273   
274    /**
275    * @param reference the reference
276    * @return the entity reference set
277    */
 
278  8 toggle public EntityReferenceSet excludes(EntityReference reference)
279    {
280  8 if (this.excludes == null) {
281  6 this.excludes = new EntityReferenceEntry();
282    }
283   
284  8 add(reference, this.excludes);
285   
286  8 return this;
287    }
288   
 
289  122 toggle private boolean matchesInclude(EntityReference reference)
290    {
291  122 if (this.includes == null) {
292  33 return true;
293    }
294   
295  89 EntityReferenceEntry currentEntry = this.includes;
296  89 for (EntityReference element : reference.getReversedReferenceChain()) {
297    // No children
298  204 if (currentEntry.children == null) {
299  2 return true;
300    }
301   
302  202 EntityReferenceEntryChildren typedChildren = currentEntry.children.get(element.getType());
303   
304  202 if (typedChildren != null) {
305    // Children have same type
306  195 EntityReferenceEntry nameEntry = typedChildren.children.get(element.getName());
307   
308  195 if (nameEntry == null) {
309  28 currentEntry = typedChildren.children.get(null);
310   
311  28 if (currentEntry == null) {
312  28 return false;
313    }
314    } else {
315  167 currentEntry = nameEntry;
316    }
317   
318  167 if (!currentEntry.matches(element)) {
319  5 return false;
320    }
321    } else {
322  7 if (currentEntry.name != null || currentEntry.getClosestChildren(element.getType()) == null) {
323  5 return false;
324    }
325    }
326    }
327   
328  49 return true;
329    }
330   
 
331  84 toggle private boolean matchesExclude(EntityReference reference)
332    {
333  84 if (this.excludes == null) {
334  51 return true;
335    }
336   
337  33 EntityReferenceEntry currentEntry = this.excludes;
338  33 for (EntityReference element : reference.getReversedReferenceChain()) {
339    // No children
340  63 if (currentEntry.children == null) {
341  2 return false;
342    }
343   
344  61 EntityReferenceEntryChildren typedChildren = currentEntry.children.get(element.getType());
345   
346  61 if (typedChildren != null) {
347    // Children have same type
348  58 EntityReferenceEntry nameEntry = typedChildren.children.get(element.getName());
349   
350  58 if (nameEntry == null) {
351  12 currentEntry = typedChildren.children.get(null);
352   
353  12 if (currentEntry == null) {
354  12 return true;
355    }
356    } else {
357  46 currentEntry = nameEntry;
358    }
359   
360  46 if (!currentEntry.matches(element)) {
361  3 return true;
362    }
363    }
364    }
365   
366    // Check if the reference is shorter than the exclude(s)
367  16 return currentEntry.children != null
368    // Check if the excluded parameters are the same as the one the reference contains
369    || (currentEntry.parameters != null && CollectionUtils.intersection(
370    getParametersKeys(currentEntry.parameters), reference.getParameters().keySet()).isEmpty());
371    }
372   
 
373  5 toggle private Set<String> getParametersKeys(List<Map<String, Serializable>> parameters)
374    {
375  5 if (parameters.isEmpty()) {
376  0 return Collections.emptySet();
377    }
378   
379  5 Set<String> set = new HashSet<String>();
380   
381  5 for (Map<String, Serializable> map : parameters) {
382  8 set.addAll(map.keySet());
383    }
384   
385  5 return set;
386    }
387   
388    /**
389    * @param reference the reference
390    * @return the entity reference set
391    */
 
392  122 toggle public boolean matches(EntityReference reference)
393    {
394  122 return matchesInclude(reference) && matchesExclude(reference);
395    }
396    }