Cleanup: remove redundant casts
[yangtools.git] / common / util / src / main / java / org / opendaylight / yangtools / util / SingletonSet.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.yangtools.util;
9
10 import com.google.common.annotations.Beta;
11 import com.google.common.base.Preconditions;
12 import com.google.common.collect.Iterators;
13 import java.io.Serializable;
14 import java.util.Collection;
15 import java.util.Iterator;
16 import java.util.Set;
17 import javax.annotation.Nonnull;
18 import org.opendaylight.yangtools.concepts.Immutable;
19
20 /**
21  * A {@link Set} containing a single value. For some reason neither Java nor Guava provide direct access to the retained
22  * element -- which is desirable in some situations, as is the case in {@link SharedSingletonMap#entrySet()}.
23  */
24 @Beta
25 public abstract class SingletonSet<E> implements Set<E>, Immutable, Serializable {
26     private static final long serialVersionUID = 1L;
27
28     private static final SingletonSet<?> NULL_SINGLETON = new SingletonSet<Object>() {
29         private static final long serialVersionUID = 1L;
30
31         @Override
32         public boolean contains(final Object o) {
33             return o == null;
34         }
35
36         @Override
37         public int hashCode() {
38             return 0;
39         }
40
41         @Override
42         public Object getElement() {
43             return null;
44         }
45
46         @Override
47         public String toString() {
48             return "[null]";
49         }
50
51         private Object readResolve() {
52             return NULL_SINGLETON;
53         }
54     };
55
56     @SuppressWarnings("unchecked")
57     public static <E> SingletonSet<E> of(@Nonnull final E element) {
58         if (element == null) {
59             return (SingletonSet<E>) NULL_SINGLETON;
60         }
61         return new RegularSingletonSet<>(element);
62     }
63
64     public abstract E getElement();
65
66     @Override
67     public final int size() {
68         return 1;
69     }
70
71     @Override
72     public final boolean isEmpty() {
73         return false;
74     }
75
76     @Override
77     public final Iterator<E> iterator() {
78         return Iterators.singletonIterator(getElement());
79     }
80
81     @Override
82     public final Object[] toArray() {
83         return new Object[] { getElement() };
84     }
85
86     @SuppressWarnings("unchecked")
87     @Override
88     public final <T> T[] toArray(final T[] a) {
89         if (a.length > 0) {
90             a[0] = (T)getElement();
91             return a;
92         }
93
94         return (T[]) new Object[] {getElement()};
95     }
96
97     @Override
98     public final boolean add(final E e) {
99         throw new UnsupportedOperationException();
100     }
101
102     @Override
103     public final boolean remove(final Object o) {
104         throw new UnsupportedOperationException();
105     }
106
107     @Override
108     public final boolean containsAll(final Collection<?> c) {
109         if (c.isEmpty()) {
110             return true;
111         }
112         if (c.size() != 1) {
113             return false;
114         }
115
116         return otherContains(c);
117     }
118
119     @Override
120     public final boolean addAll(final Collection<? extends E> c) {
121         throw new UnsupportedOperationException();
122     }
123
124     @Override
125     public final boolean retainAll(final Collection<?> c) {
126         throw new UnsupportedOperationException();
127     }
128
129     @Override
130     public final boolean removeAll(final Collection<?> c) {
131         throw new UnsupportedOperationException();
132     }
133
134     @Override
135     public final void clear() {
136         throw new UnsupportedOperationException();
137     }
138
139     @Override
140     public abstract int hashCode();
141
142     @Override
143     public final boolean equals(final Object obj) {
144         if (obj == this) {
145             return true;
146         }
147         if (!(obj instanceof Set)) {
148             return false;
149         }
150
151         final Set<?> s = (Set<?>)obj;
152         return s.size() == 1 && otherContains(s);
153     }
154
155     private boolean otherContains(final Collection<?> other) {
156         try {
157             return other.contains(getElement());
158         } catch (ClassCastException | NullPointerException e) {
159             return false;
160         }
161     }
162
163     private static final class RegularSingletonSet<E> extends SingletonSet<E> {
164         private static final long serialVersionUID = 1L;
165         private final E element;
166
167         RegularSingletonSet(final E element) {
168             this.element = Preconditions.checkNotNull(element);
169         }
170
171         @Override
172         public boolean contains(final Object o) {
173             return element.equals(o);
174         }
175
176         @Override
177         public E getElement() {
178             return element;
179         }
180
181         @Override
182         public int hashCode() {
183             return getElement().hashCode();
184         }
185
186         @Override
187         public String toString() {
188             return "[" + element + ']';
189         }
190     }
191 }