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.io.IOException;
020 import java.io.ObjectInputStream;
021 import java.io.ObjectOutputStream;
022 import java.io.Serializable;
023 import java.util.Collection;
024 import java.util.Iterator;
025 import java.util.Map;
026 import java.util.Set;
027
028 import org.apache.commons.collections.BoundedMap;
029 import org.apache.commons.collections.collection.UnmodifiableCollection;
030 import org.apache.commons.collections.set.UnmodifiableSet;
031
032 /**
033 * Decorates another <code>Map</code> to fix the size, preventing add/remove.
034 * <p>
035 * Any action that would change the size of the map is disallowed.
036 * The put method is allowed to change the value associated with an existing
037 * key however.
038 * <p>
039 * If trying to remove or clear the map, an UnsupportedOperationException is
040 * thrown. If trying to put a new mapping into the map, an
041 * IllegalArgumentException is thrown. This is because the put method can
042 * succeed if the mapping's key already exists in the map, so the put method
043 * is not always unsupported.
044 * <p>
045 * <strong>Note that FixedSizeMap is not synchronized and is not thread-safe.</strong>
046 * If you wish to use this map from multiple threads concurrently, you must use
047 * appropriate synchronization. The simplest approach is to wrap this map
048 * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw
049 * exceptions when accessed by concurrent threads without synchronization.
050 * <p>
051 * This class is Serializable from Commons Collections 3.1.
052 *
053 * @since Commons Collections 3.0
054 * @version $Revision: 646777 $ $Date: 2008-04-10 13:33:15 +0100 (Thu, 10 Apr 2008) $
055 *
056 * @author Stephen Colebourne
057 * @author Paul Jack
058 */
059 public class FixedSizeMap
060 extends AbstractMapDecorator
061 implements Map, BoundedMap, Serializable {
062
063 /** Serialization version */
064 private static final long serialVersionUID = 7450927208116179316L;
065
066 /**
067 * Factory method to create a fixed size map.
068 *
069 * @param map the map to decorate, must not be null
070 * @throws IllegalArgumentException if map is null
071 */
072 public static Map decorate(Map map) {
073 return new FixedSizeMap(map);
074 }
075
076 //-----------------------------------------------------------------------
077 /**
078 * Constructor that wraps (not copies).
079 *
080 * @param map the map to decorate, must not be null
081 * @throws IllegalArgumentException if map is null
082 */
083 protected FixedSizeMap(Map map) {
084 super(map);
085 }
086
087 //-----------------------------------------------------------------------
088 /**
089 * Write the map out using a custom routine.
090 *
091 * @param out the output stream
092 * @throws IOException
093 * @since Commons Collections 3.1
094 */
095 private void writeObject(ObjectOutputStream out) throws IOException {
096 out.defaultWriteObject();
097 out.writeObject(map);
098 }
099
100 /**
101 * Read the map in using a custom routine.
102 *
103 * @param in the input stream
104 * @throws IOException
105 * @throws ClassNotFoundException
106 * @since Commons Collections 3.1
107 */
108 private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
109 in.defaultReadObject();
110 map = (Map) in.readObject();
111 }
112
113 //-----------------------------------------------------------------------
114 public Object put(Object key, Object value) {
115 if (map.containsKey(key) == false) {
116 throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
117 }
118 return map.put(key, value);
119 }
120
121 public void putAll(Map mapToCopy) {
122 for (Iterator it = mapToCopy.keySet().iterator(); it.hasNext(); ) {
123 if (mapToCopy.containsKey(it.next()) == false) {
124 throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
125 }
126 }
127 map.putAll(mapToCopy);
128 }
129
130 public void clear() {
131 throw new UnsupportedOperationException("Map is fixed size");
132 }
133
134 public Object remove(Object key) {
135 throw new UnsupportedOperationException("Map is fixed size");
136 }
137
138 public Set entrySet() {
139 Set set = map.entrySet();
140 // unmodifiable set will still allow modification via Map.Entry objects
141 return UnmodifiableSet.decorate(set);
142 }
143
144 public Set keySet() {
145 Set set = map.keySet();
146 return UnmodifiableSet.decorate(set);
147 }
148
149 public Collection values() {
150 Collection coll = map.values();
151 return UnmodifiableCollection.decorate(coll);
152 }
153
154 public boolean isFull() {
155 return true;
156 }
157
158 public int maxSize() {
159 return size();
160 }
161
162 }