001    /*
002     * Licensed under the Apache License, Version 2.0 (the "License");
003     * you may not use this file except in compliance with the License.
004     * You may obtain a copy of the License at
005     *
006     *      http://www.apache.org/licenses/LICENSE-2.0
007     *
008     * Unless required by applicable law or agreed to in writing, software
009     * distributed under the License is distributed on an "AS IS" BASIS,
010     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011     * See the License for the specific language governing permissions and
012     * limitations under the License.
013     */
014    package org.apache.commons.classscan.util;
015    
016    import java.lang.reflect.Array;
017    import java.util.Arrays;
018    import java.util.Collection;
019    import java.util.Iterator;
020    import java.util.NoSuchElementException;
021    import java.util.Set;
022    
023    /**
024     * Set of immutable instances.
025     * 
026     * @param <V>
027     *            The contained type
028     */
029    public class ReadOnlySet<V> implements Set<V> {
030        
031        protected V[] values;
032    
033        public ReadOnlySet(V[] values) {
034            if(values==null) {
035                throw new UnsupportedOperationException();
036            }
037            else {
038                this.values = values;
039            }
040        }
041    
042        /**
043         * Subclasses may use this constructor to delay initialization of values.
044         * The derived class must call setValues before general use.
045         */
046        protected ReadOnlySet() {
047        }
048    
049        /**
050         * @param values
051         *            The array to view
052         */
053        protected void setValues(V[] values) {
054            this.values = values;
055        }
056    
057        @Override
058        public boolean contains(Object o) {
059            for (V t : values) {
060                if (t.equals(o)) {
061                    return true;
062                }
063            }
064            return false;
065        }
066    
067        @Override
068        public boolean containsAll(Collection<?> collection) {
069            for (Object single : collection) {
070                if (!contains(single)) {
071                    return false;
072                }
073            }
074            return true;
075        }
076    
077        @Override
078        public boolean isEmpty() {
079            return values.length == 0;
080        }
081    
082        @Override
083        public Iterator<V> iterator() {
084            return new Iterator<V>() {
085                int i;
086    
087                @Override
088                public boolean hasNext() {
089                    return i < values.length;
090                }
091    
092                @Override
093                public V next() {
094                    if (i == values.length) {
095                        throw new NoSuchElementException("Reading past end of iterator");
096                    }
097                    return values[i++];
098                }
099    
100                @Override
101                public void remove() {
102                    throw new UnsupportedOperationException("Read only iterator");
103                }
104            };
105        }
106    
107        @Override
108        public int size() {
109            return values.length;
110        }
111    
112        @Override
113        public Object[] toArray() {
114            return values.clone();
115        }
116    
117        @Override
118        public <T> T[] toArray(T[] a) {
119            int numberToNull = a.length - values.length;
120            if (numberToNull >= 0) {
121                System.arraycopy(values, 0, a, 0, values.length);
122                if (numberToNull > 0) {
123                    Arrays.fill(a, values.length, a.length, null);
124                }
125                return a;
126            }
127    
128            @SuppressWarnings("unchecked")
129            T[] rv = (T[]) Array.newInstance(a.getClass().getComponentType(), values.length);
130            System.arraycopy(values, 0, rv, 0, values.length);
131            return rv;
132        }
133    
134        @Override
135        final public boolean add(V e) {
136            throw new UnsupportedOperationException("Set is readonly");
137        }
138    
139        @Override
140        final public boolean addAll(Collection<? extends V> c) {
141            throw new UnsupportedOperationException("Set is readonly");
142        }
143    
144        @Override
145        final public void clear() {
146            throw new UnsupportedOperationException("Set is readonly");
147        }
148    
149        @Override
150        final public boolean remove(Object e) {
151            throw new UnsupportedOperationException("Set is readonly");
152        }
153    
154        @Override
155        final public boolean removeAll(Collection<?> c) {
156            throw new UnsupportedOperationException("Set is readonly");
157        }
158    
159        @Override
160        final public boolean retainAll(Collection<?> c) {
161            throw new UnsupportedOperationException("Set is readonly");
162        }
163    
164    }