001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.commons.collections.map;
018    
019    import java.lang.reflect.Array;
020    import java.util.Collection;
021    import java.util.Iterator;
022    import java.util.Map;
023    import java.util.Set;
024    
025    import org.apache.commons.collections.Unmodifiable;
026    import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
027    import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
028    import org.apache.commons.collections.set.AbstractSetDecorator;
029    
030    /**
031     * Decorates a map entry <code>Set</code> to ensure it can't be altered.
032     *
033     * @since Commons Collections 3.0
034     * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
035     * 
036     * @author Stephen Colebourne
037     */
038    public final class UnmodifiableEntrySet
039            extends AbstractSetDecorator implements Unmodifiable {
040    
041        /**
042         * Factory method to create an unmodifiable set of Map Entry objects.
043         * 
044         * @param set  the set to decorate, must not be null
045         * @throws IllegalArgumentException if set is null
046         */
047        public static Set decorate(Set set) {
048            if (set instanceof Unmodifiable) {
049                return set;
050            }
051            return new UnmodifiableEntrySet(set);
052        }
053    
054        //-----------------------------------------------------------------------
055        /**
056         * Constructor that wraps (not copies).
057         * 
058         * @param set  the set to decorate, must not be null
059         * @throws IllegalArgumentException if set is null
060         */
061        private UnmodifiableEntrySet(Set set) {
062            super(set);
063        }
064    
065        //-----------------------------------------------------------------------
066        public boolean add(Object object) {
067            throw new UnsupportedOperationException();
068        }
069    
070        public boolean addAll(Collection coll) {
071            throw new UnsupportedOperationException();
072        }
073    
074        public void clear() {
075            throw new UnsupportedOperationException();
076        }
077    
078        public boolean remove(Object object) {
079            throw new UnsupportedOperationException();
080        }
081    
082        public boolean removeAll(Collection coll) {
083            throw new UnsupportedOperationException();
084        }
085    
086        public boolean retainAll(Collection coll) {
087            throw new UnsupportedOperationException();
088        }
089    
090        //-----------------------------------------------------------------------
091        public Iterator iterator() {
092            return new UnmodifiableEntrySetIterator(collection.iterator());
093        }
094        
095        public Object[] toArray() {
096            Object[] array = collection.toArray();
097            for (int i = 0; i < array.length; i++) {
098                array[i] = new UnmodifiableEntry((Map.Entry) array[i]);
099            }
100            return array;
101        }
102        
103        public Object[] toArray(Object array[]) {
104            Object[] result = array;
105            if (array.length > 0) {
106                // we must create a new array to handle multi-threaded situations
107                // where another thread could access data before we decorate it
108                result = (Object[]) Array.newInstance(array.getClass().getComponentType(), 0);
109            }
110            result = collection.toArray(result);
111            for (int i = 0; i < result.length; i++) {
112                result[i] = new UnmodifiableEntry((Map.Entry) result[i]);
113            }
114    
115            // check to see if result should be returned straight
116            if (result.length > array.length) {
117                return result;
118            }
119    
120            // copy back into input array to fulfil the method contract
121            System.arraycopy(result, 0, array, 0, result.length);
122            if (array.length > result.length) {
123                array[result.length] = null;
124            }
125            return array;
126        }
127        
128        //-----------------------------------------------------------------------
129        /**
130         * Implementation of an entry set iterator.
131         */
132        final static class UnmodifiableEntrySetIterator extends AbstractIteratorDecorator {
133            
134            protected UnmodifiableEntrySetIterator(Iterator iterator) {
135                super(iterator);
136            }
137            
138            public Object next() {
139                Map.Entry entry = (Map.Entry) iterator.next();
140                return new UnmodifiableEntry(entry);
141            }
142            
143            public void remove() {
144                throw new UnsupportedOperationException();
145            }
146        }
147    
148        //-----------------------------------------------------------------------
149        /**
150         * Implementation of a map entry that is unmodifiable.
151         */
152        final static class UnmodifiableEntry extends AbstractMapEntryDecorator {
153    
154            protected UnmodifiableEntry(Map.Entry entry) {
155                super(entry);
156            }
157    
158            public Object setValue(Object obj) {
159                throw new UnsupportedOperationException();
160            }
161        }
162    
163    }