]> source.dussan.org Git - vaadin-framework.git/blob
89596a1aa4a64216933d80399d871cf01996be1c
[vaadin-framework.git] /
1 /*
2  * Copyright 2000-2018 Vaadin Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 package com.vaadin.v7.data.util.converter;
17
18 import java.io.Serializable;
19 import java.lang.reflect.Modifier;
20 import java.util.ArrayList;
21 import java.util.Collection;
22 import java.util.HashSet;
23 import java.util.Locale;
24
25 /**
26  * A converter that converts from {@link String} to {@link Collection} of tokens
27  * and back.
28  * <p>
29  * Allows to break a string into tokens using delimiter. Each token can be
30  * converted to its own model using provided converter.
31  * <p>
32  * Default constructor uses <code>", "</code> as delimiter string and
33  * {@link String} for token types. Other constructors allow to configure
34  * delimiter and token types.
35  *
36  * @since 7.5.0
37  *
38  * @author Vaadin Ltd
39  *
40  * @deprecated As of 8.0, a lightweight lambda-based converter can be build with
41  *             {@link com.vaadin.data.Binder
42  *             Binder}{@code .forField(...).withConverter(...)} methods.
43  */
44 @Deprecated
45 public class StringToCollectionConverter
46         implements Converter<String, Collection> {
47
48     private final String delimiter;
49     private final Converter<String, ?> tokenConverter;
50     private final Class<?> tokenType;
51     private final CollectionFactory factory;
52
53     /**
54      * Creates converter with <code>", "</code> as delimiter and {@link String}
55      * as token model type in collection.
56      */
57     public StringToCollectionConverter() {
58         this(", ", null, String.class);
59     }
60
61     /**
62      * Creates converter with given {@code delimiter} and {@link String} as
63      * token model type in collection.
64      *
65      * @param delimiter
66      *            custom delimiter
67      */
68     public StringToCollectionConverter(String delimiter) {
69         this(delimiter, null, String.class);
70     }
71
72     /**
73      * Creates converter with given {@code tokenConverter} for convert tokens
74      * and expected {@code tokenType}.
75      * <p>
76      * If {@code tokenConverter} is null then no conversation is done and
77      * {@link String} is used as token type in resulting model collection.
78      *
79      * @param tokenConverter
80      *            converter for token
81      * @param tokenType
82      *            expected token model type
83      */
84     public StringToCollectionConverter(Converter<String, ?> tokenConverter,
85             Class<?> tokenType) {
86         this(", ", tokenConverter, tokenType);
87     }
88
89     /**
90      * Creates converter with given {@code tokenConverter} for convert tokens
91      * and expected {@code tokenType}.
92      * <p>
93      * If {@code tokenConverter} is null then no conversation is done and
94      * {@link String} is used as token type in resulting model collection.
95      *
96      * @param tokenConverter
97      *            converter for token
98      * @param tokenClass
99      *            expected token model type
100      * @param delimiter
101      *            delimiter in presentation string
102      */
103     public StringToCollectionConverter(String delimiter,
104             Converter<String, ?> tokenConverter, Class<?> tokenClass) {
105         this(delimiter, tokenConverter, tokenClass,
106                 new DefaultCollectionFactory());
107     }
108
109     /**
110      * Creates converter with given {@code tokenConverter} for convert tokens
111      * and expected {@code tokenType}.
112      * <p>
113      * If {@code tokenConverter} is null then no conversation is done and
114      * {@link String} is used as token type in resulting model collection.
115      *
116      * @param tokenConverter
117      *            converter for token
118      * @param tokenClass
119      *            expected token model type
120      * @param delimiter
121      *            delimiter in presentation string
122      * @param factory
123      *            factory to create resulting collection
124      */
125     public StringToCollectionConverter(String delimiter,
126             Converter<String, ?> tokenConverter, Class<?> tokenClass,
127             CollectionFactory factory) {
128         if (delimiter == null || delimiter.isEmpty()) {
129             throw new IllegalArgumentException(
130                     "Delimiter should be non-empty string");
131         }
132         this.delimiter = delimiter;
133         this.tokenConverter = tokenConverter;
134         tokenType = tokenClass;
135         this.factory = factory;
136     }
137
138     @Override
139     public Class<Collection> getModelType() {
140         return Collection.class;
141     }
142
143     @Override
144     public Class<String> getPresentationType() {
145         return String.class;
146     }
147
148     @Override
149     public Collection convertToModel(String value,
150             Class<? extends Collection> targetType, Locale locale)
151             throws Converter.ConversionException {
152         if (value == null) {
153             return null;
154         }
155
156         int index = value.indexOf(delimiter);
157         int previous = 0;
158         Collection result = factory.createCollection(targetType);
159         Converter converter = tokenConverter;
160         while (index != -1) {
161             collectToken(value.substring(previous, index), result, converter,
162                     locale);
163             previous = index + delimiter.length();
164             index = value.indexOf(delimiter, previous);
165         }
166         collectToken(value.substring(previous), result, converter, locale);
167         return result;
168     }
169
170     @Override
171     public String convertToPresentation(Collection value,
172             Class<? extends String> targetType, Locale locale)
173             throws Converter.ConversionException {
174         if (value == null) {
175             return null;
176         }
177         StringBuilder builder = new StringBuilder();
178         Converter converter = tokenConverter;
179         for (Object o : value) {
180             if (converter == null) {
181                 builder.append(o);
182             } else {
183                 builder.append(
184                         converter.convertToPresentation(o, targetType, locale));
185             }
186             builder.append(delimiter);
187         }
188         if (builder.length() != 0) {
189             return builder.substring(0, builder.length() - delimiter.length());
190         } else {
191             return builder.toString();
192         }
193     }
194
195     private void collectToken(String token, Collection collection,
196             Converter converter, Locale locale) {
197         if (converter == null) {
198             collection.add(token);
199         } else {
200             collection.add(converter.convertToModel(token, tokenType, locale));
201         }
202     }
203
204     /**
205      * Default collection factory implementation.
206      *
207      * @author Vaadin Ltd
208      */
209     @Deprecated
210     public static class DefaultCollectionFactory implements CollectionFactory {
211
212         @Override
213         public Collection<?> createCollection(
214                 Class<? extends Collection> type) {
215             if (type.isAssignableFrom(ArrayList.class)) {
216                 return new ArrayList<Object>();
217             } else if (type.isAssignableFrom(HashSet.class)) {
218                 return new HashSet<Object>();
219             } else if (!type.isInterface()
220                     && !Modifier.isAbstract(type.getModifiers())) {
221                 try {
222                     return type.newInstance();
223                 } catch (InstantiationException ignore) {
224                 } catch (IllegalAccessException ignore) {
225                 }
226             }
227             return new ArrayList<Object>();
228         }
229
230     }
231
232     /**
233      * Collection factory. Defines a strategy to create collection by collection
234      * class.
235      *
236      * @author Vaadin Ltd
237      */
238     @Deprecated
239     public interface CollectionFactory extends Serializable {
240
241         /**
242          * Create collection by its {@code type}.
243          *
244          * @param type
245          *            collection type
246          * @return instantiated collection with given {@code type}
247          */
248         Collection<?> createCollection(Class<? extends Collection> type);
249     }
250 }