Coverage Report - com.jcabi.immutable.ArraySortedSet
 
Classes in this File Line Coverage Branch Coverage Complexity
ArraySortedSet
46%
41/89
35%
12/34
1.933
 
 1  
 /**
 2  
  * Copyright (c) 2012-2014, jcabi.com
 3  
  * All rights reserved.
 4  
  *
 5  
  * Redistribution and use in source and binary forms, with or without
 6  
  * modification, are permitted provided that the following conditions
 7  
  * are met: 1) Redistributions of source code must retain the above
 8  
  * copyright notice, this list of conditions and the following
 9  
  * disclaimer. 2) Redistributions in binary form must reproduce the above
 10  
  * copyright notice, this list of conditions and the following
 11  
  * disclaimer in the documentation and/or other materials provided
 12  
  * with the distribution. 3) Neither the name of the jcabi.com nor
 13  
  * the names of its contributors may be used to endorse or promote
 14  
  * products derived from this software without specific prior written
 15  
  * permission.
 16  
  *
 17  
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 18  
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT
 19  
  * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
 20  
  * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 21  
  * THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 22  
  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 23  
  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 24  
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 25  
  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 26  
  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 27  
  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 28  
  * OF THE POSSIBILITY OF SUCH DAMAGE.
 29  
  */
 30  
 package com.jcabi.immutable;
 31  
 
 32  
 import com.jcabi.aspects.Immutable;
 33  
 import com.jcabi.aspects.Loggable;
 34  
 import java.util.Arrays;
 35  
 import java.util.Collection;
 36  
 import java.util.Collections;
 37  
 import java.util.Comparator;
 38  
 import java.util.Iterator;
 39  
 import java.util.NoSuchElementException;
 40  
 import java.util.Set;
 41  
 import java.util.SortedSet;
 42  
 import java.util.TreeSet;
 43  
 
 44  
 /**
 45  
  * Sorted Set on top of array.
 46  
  *
 47  
  * <p>This class is truly immutable. This means that it never changes
 48  
  * its encapsulated values and is annotated with {@code &#64;Immutable}
 49  
  * annotation.
 50  
  *
 51  
  * @param <T> Value key type
 52  
  * @author Yegor Bugayenko (yegor@tpc2.com)
 53  
  * @version $Id$
 54  
  * @since 0.1
 55  
  */
 56  
 @Immutable
 57  
 @Loggable(Loggable.DEBUG)
 58  
 @SuppressWarnings({ "unchecked", "PMD.TooManyMethods" })
 59  
 public final class ArraySortedSet<T> implements SortedSet<T> {
 60  
 
 61  
     /**
 62  
      * All values.
 63  
      */
 64  
     @Immutable.Array
 65  
     private final transient T[] values;
 66  
 
 67  
     /**
 68  
      * Comparator to use.
 69  
      */
 70  
     private final transient ArrayComparator<T> cmp;
 71  
 
 72  
     /**
 73  
      * Public ctor.
 74  
      * @param comparator Comparator to use
 75  
      */
 76  
     public ArraySortedSet(final ArrayComparator<T> comparator) {
 77  3
         this(comparator, (T[]) new Object[0]);
 78  3
     }
 79  
 
 80  
     /**
 81  
      * Public ctor.
 82  
      * @param set Original set
 83  
      */
 84  
     public ArraySortedSet(final T... set) {
 85  0
         this(Arrays.asList(set));
 86  0
     }
 87  
 
 88  
     /**
 89  
      * Public ctor.
 90  
      * @param comparator The comparator to use
 91  
      * @param set Original set
 92  
      */
 93  
     public ArraySortedSet(final ArrayComparator<T> comparator,
 94  
         final T... set) {
 95  3
         this(Arrays.asList(set), comparator);
 96  3
     }
 97  
 
 98  
     /**
 99  
      * Public ctor, with default comparator.
 100  
      * @param set Original set
 101  
      * @since 0.12
 102  
      */
 103  
     public ArraySortedSet(final Iterable<T> set) {
 104  2
         this(set, new ArrayComparator.Default<T>());
 105  2
     }
 106  
 
 107  
     /**
 108  
      * Public ctor.
 109  
      * @param set Original set
 110  
      * @param comparator Comparator to use
 111  
      */
 112  
     public ArraySortedSet(final Iterable<T> set,
 113  19
         final ArrayComparator<T> comparator) {
 114  19
         if (set == null) {
 115  0
             throw new IllegalArgumentException(
 116  
                 "first argument of ArraySortedSet ctor can't be NULL"
 117  
             );
 118  
         }
 119  19
         if (comparator == null) {
 120  0
             throw new IllegalArgumentException(
 121  
                 "second argument of ArraySortedSet ctor can't be NULL"
 122  
             );
 123  
         }
 124  19
         this.cmp = comparator;
 125  19
         if (set instanceof ArraySortedSet) {
 126  1
             final ArraySortedSet<T> origin = (ArraySortedSet<T>) set;
 127  1
             if (origin.cmp.equals(this.cmp)) {
 128  0
                 this.values = origin.values;
 129  
             } else {
 130  1
                 final Set<T> hset = new TreeSet<T>(this.cmp);
 131  1
                 hset.addAll(Collection.class.cast(set));
 132  1
                 this.values = hset.toArray((T[]) new Object[hset.size()]);
 133  
             }
 134  1
         } else if (set instanceof Collection) {
 135  18
             final Set<T> hset = new TreeSet<T>(this.cmp);
 136  18
             hset.addAll(Collection.class.cast(set));
 137  18
             this.values = hset.toArray((T[]) new Object[hset.size()]);
 138  18
         } else {
 139  0
             final Set<T> hset = new TreeSet<T>(this.cmp);
 140  0
             for (final T item : set) {
 141  0
                 hset.add(item);
 142  0
             }
 143  0
             this.values = hset.toArray((T[]) new Object[hset.size()]);
 144  
         }
 145  19
     }
 146  
 
 147  
     /**
 148  
      * Make a new one with an extra entry.
 149  
      * @param value The value
 150  
      * @return New set
 151  
      */
 152  
     public ArraySortedSet<T> with(final T value) {
 153  8
         if (value == null) {
 154  0
             throw new IllegalArgumentException(
 155  
                 "argument of ArraySortedSet#with() can't be NULL"
 156  
             );
 157  
         }
 158  8
         final Collection<T> list = new TreeSet<T>(this.cmp);
 159  8
         list.addAll(this);
 160  8
         list.remove(value);
 161  8
         list.add(value);
 162  8
         return new ArraySortedSet<T>(list, this.cmp);
 163  
     }
 164  
 
 165  
     /**
 166  
      * Make a new one with some extra entries.
 167  
      * @param vals Values to add
 168  
      * @return New set
 169  
      */
 170  
     public ArraySortedSet<T> with(final Collection<T> vals) {
 171  0
         if (vals == null) {
 172  0
             throw new IllegalArgumentException(
 173  
                 "arguments of ArraySortedSet#with() can't be NULL"
 174  
             );
 175  
         }
 176  0
         final Collection<T> list = new TreeSet<T>(this.cmp);
 177  0
         list.addAll(this);
 178  0
         list.removeAll(vals);
 179  0
         list.addAll(vals);
 180  0
         return new ArraySortedSet<T>(list, this.cmp);
 181  
     }
 182  
 
 183  
     /**
 184  
      * Make a new one without an extra entry.
 185  
      * @param value The value
 186  
      * @return New set
 187  
      */
 188  
     public ArraySortedSet<T> without(final T value) {
 189  3
         if (value == null) {
 190  0
             throw new IllegalArgumentException(
 191  
                 "argument of ArraySortedSet#without() can't be NULL"
 192  
             );
 193  
         }
 194  3
         final Collection<T> list = new TreeSet<T>(this.cmp);
 195  3
         list.addAll(this);
 196  3
         list.remove(value);
 197  3
         return new ArraySortedSet<T>(list, this.cmp);
 198  
     }
 199  
 
 200  
     @Override
 201  
     public int hashCode() {
 202  0
         return Arrays.hashCode(this.values);
 203  
     }
 204  
 
 205  
     @Override
 206  
     public boolean equals(final Object object) {
 207  1
         return object instanceof ArraySortedSet
 208  
             && Arrays.deepEquals(
 209  
                 this.values, ArraySortedSet.class.cast(object).values
 210  
             );
 211  
     }
 212  
 
 213  
     @Override
 214  
     public String toString() {
 215  0
         final StringBuilder text = new StringBuilder(0);
 216  0
         for (final T item : this.values) {
 217  0
             if (text.length() > 0) {
 218  0
                 text.append(", ");
 219  
             }
 220  0
             text.append(item);
 221  
         }
 222  0
         return text.toString();
 223  
     }
 224  
 
 225  
     @Override
 226  
     public int size() {
 227  21
         return this.values.length;
 228  
     }
 229  
 
 230  
     @Override
 231  
     public boolean isEmpty() {
 232  0
         return this.values.length == 0;
 233  
     }
 234  
 
 235  
     @Override
 236  
     public boolean contains(final Object key) {
 237  0
         return Arrays.asList(this.values).contains(key);
 238  
     }
 239  
 
 240  
     @Override
 241  
     public Comparator<? super T> comparator() {
 242  9
         return this.cmp;
 243  
     }
 244  
 
 245  
     @Override
 246  
     public SortedSet<T> subSet(final T from, final T till) {
 247  0
         return Collections.unmodifiableSortedSet(
 248  
             new TreeSet<T>(this).subSet(from, till)
 249  
         );
 250  
     }
 251  
 
 252  
     @Override
 253  
     public SortedSet<T> headSet(final T till) {
 254  0
         return Collections.unmodifiableSortedSet(
 255  
             new TreeSet<T>(this)
 256  
         ).headSet(till);
 257  
     }
 258  
 
 259  
     @Override
 260  
     public SortedSet<T> tailSet(final T from) {
 261  0
         return Collections.unmodifiableSortedSet(
 262  
             new TreeSet<T>(this)
 263  
         ).tailSet(from);
 264  
     }
 265  
 
 266  
     @Override
 267  
     public T first() {
 268  1
         if (this.values.length == 0) {
 269  0
             throw new NoSuchElementException("sorted set is empty, no first()");
 270  
         }
 271  1
         return this.values[0];
 272  
     }
 273  
 
 274  
     @Override
 275  
     public T last() {
 276  1
         if (this.values.length == 0) {
 277  0
             throw new NoSuchElementException("sorted set is empty, not last()");
 278  
         }
 279  1
         return this.values[this.values.length - 1];
 280  
     }
 281  
 
 282  
     @Override
 283  
     public Iterator<T> iterator() {
 284  18
         return Collections.unmodifiableList(
 285  
             Arrays.asList(this.values)
 286  
         ).iterator();
 287  
     }
 288  
 
 289  
     @Override
 290  
     public Object[] toArray() {
 291  0
         final Object[] array = new Object[this.values.length];
 292  0
         System.arraycopy(this.values, 0, array, 0, this.values.length);
 293  0
         return array;
 294  
     }
 295  
 
 296  
     @Override
 297  
     public <T> T[] toArray(final T[] array) {
 298  
         T[] dest;
 299  0
         if (array.length == this.values.length) {
 300  0
             dest = array;
 301  
         } else {
 302  0
             dest = (T[]) new Object[this.values.length];
 303  
         }
 304  0
         System.arraycopy(this.values, 0, dest, 0, this.values.length);
 305  0
         return dest;
 306  
     }
 307  
 
 308  
     @Override
 309  
     public boolean add(final T element) {
 310  0
         throw new UnsupportedOperationException(
 311  
             "add(): ArraySortedSet is immutable"
 312  
         );
 313  
     }
 314  
 
 315  
     @Override
 316  
     public boolean remove(final Object obj) {
 317  0
         throw new UnsupportedOperationException(
 318  
             "remove(): ArraySortedSet is immutable"
 319  
         );
 320  
     }
 321  
 
 322  
     @Override
 323  
     public boolean containsAll(final Collection<?> col) {
 324  0
         return Arrays.asList(this.values).containsAll(col);
 325  
     }
 326  
 
 327  
     @Override
 328  
     public boolean addAll(final Collection<? extends T> col) {
 329  0
         throw new UnsupportedOperationException(
 330  
             "addAll(): ArraySortedSet is immutable"
 331  
         );
 332  
     }
 333  
 
 334  
     @Override
 335  
     public boolean retainAll(final Collection<?> col) {
 336  0
         throw new UnsupportedOperationException(
 337  
             "retainAll(): ArraySortedSet is immutable"
 338  
         );
 339  
     }
 340  
 
 341  
     @Override
 342  
     public boolean removeAll(final Collection<?> col) {
 343  0
         throw new UnsupportedOperationException(
 344  
             "removeAll(): ArraySortedSet is immutable"
 345  
         );
 346  
     }
 347  
 
 348  
     @Override
 349  
     public void clear() {
 350  0
         throw new UnsupportedOperationException(
 351  
             "clear(): ArraySortedSet is immutable"
 352  
         );
 353  
     }
 354  
 
 355  
 }