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

File RightMap.java

 

Coverage histogram

../../../../img/srcFileCovDistChart8.png
54% of files have more coverage

Code metrics

84
158
53
8
631
448
98
0.62
2.98
6.62
1.85

Classes

Class Line # Actions
RightMap 44 78 0% 49 46
0.691275269.1%
RightMap.RightSet 268 7 0% 5 2
0.833333383.3%
RightMap.Values 309 5 0% 5 0
1.0100%
RightMap.EntrySet 353 26 0% 15 5
0.895833389.6%
RightMap.AbstractRightMapIterator 442 7 0% 5 0
1.0100%
RightMap.RightIterator 474 4 0% 2 2
0.7142857371.4%
RightMap.ValueIterator 490 4 0% 2 2
0.7142857371.4%
RightMap.EntryIterator 506 27 0% 15 23
0.5306122353.1%
 

Contributing tests

This file is covered by 1 test. .

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.security.authorization;
21   
22    import java.io.IOException;
23    import java.io.ObjectInputStream;
24    import java.io.ObjectOutputStream;
25    import java.io.Serializable;
26    import java.util.AbstractCollection;
27    import java.util.AbstractMap;
28    import java.util.AbstractSet;
29    import java.util.ArrayList;
30    import java.util.Collection;
31    import java.util.Iterator;
32    import java.util.List;
33    import java.util.Map;
34    import java.util.NoSuchElementException;
35    import java.util.Set;
36   
37    /**
38    * Optimized map implementation with a key of type Right.
39    *
40    * @param <V> the value type of this map
41    * @version $Id: d4987285b8fd73492de92b7803062e831f12723f $
42    * @since 4.0M2
43    */
 
44    public class RightMap<V> extends AbstractMap<Right, V> implements Serializable, Cloneable
45    {
46    /** Serialization identifier. */
47    private static final long serialVersionUID = 1L;
48   
49    /** Need to distinct null and NULL. */
50    private static final Object NULL = new Object();
51   
52    /** Array list to store values. */
53    private transient List<Object> rights;
54   
55    /** Cached key set. */
56    private transient Set<Right> keySet;
57   
58    /** Cached value collection. */
59    private transient Collection<V> values;
60   
61    /** Cached entry set. */
62    private transient Set<Entry<Right, V>> entrySet;
63   
64    /** Cached size. */
65    private transient int size;
66   
67    /** Default constructor. */
 
68  102 toggle public RightMap() {
69  102 rights = new ArrayList<Object>(Right.size());
70    }
71   
72    /**
73    * Convert null to NULL.
74    * @param value the value to convert
75    * @return the converted value
76    */
 
77  1359 toggle private Object maskNull(Object value) {
78  1359 return (value == null ? NULL : value);
79    }
80   
81    /**
82    * Convert NULL to null.
83    * @param value the value to convert
84    * @return the converted value
85    */
 
86  2784 toggle @SuppressWarnings("unchecked")
87    private V unmaskNull(Object value) {
88  2784 return (V) (value == NULL ? null : value);
89    }
90   
 
91  4 toggle @Override
92    public void clear()
93    {
94  4 rights.clear();
95  4 size = 0;
96    }
97   
 
98  0 toggle @Override
99    @SuppressWarnings("unchecked")
100    protected Object clone() throws CloneNotSupportedException
101    {
102  0 RightMap<V> clone = (RightMap<V>) super.clone();
103  0 clone.rights.addAll(rights);
104  0 clone.size = size();
105  0 return clone;
106    }
107   
 
108  191 toggle @Override
109    public boolean containsKey(Object o)
110    {
111  191 return o instanceof Right && getValue(((Right) o).ordinal()) != null;
112    }
113   
 
114  711 toggle @Override
115    public boolean containsValue(Object o)
116    {
117  711 return rights.contains(maskNull(o));
118    }
119   
 
120  10 toggle @Override
121    public boolean equals(Object o)
122    {
123  10 if (!(o instanceof RightMap)) {
124  4 return super.equals(o);
125    }
126   
127  6 RightMap rmap = (RightMap) o;
128   
129    // Key types match, compare each value
130  65 for (int i = 0; i < Right.size(); i++) {
131  61 Object val = getValue(i);
132  61 Object rval = rmap.getValue(i);
133  61 if (rval != val && (rval == null || !rval.equals(val))) {
134  2 return false;
135    }
136    }
137  4 return true;
138    }
139   
 
140  194 toggle @Override
141    public V get(Object o)
142    {
143  194 return (o instanceof Right ? unmaskNull(getValue(((Right) o).ordinal())) : null);
144    }
145   
 
146  12 toggle @Override
147    public int hashCode()
148    {
149  12 return rights.isEmpty() ? 0 : rights.hashCode();
150    }
151   
 
152  53 toggle @Override
153    public boolean isEmpty()
154    {
155  53 return (size == 0);
156    }
157   
158    /**
159    * Retrieve a value from the map.
160    * @param index index to retrieve
161    * @return a value for the given index or null
162    */
 
163  11846 toggle @SuppressWarnings("unchecked")
164    private V getValue(int index)
165    {
166  11846 return (index < rights.size()) ? (V) rights.get(index) : null;
167    }
168   
169    /**
170    * Update a value in the map, keeping size in sync.
171    * @param index the index to update
172    * @param newValue the new value for this index, should be NULL for real null
173    * @return the old value at the index
174    */
 
175  488 toggle @SuppressWarnings("unchecked")
176    private V updateValue(int index, Object newValue)
177    {
178  488 if (index < 0) {
179  1 return null;
180    }
181  487 if (rights.size() <= index) {
182  91 ((ArrayList) rights).ensureCapacity(Right.size() + 1);
183  1274 while (rights.size() <= Right.size()) {
184  1183 rights.add(null);
185    }
186    }
187  487 Object oldValue = rights.set(index, newValue);
188  487 if (oldValue == null) {
189  460 if (newValue != null) {
190  459 size++;
191    }
192  460 return null;
193    }
194  27 if (newValue == null) {
195  22 size--;
196    }
197  27 return unmaskNull(oldValue);
198    }
199   
 
200  463 toggle @Override
201    public V put(Right right, V value)
202    {
203  463 return updateValue(right.ordinal(), maskNull(value));
204    }
205   
 
206  2 toggle @Override
207    @SuppressWarnings("unchecked")
208    public void putAll(Map<? extends Right, ? extends V> map)
209    {
210  2 if (map instanceof RightMap) {
211  0 RightMap<? extends V> rmap = (RightMap<? extends V>) map;
212   
213  0 for (int i = 0; i < Right.size(); i++) {
214  0 updateValue(i, rmap.getValue(i));
215    }
216    } else {
217  2 super.putAll(map);
218    }
219    }
220   
 
221  5 toggle @Override
222    public V remove(Object o)
223    {
224  5 if (o instanceof Right) {
225  5 return updateValue(((Right) o).ordinal(), null);
226    }
227  0 return null;
228    }
229   
 
230  653 toggle @Override
231    public int size()
232    {
233  653 return size;
234    }
235   
 
236  0 toggle @Override
237    public String toString()
238    {
239  0 StringBuilder sb = new StringBuilder("[");
240  0 boolean first = true;
241  0 for (int i = 0; i < rights.size(); i++) {
242  0 if (getValue(i) != null) {
243  0 if (first) {
244  0 first = false;
245    } else {
246  0 sb.append(", ");
247    }
248  0 sb.append(Right.get(i).getName())
249    .append(" = ")
250    .append(unmaskNull(getValue(i)).toString());
251    }
252    }
253  0 sb.append("]");
254  0 return sb.toString();
255    }
256   
 
257  64 toggle @Override
258    public Set<Right> keySet() {
259  64 if (keySet == null) {
260  49 keySet = new RightSet();
261    }
262  64 return keySet;
263    }
264   
265    /**
266    * Private right set for representing keys of this map.
267    */
 
268    private class RightSet extends AbstractSet<Right>
269    {
 
270  164 toggle @Override
271    public Iterator<Right> iterator() {
272  164 return new RightIterator();
273    }
274   
 
275  206 toggle @Override
276    public int size() {
277  206 return size;
278    }
279   
 
280  0 toggle @Override
281    public boolean contains(Object o) {
282  0 return containsKey(o);
283    }
284   
 
285  2 toggle @Override
286    public boolean remove(Object o) {
287  2 int oldSize = size;
288  2 RightMap.this.remove(o);
289  2 return size != oldSize;
290    }
291   
 
292  1 toggle @Override
293    public void clear() {
294  1 RightMap.this.clear();
295    }
296    }
297   
 
298  112 toggle @Override
299    public Collection<V> values() {
300  112 if (values == null) {
301  48 values = new Values();
302    }
303  112 return values;
304    }
305   
306    /**
307    * Private value collection for representing value of this map.
308    */
 
309    private class Values extends AbstractCollection<V>
310    {
 
311  367 toggle @Override
312    public Iterator<V> iterator()
313    {
314  367 return new ValueIterator();
315    }
316   
 
317  307 toggle @Override
318    public int size()
319    {
320  307 return size;
321    }
322   
 
323  352 toggle @Override
324    public boolean contains(Object o)
325    {
326  352 return containsValue(o);
327    }
328   
 
329  2 toggle @Override
330    public boolean remove(Object o)
331    {
332  2 return updateValue(rights.indexOf(maskNull(o)), null) != null;
333    }
334   
 
335  1 toggle @Override
336    public void clear()
337    {
338  1 RightMap.this.clear();
339    }
340    }
341   
 
342  115 toggle @Override
343    public Set<Entry<Right, V>> entrySet() {
344  115 if (entrySet == null) {
345  93 entrySet = new EntrySet();
346    }
347  115 return entrySet;
348    }
349   
350    /**
351    * Private EntrySet for representing this map.
352    */
 
353    private class EntrySet extends AbstractSet<Entry<Right, V>>
354    {
 
355  269 toggle @Override
356    public Iterator<Entry<Right, V>> iterator()
357    {
358  269 return new EntryIterator();
359    }
360   
 
361  239 toggle @Override
362    public boolean contains(Object o)
363    {
364  239 if (!(o instanceof Map.Entry)) {
365  51 return false;
366    }
367   
368  188 Map.Entry entry = (Map.Entry) o;
369  188 return entry.getKey() instanceof Right
370    && maskNull(entry.getValue()).equals(getValue(((Right) entry.getKey()).ordinal()));
371    }
372   
 
373  5 toggle @Override
374    public boolean remove(Object o)
375    {
376  5 if (!(o instanceof Map.Entry)) {
377  0 return false;
378    }
379   
380  5 Map.Entry entry = (Map.Entry) o;
381  5 if (contains(entry)) {
382  2 updateValue(((Right) entry.getKey()).ordinal(), null);
383  2 return true;
384    }
385  3 return false;
386    }
387   
 
388  243 toggle @Override
389    public int size()
390    {
391  243 return size;
392    }
393   
 
394  1 toggle @Override
395    public void clear()
396    {
397  1 RightMap.this.clear();
398    }
399   
 
400  51 toggle @Override
401    public Object[] toArray()
402    {
403  51 return fillArray(new Object[size]);
404    }
405   
 
406  51 toggle @Override
407    @SuppressWarnings("unchecked")
408    public <T> T[] toArray(T[] ts)
409    {
410  51 T[] a = ts;
411  51 if (a.length < size) {
412  0 a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
413    }
414  51 if (a.length > size) {
415  51 a[size] = null;
416    }
417  51 return (T[]) fillArray(a);
418    }
419   
420    /**
421    * Fill array ts that should have the appropriate size with the {@code Entry} in this set.
422    * @param a an array properly sized to receive this set
423    * @return an array representing this set
424    */
 
425  102 toggle private Object[] fillArray(Object[] a)
426    {
427  102 int j = 0;
428  1116 for (int i = 0; i < rights.size(); i++) {
429  1014 if (getValue(i) != null) {
430  350 a[j++] = new AbstractMap.SimpleEntry<Right, V>(
431    Right.get(i), unmaskNull(getValue(i)));
432    }
433    }
434  102 return a;
435    }
436    }
437   
438    /**
439    * Private abstract iterator for this map.
440    * @param <T> Value type
441    */
 
442    private abstract class AbstractRightMapIterator<T> implements Iterator<T>
443    {
444    /** Current index. */
445    protected int index;
446   
447    /** Last returned index. */
448    protected int lastIndex = -1;
449   
 
450  4541 toggle @Override
451    public boolean hasNext()
452    {
453    // Skip empty buckets
454  8203 while (index < rights.size() && getValue(index) == null) {
455  3662 index++;
456    }
457  4541 return index != rights.size();
458    }
459   
 
460  17 toggle @Override
461    public void remove()
462    {
463  17 if (lastIndex < 0) {
464  2 throw new IllegalStateException();
465    }
466  15 updateValue(lastIndex, null);
467  15 lastIndex = -1;
468    }
469    }
470   
471    /**
472    * Private iterator for keys.
473    */
 
474    private class RightIterator extends AbstractRightMapIterator<Right>
475    {
 
476  365 toggle @Override
477    public Right next()
478    {
479  365 if (!hasNext()) {
480  0 throw new NoSuchElementException();
481    }
482  365 lastIndex = index++;
483  365 return Right.get(lastIndex);
484    }
485    }
486   
487    /**
488    * Private iterator for values.
489    */
 
490    private class ValueIterator extends AbstractRightMapIterator<V>
491    {
 
492  940 toggle @Override
493    public V next()
494    {
495  940 if (!hasNext()) {
496  0 throw new NoSuchElementException();
497    }
498  940 lastIndex = index++;
499  940 return unmaskNull(getValue(lastIndex));
500    }
501    }
502   
503    /**
504    * Private iterator for entries.
505    */
 
506    private class EntryIterator extends AbstractRightMapIterator<Entry<Right, V>> implements Map.Entry<Right, V>
507    {
 
508  606 toggle @Override
509    public Map.Entry<Right, V> next()
510    {
511  606 if (!hasNext()) {
512  0 throw new NoSuchElementException();
513    }
514  606 lastIndex = index++;
515  606 return this;
516    }
517   
 
518  264 toggle @Override
519    public Right getKey()
520    {
521  264 checkLastIndex();
522  264 return Right.get(lastIndex);
523    }
524   
 
525  257 toggle @Override
526    public V getValue()
527    {
528  257 checkLastIndex();
529  257 return unmaskNull(RightMap.this.getValue(lastIndex));
530    }
531   
 
532  2 toggle @Override
533    public V setValue(V value)
534    {
535  2 checkLastIndex();
536  2 return updateValue(lastIndex, value);
537    }
538   
 
539  1017 toggle @Override
540    public boolean equals(Object o)
541    {
542  1017 if (lastIndex < 0) {
543  0 return o == this;
544    }
545   
546  1017 if (!(o instanceof Map.Entry)) {
547  0 return false;
548    }
549   
550  1017 Map.Entry e = (Map.Entry) o;
551  1017 V val = unmaskNull(RightMap.this.getValue(lastIndex));
552  1017 Object rval = e.getValue();
553  1017 return e.getKey() == Right.get(lastIndex) && (val == rval || (val != null && val.equals(rval)));
554    }
555   
 
556  0 toggle @Override
557    public int hashCode()
558    {
559  0 if (lastIndex < 0) {
560  0 return super.hashCode();
561    }
562   
563  0 Object value = RightMap.this.getValue(lastIndex);
564  0 return Right.get(lastIndex).hashCode() ^ (value == NULL ? 0 : value.hashCode());
565    }
566   
 
567  0 toggle @Override
568    public String toString()
569    {
570  0 if (lastIndex < 0) {
571  0 return super.toString();
572    }
573   
574  0 return Right.get(lastIndex) + "=" + unmaskNull(RightMap.this.getValue(lastIndex));
575    }
576   
577    /**
578    * Throws if lastIndex is invalid.
579    */
 
580  523 toggle private void checkLastIndex()
581    {
582  523 if (lastIndex < 0) {
583  0 throw new IllegalStateException("Entry was removed");
584    }
585    }
586    }
587   
588    /**
589    * Serialization support.
590    *
591    * @param s the output stream
592    * @throws IOException on error
593    */
 
594  0 toggle private void writeObject(ObjectOutputStream s) throws IOException
595    {
596    // Write out the key type and any hidden stuff
597  0 s.defaultWriteObject();
598   
599    // Write out size (number of Mappings)
600  0 s.writeInt(size);
601   
602    // Write out keys and values (alternating)
603  0 for (Map.Entry<Right, V> e : entrySet()) {
604  0 s.writeObject(e.getKey());
605  0 s.writeObject(e.getValue());
606    }
607    }
608   
609    /**
610    * Serialization support.
611    *
612    * @param s the input stream
613    * @throws IOException on error
614    * @throws ClassNotFoundException on error
615    */
 
616  0 toggle @SuppressWarnings("unchecked")
617    private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException
618    {
619    // Read in the key type and any hidden stuff
620  0 s.defaultReadObject();
621   
622  0 rights = new ArrayList<Object>(Right.size());
623   
624    // Read the keys and values, and put the mappings in the HashMap
625  0 for (int i = 0; i < s.readInt(); i++) {
626  0 Right key = (Right) s.readObject();
627  0 V value = (V) s.readObject();
628  0 put(key, value);
629    }
630    }
631    }