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

File EntityReferenceTreeNode.java

 

Coverage histogram

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

Code metrics

42
74
15
2
281
167
37
0.5
4.93
7.5
2.47

Classes

Class Line # Actions
EntityReferenceTreeNode 40 73 0% 35 16
0.87587.5%
EntityReferenceTreeNode.LocaleComparator 47 1 0% 2 0
1.0100%
 

Contributing tests

This file is covered by 14 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.util.ArrayList;
23    import java.util.Collection;
24    import java.util.Collections;
25    import java.util.Comparator;
26    import java.util.IdentityHashMap;
27    import java.util.List;
28    import java.util.Locale;
29    import java.util.Map;
30    import java.util.TreeMap;
31   
32    import org.xwiki.model.EntityType;
33   
34    /**
35    * A node in a {@link EntityReferenceTree}.
36    *
37    * @version $Id: e4444f7d822a663f2f28b462aee1d0b03ddfaaef $
38    * @since 5.4RC1
39    */
 
40    public class EntityReferenceTreeNode
41    {
42    /**
43    * USed to order {@link Locale}s.
44    *
45    * @version $Id: e4444f7d822a663f2f28b462aee1d0b03ddfaaef $
46    */
 
47    static final class LocaleComparator implements Comparator<Locale>
48    {
49    static final LocaleComparator INSTANCE = new LocaleComparator();
50   
 
51  2 toggle private LocaleComparator()
52    {
53    // Stateless
54    }
55   
 
56  8 toggle @Override
57    public int compare(Locale locale1, Locale locale2)
58    {
59  8 return locale1.toString().compareTo(locale2.toString());
60    }
61    }
62   
63    private final EntityReference reference;
64   
65    private final int referenceSize;
66   
67    private final Comparator<String> comparator;
68   
69    private Map<String, Map<EntityType, EntityReferenceTreeNode>> children;
70   
71    private Map<Locale, EntityReference> locales;
72   
 
73  30 toggle protected EntityReferenceTreeNode(Comparator<String> comparator)
74    {
75  30 this.reference = null;
76  30 this.referenceSize = 0;
77  30 this.comparator = comparator;
78    }
79   
 
80  104 toggle EntityReferenceTreeNode(EntityReference reference, Comparator<String> comparator)
81    {
82  104 this.reference = reference;
83  104 this.referenceSize = reference.getReversedReferenceChain().size();
84  104 this.comparator = comparator;
85    }
86   
 
87  148 toggle void addChild(EntityReference childReference)
88    {
89  148 if (this.children == null) {
90  83 this.children = new TreeMap<String, Map<EntityType, EntityReferenceTreeNode>>(this.comparator);
91    }
92   
93  148 List<EntityReference> childReferenceList = childReference.getReversedReferenceChain();
94   
95  148 EntityReference childNodeReference = childReferenceList.get(this.referenceSize);
96   
97  148 Map<EntityType, EntityReferenceTreeNode> childrenByType = this.children.get(childNodeReference.getName());
98  148 if (childrenByType == null) {
99  103 childrenByType = new IdentityHashMap<>();
100  103 this.children.put(childNodeReference.getName(), childrenByType);
101    }
102   
103  148 EntityReferenceTreeNode childNode = childrenByType.get(childNodeReference.getType());
104  148 if (childNode == null) {
105  104 childNode = new EntityReferenceTreeNode(childNodeReference, this.comparator);
106    }
107   
108  148 if (childReferenceList.size() > this.referenceSize + 1) {
109  104 childNode.addChild(childReference);
110    }
111   
112  148 if (childNodeReference.getParameter(DocumentReference.LOCALE) != null) {
113  8 childNode.addLocale(childReference);
114    }
115   
116  148 childrenByType.put(childNodeReference.getType(), childNode);
117    }
118   
 
119  8 toggle void addLocale(EntityReference childReference)
120    {
121  8 if (this.locales == null) {
122  8 this.locales = new TreeMap<Locale, EntityReference>(LocaleComparator.INSTANCE);
123    }
124   
125  8 this.locales.put((Locale) childReference.getParameter(DocumentReference.LOCALE), childReference);
126    }
127   
128    /**
129    * @return the reference associated to this node
130    */
 
131  268 toggle public EntityReference getReference()
132    {
133  268 return this.reference;
134    }
135   
136    /**
137    * Return the first found direct child with passed name.
138    *
139    * @param name the name of the child node
140    * @return the node associated to the passed name
141    */
 
142  11 toggle public EntityReferenceTreeNode get(String name)
143    {
144  11 Collection<EntityReferenceTreeNode> childrenWhithName = getChildrenInternal(name);
145   
146  11 if (childrenWhithName != null && !childrenWhithName.isEmpty()) {
147  11 return childrenWhithName.iterator().next();
148    }
149   
150  0 return null;
151    }
152   
153    /**
154    * @param path a path in the tree starting from this node, specified as an {@link EntityReference}
155    * @return the node associated to the specified path
156    * @since 7.2M1
157    */
 
158  26 toggle public EntityReferenceTreeNode get(EntityReference path)
159    {
160  26 if (path == null) {
161  1 return null;
162    }
163   
164  25 EntityReferenceTreeNode descendant = this;
165  25 for (EntityReference pathElement : path.getReversedReferenceChain()) {
166  54 if (descendant.children == null) {
167  8 return null;
168    }
169   
170  46 Map<EntityType, EntityReferenceTreeNode> descendantByType = descendant.children.get(pathElement.getName());
171  46 if (descendantByType == null) {
172  1 return null;
173    }
174   
175  45 descendant = descendantByType.get(pathElement.getType());
176  45 if (descendant == null) {
177  1 return null;
178    }
179    }
180   
181  15 return descendant;
182    }
183   
184    /**
185    * @return the child reference nodes
186    */
 
187  120 toggle public Collection<EntityReferenceTreeNode> getChildren()
188    {
189  120 if (this.children != null) {
190  89 List<EntityReferenceTreeNode> childrenList = new ArrayList<>(this.children.size() * 2);
191   
192  89 for (Map<EntityType, EntityReferenceTreeNode> childrenByType : this.children.values()) {
193  115 childrenList.addAll(childrenByType.values());
194    }
195   
196  89 return childrenList;
197    }
198   
199  31 return Collections.emptyList();
200    }
201   
202    /**
203    * @param name the name of the children to return
204    * @return the children with the passed name
205    * @since 7.4M1
206    */
 
207  0 toggle public Collection<EntityReferenceTreeNode> getChildren(String name)
208    {
209  0 Collection<EntityReferenceTreeNode> childrenWhithName = getChildrenInternal(name);
210   
211  0 return childrenWhithName != null ? Collections.unmodifiableCollection(childrenWhithName)
212    : Collections.<EntityReferenceTreeNode>emptyList();
213    }
214   
215    /**
216    * @param type the type of the children to return
217    * @return the children with the passed {@link EntityType}
218    * @since 7.4M1
219    */
 
220  4 toggle public Collection<EntityReferenceTreeNode> getChildren(EntityType type)
221    {
222  4 if (this.children != null) {
223  4 List<EntityReferenceTreeNode> childrenList = new ArrayList<>(this.children.size());
224   
225  4 for (Map<EntityType, EntityReferenceTreeNode> childrenByType : this.children.values()) {
226  4 EntityReferenceTreeNode child = childrenByType.get(type);
227  4 if (child != null) {
228  4 childrenList.add(child);
229    }
230    }
231   
232  4 return childrenList;
233    }
234   
235  0 return Collections.emptyList();
236    }
237   
238    /**
239    * @param name the name of the children to return
240    * @return the children with the passed name
241    */
 
242  11 toggle public Collection<EntityReferenceTreeNode> getChildrenInternal(String name)
243    {
244  11 if (this.children != null) {
245  11 Map<EntityType, EntityReferenceTreeNode> childrenByType = this.children.get(name);
246   
247  11 if (childrenByType != null) {
248  11 return childrenByType.values();
249    }
250    }
251   
252  0 return null;
253    }
254   
255    /**
256    * @return the child references containing a {@link Locale}
257    */
 
258  32 toggle public Collection<EntityReference> getLocales()
259    {
260  32 return this.locales != null ? this.locales.values() : Collections.<EntityReference>emptyList();
261    }
262   
 
263  21 toggle @Override
264    public String toString()
265    {
266  21 StringBuilder builder = new StringBuilder();
267   
268  21 if (getReference() != null) {
269  21 builder.append(getReference());
270    }
271   
272  21 if (!getChildren().isEmpty()) {
273  9 if (builder.length() > 0) {
274  9 builder.append(" = ");
275    }
276  9 builder.append(getChildren());
277    }
278   
279  21 return builder.toString();
280    }
281    }