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 }