KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > collections > map > AbstractInputCheckedMapDecorator


1 /*
2  * Copyright 2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.commons.collections.map;
17
18 import java.lang.reflect.Array JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Map JavaDoc;
21 import java.util.Set JavaDoc;
22
23 import org.apache.commons.collections.iterators.AbstractIteratorDecorator;
24 import org.apache.commons.collections.keyvalue.AbstractMapEntryDecorator;
25 import org.apache.commons.collections.set.AbstractSetDecorator;
26
27 /**
28  * An abstract base class that simplifies the task of creating map decorators.
29  * <p>
30  * The Map API is very difficult to decorate correctly, and involves implementing
31  * lots of different classes. This class exists to provide a simpler API.
32  * <p>
33  * Special hook methods are provided that are called when objects are added to
34  * the map. By overriding these methods, the input can be validated or manipulated.
35  * In addition to the main map methods, the entrySet is also affected, which is
36  * the hardest part of writing map implementations.
37  * <p>
38  * This class is package-scoped, and may be withdrawn or replaced in future
39  * versions of Commons Collections.
40  *
41  * @since Commons Collections 3.1
42  * @version $Revision: 1.2 $ $Date: 2004/05/21 22:01:04 $
43  *
44  * @author Stephen Colebourne
45  */

46 abstract class AbstractInputCheckedMapDecorator
47         extends AbstractMapDecorator {
48
49     /**
50      * Constructor only used in deserialization, do not use otherwise.
51      */

52     protected AbstractInputCheckedMapDecorator() {
53         super();
54     }
55
56     /**
57      * Constructor that wraps (not copies).
58      *
59      * @param map the map to decorate, must not be null
60      * @throws IllegalArgumentException if map is null
61      */

62     protected AbstractInputCheckedMapDecorator(Map JavaDoc map) {
63         super(map);
64     }
65
66     //-----------------------------------------------------------------------
67
/**
68      * Hook method called when a value is being set using <code>setValue</code>.
69      * <p>
70      * An implementation may validate the value and throw an exception
71      * or it may transform the value into another object.
72      * <p>
73      * This implementation returns the input value.
74      *
75      * @param value the value to check
76      * @throws UnsupportedOperationException if the map may not be changed by setValue
77      * @throws IllegalArgumentException if the specified value is invalid
78      * @throws ClassCastException if the class of the specified value is invalid
79      * @throws NullPointerException if the specified value is null and nulls are invalid
80      */

81     protected abstract Object JavaDoc checkSetValue(Object JavaDoc value);
82
83     /**
84      * Hook method called to determine if <code>checkSetValue</code> has any effect.
85      * <p>
86      * An implementation should return false if the <code>checkSetValue</code> method
87      * has no effect as this optimises the implementation.
88      * <p>
89      * This implementation returns <code>true</code>.
90      *
91      * @param value the value to check
92      */

93     protected boolean isSetValueChecking() {
94         return true;
95     }
96
97     //-----------------------------------------------------------------------
98
public Set JavaDoc entrySet() {
99         if (isSetValueChecking()) {
100             return new EntrySet(map.entrySet(), this);
101         } else {
102             return map.entrySet();
103         }
104     }
105
106     //-----------------------------------------------------------------------
107
/**
108      * Implementation of an entry set that checks additions via setValue.
109      */

110     static class EntrySet extends AbstractSetDecorator {
111         
112         /** The parent map */
113         private final AbstractInputCheckedMapDecorator parent;
114
115         protected EntrySet(Set JavaDoc set, AbstractInputCheckedMapDecorator parent) {
116             super(set);
117             this.parent = parent;
118         }
119
120         public Iterator JavaDoc iterator() {
121             return new EntrySetIterator(collection.iterator(), parent);
122         }
123         
124         public Object JavaDoc[] toArray() {
125             Object JavaDoc[] array = collection.toArray();
126             for (int i = 0; i < array.length; i++) {
127                 array[i] = new MapEntry((Map.Entry JavaDoc) array[i], parent);
128             }
129             return array;
130         }
131         
132         public Object JavaDoc[] toArray(Object JavaDoc array[]) {
133             Object JavaDoc[] result = array;
134             if (array.length > 0) {
135                 // we must create a new array to handle multi-threaded situations
136
// where another thread could access data before we decorate it
137
result = (Object JavaDoc[]) Array.newInstance(array.getClass().getComponentType(), 0);
138             }
139             result = collection.toArray(result);
140             for (int i = 0; i < result.length; i++) {
141                 result[i] = new MapEntry((Map.Entry JavaDoc) result[i], parent);
142             }
143
144             // check to see if result should be returned straight
145
if (result.length > array.length) {
146                 return result;
147             }
148
149             // copy back into input array to fulfil the method contract
150
System.arraycopy(result, 0, array, 0, result.length);
151             if (array.length > result.length) {
152                 array[result.length] = null;
153             }
154             return array;
155         }
156     }
157
158     /**
159      * Implementation of an entry set iterator that checks additions via setValue.
160      */

161     static class EntrySetIterator extends AbstractIteratorDecorator {
162         
163         /** The parent map */
164         private final AbstractInputCheckedMapDecorator parent;
165         
166         protected EntrySetIterator(Iterator JavaDoc iterator, AbstractInputCheckedMapDecorator parent) {
167             super(iterator);
168             this.parent = parent;
169         }
170         
171         public Object JavaDoc next() {
172             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
173             return new MapEntry(entry, parent);
174         }
175     }
176
177     /**
178      * Implementation of a map entry that checks additions via setValue.
179      */

180     static class MapEntry extends AbstractMapEntryDecorator {
181
182         /** The parent map */
183         private final AbstractInputCheckedMapDecorator parent;
184
185         protected MapEntry(Map.Entry JavaDoc entry, AbstractInputCheckedMapDecorator parent) {
186             super(entry);
187             this.parent = parent;
188         }
189
190         public Object JavaDoc setValue(Object JavaDoc value) {
191             value = parent.checkSetValue(value);
192             return entry.setValue(value);
193         }
194     }
195
196 }
197
Popular Tags