KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > beans > propertyeditors > CustomCollectionEditor


1 /*
2  * Copyright 2002-2006 the original author or authors.
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
17 package org.springframework.beans.propertyeditors;
18
19 import java.beans.PropertyEditorSupport JavaDoc;
20 import java.lang.reflect.Array JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.SortedSet JavaDoc;
26 import java.util.TreeSet JavaDoc;
27
28 import org.springframework.core.CollectionFactory;
29
30 /**
31  * Property editor for Collections, converting any source Collection
32  * to a given target Collection type.
33  *
34  * <p>By default registered for Set, SortedSet and List,
35  * to automatically convert any given Collection to one of those
36  * target types if the type does not match the target property.
37  *
38  * @author Juergen Hoeller
39  * @since 1.1.3
40  * @see java.util.Collection
41  * @see java.util.Set
42  * @see java.util.SortedSet
43  * @see java.util.List
44  */

45 public class CustomCollectionEditor extends PropertyEditorSupport JavaDoc {
46
47     private final Class JavaDoc collectionType;
48
49     private final boolean nullAsEmptyCollection;
50
51
52     /**
53      * Create a new CustomCollectionEditor for the given target type,
54      * keeping an incoming <code>null</code> as-is.
55      * @param collectionType the target type, which needs to be a
56      * sub-interface of Collection or a concrete Collection class
57      * @see java.util.Collection
58      * @see java.util.ArrayList
59      * @see java.util.TreeSet
60      * @see org.springframework.core.CollectionFactory#createLinkedSetIfPossible
61      */

62     public CustomCollectionEditor(Class JavaDoc collectionType) {
63         this(collectionType, false);
64     }
65
66     /**
67      * Create a new CustomCollectionEditor for the given target type.
68      * <p>If the incoming value is of the given type, it will be used as-is.
69      * If it is a different Collection type or an array, it will be converted
70      * to a default implementation of the given Collection type.
71      * If the value is anything else, a target Collection with that single
72      * value will be created.
73      * <p>The default Collection implementations are: ArrayList for List,
74      * TreeSet for SortedSet, and LinkedHashSet or HashSet for Set.
75      * @param collectionType the target type, which needs to be a
76      * sub-interface of Collection or a concrete Collection class
77      * @param nullAsEmptyCollection whether to convert an incoming <code>null</code>
78      * value to an empty Collection (of the appropriate type)
79      * @see java.util.Collection
80      * @see java.util.ArrayList
81      * @see java.util.TreeSet
82      * @see org.springframework.core.CollectionFactory#createLinkedSetIfPossible
83      */

84     public CustomCollectionEditor(Class JavaDoc collectionType, boolean nullAsEmptyCollection) {
85         if (collectionType == null) {
86             throw new IllegalArgumentException JavaDoc("Collection type is required");
87         }
88         if (!Collection JavaDoc.class.isAssignableFrom(collectionType)) {
89             throw new IllegalArgumentException JavaDoc(
90                     "Collection type [" + collectionType.getName() + "] does not implement [java.util.Collection]");
91         }
92         this.collectionType = collectionType;
93         this.nullAsEmptyCollection = nullAsEmptyCollection;
94     }
95
96
97     /**
98      * Convert the given text value to a Collection with a single element.
99      */

100     public void setAsText(String JavaDoc text) throws IllegalArgumentException JavaDoc {
101         setValue(text);
102     }
103
104     /**
105      * Convert the given value to a Collection of the target type.
106      */

107     public void setValue(Object JavaDoc value) {
108         if (value == null && this.nullAsEmptyCollection) {
109             super.setValue(createCollection(this.collectionType, 0));
110         }
111         else if (value == null || (this.collectionType.isInstance(value) && !alwaysCreateNewCollection())) {
112             // Use the source value as-is, as it matches the target type.
113
super.setValue(value);
114         }
115         else if (value instanceof Collection JavaDoc) {
116             // Convert Collection elements.
117
Collection JavaDoc source = (Collection JavaDoc) value;
118             Collection JavaDoc target = createCollection(this.collectionType, source.size());
119             for (Iterator JavaDoc it = source.iterator(); it.hasNext();) {
120                 target.add(convertElement(it.next()));
121             }
122             super.setValue(target);
123         }
124         else if (value.getClass().isArray()) {
125             // Convert array elements to Collection elements.
126
int length = Array.getLength(value);
127             Collection JavaDoc target = createCollection(this.collectionType, length);
128             for (int i = 0; i < length; i++) {
129                 target.add(convertElement(Array.get(value, i)));
130             }
131             super.setValue(target);
132         }
133         else {
134             // A plain value: convert it to a Collection with a single element.
135
Collection JavaDoc target = createCollection(this.collectionType, 1);
136             target.add(convertElement(value));
137             super.setValue(target);
138         }
139     }
140
141     /**
142      * Create a Collection of the given type, with the given
143      * initial capacity (if supported by the Collection type).
144      * @param collectionType a sub-interface of Collection
145      * @param initialCapacity the initial capacity
146      * @return the new Collection instance
147      */

148     protected Collection JavaDoc createCollection(Class JavaDoc collectionType, int initialCapacity) {
149         if (!collectionType.isInterface()) {
150             try {
151                 return (Collection JavaDoc) collectionType.newInstance();
152             }
153             catch (Exception JavaDoc ex) {
154                 throw new IllegalArgumentException JavaDoc(
155                         "Could not instantiate collection class [" + collectionType.getName() + "]: " + ex.getMessage());
156             }
157         }
158         else if (List JavaDoc.class.equals(collectionType)) {
159             return new ArrayList JavaDoc(initialCapacity);
160         }
161         else if (SortedSet JavaDoc.class.equals(collectionType)) {
162             return new TreeSet JavaDoc();
163         }
164         else {
165             return CollectionFactory.createLinkedSetIfPossible(initialCapacity);
166         }
167     }
168
169     /**
170      * Return whether to always create a new Collection,
171      * even if the type of the passed-in Collection already matches.
172      * <p>Default is "false"; can be overridden to enforce creation of a
173      * new Collection, for example to convert elements in any case.
174      * @see #convertElement
175      */

176     protected boolean alwaysCreateNewCollection() {
177         return false;
178     }
179
180     /**
181      * Hook to convert each encountered Collection/array element.
182      * The default implementation simply returns the passed-in element as-is.
183      * <p>Can be overridden to perform conversion of certain elements,
184      * for example String to Integer if a String array comes in and
185      * should be converted to a Set of Integer objects.
186      * <p>Only called if actually creating a new Collection!
187      * This is by default not the case if the type of the passed-in Collection
188      * already matches. Override {@link #alwaysCreateNewCollection()} to
189      * enforce creating a new Collection in every case.
190      * @param element the source element
191      * @return the element to be used in the target Collection
192      * @see #alwaysCreateNewCollection()
193      */

194     protected Object JavaDoc convertElement(Object JavaDoc element) {
195         return element;
196     }
197
198
199     /**
200      * This implementation returns <code>null</code> to indicate that
201      * there is no appropriate text representation.
202      */

203     public String JavaDoc getAsText() {
204         return null;
205     }
206
207 }
208
Popular Tags