View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.collections.map;
18  
19  import java.io.IOException;
20  import java.io.ObjectInputStream;
21  import java.io.ObjectOutputStream;
22  import java.io.Serializable;
23  import java.util.Collection;
24  import java.util.Map;
25  import java.util.Set;
26  
27  import org.apache.commons.collections.BoundedMap;
28  import org.apache.commons.collections.collection.UnmodifiableCollection;
29  import org.apache.commons.collections.set.UnmodifiableSet;
30  
31  /**
32   * Decorates another <code>Map</code> to fix the size, preventing add/remove.
33   * <p>
34   * Any action that would change the size of the map is disallowed.
35   * The put method is allowed to change the value associated with an existing
36   * key however.
37   * <p>
38   * If trying to remove or clear the map, an UnsupportedOperationException is
39   * thrown. If trying to put a new mapping into the map, an 
40   * IllegalArgumentException is thrown. This is because the put method can 
41   * succeed if the mapping's key already exists in the map, so the put method
42   * is not always unsupported.
43   * <p>
44   * <strong>Note that FixedSizeMap is not synchronized and is not thread-safe.</strong>
45   * If you wish to use this map from multiple threads concurrently, you must use
46   * appropriate synchronization. The simplest approach is to wrap this map
47   * using {@link java.util.Collections#synchronizedMap(Map)}. This class may throw 
48   * exceptions when accessed by concurrent threads without synchronization.
49   * <p>
50   * This class is Serializable from Commons Collections 3.1.
51   *
52   * @since 3.0
53   * @version $Id: FixedSizeMap.java 1429905 2013-01-07 17:15:14Z ggregory $
54   */
55  public class FixedSizeMap<K, V>
56          extends AbstractMapDecorator<K, V>
57          implements Map<K, V>, BoundedMap<K, V>, Serializable {
58  
59      /** Serialization version */
60      private static final long serialVersionUID = 7450927208116179316L;
61  
62      /**
63       * Factory method to create a fixed size map.
64       * 
65       * @param <K>  the key type
66       * @param <V>  the value type
67       * @param map  the map to decorate, must not be null
68       * @return a new fixed size map
69       * @throws IllegalArgumentException if map is null
70       */
71      public static <K, V> FixedSizeMap<K, V> fixedSizeMap(final Map<K, V> map) {
72          return new FixedSizeMap<K, V>(map);
73      }
74  
75      //-----------------------------------------------------------------------
76      /**
77       * Constructor that wraps (not copies).
78       * 
79       * @param map  the map to decorate, must not be null
80       * @throws IllegalArgumentException if map is null
81       */
82      protected FixedSizeMap(final Map<K, V> map) {
83          super(map);
84      }
85  
86      //-----------------------------------------------------------------------
87      /**
88       * Write the map out using a custom routine.
89       * 
90       * @param out  the output stream
91       * @throws IOException
92       * @since 3.1
93       */
94      private void writeObject(final ObjectOutputStream out) throws IOException {
95          out.defaultWriteObject();
96          out.writeObject(map);
97      }
98  
99      /**
100      * Read the map in using a custom routine.
101      * 
102      * @param in  the input stream
103      * @throws IOException
104      * @throws ClassNotFoundException
105      * @since 3.1
106      */
107     @SuppressWarnings("unchecked") // (1) should only fail if input stream is incorrect 
108     private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
109         in.defaultReadObject();
110         map = (Map<K, V>) in.readObject(); // (1)
111     }
112 
113     //-----------------------------------------------------------------------
114     @Override
115     public V put(final K key, final V value) {
116         if (map.containsKey(key) == false) {
117             throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
118         }
119         return map.put(key, value);
120     }
121 
122     @Override
123     public void putAll(final Map<? extends K, ? extends V> mapToCopy) {
124         for (final K key : mapToCopy.keySet()) {
125             if (!containsKey(key)) {
126                 throw new IllegalArgumentException("Cannot put new key/value pair - Map is fixed size");
127             }
128         }
129         map.putAll(mapToCopy);
130     }
131 
132     @Override
133     public void clear() {
134         throw new UnsupportedOperationException("Map is fixed size");
135     }
136 
137     @Override
138     public V remove(final Object key) {
139         throw new UnsupportedOperationException("Map is fixed size");
140     }
141 
142     @Override
143     public Set<Map.Entry<K, V>> entrySet() {
144         final Set<Map.Entry<K, V>> set = map.entrySet();
145         // unmodifiable set will still allow modification via Map.Entry objects
146         return UnmodifiableSet.unmodifiableSet(set);
147     }
148 
149     @Override
150     public Set<K> keySet() {
151         final Set<K> set = map.keySet();
152         return UnmodifiableSet.unmodifiableSet(set);
153     }
154 
155     @Override
156     public Collection<V> values() {
157         final Collection<V> coll = map.values();
158         return UnmodifiableCollection.unmodifiableCollection(coll);
159     }
160 
161     public boolean isFull() {
162         return true;
163     }
164 
165     public int maxSize() {
166         return size();
167     }
168 
169 }