Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

StringToCollectionConverter.java 8.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /*
  2. * Copyright 2000-2016 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. import com.vaadin.data.Binder;
  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.Iterator;
  24. import java.util.Locale;
  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 Binder}{@code .forField(...).withConverter(...)} methods.
  42. */
  43. @Deprecated
  44. public class StringToCollectionConverter
  45. implements Converter<String, Collection> {
  46. private final String delimiter;
  47. private final Converter<String, ?> tokenConverter;
  48. private final Class<?> tokenType;
  49. private final CollectionFactory factory;
  50. /**
  51. * Creates converter with <code>", "</code> as delimiter and {@link String}
  52. * as token model type in collection.
  53. */
  54. public StringToCollectionConverter() {
  55. this(", ", null, String.class);
  56. }
  57. /**
  58. * Creates converter with given {@code delimiter} and {@link String} as
  59. * token model type in collection.
  60. *
  61. * @param delimiter
  62. * custom delimiter
  63. */
  64. public StringToCollectionConverter(String delimiter) {
  65. this(delimiter, null, String.class);
  66. }
  67. /**
  68. * Creates converter with given {@code tokenConverter} for convert tokens
  69. * and expected {@code tokenType}.
  70. * <p>
  71. * If {@code tokenConverter} is null then no conversation is done and
  72. * {@link String} is used as token type in resulting model collection.
  73. *
  74. * @param tokenConverter
  75. * converter for token
  76. * @param tokenType
  77. * expected token model type
  78. */
  79. public StringToCollectionConverter(Converter<String, ?> tokenConverter,
  80. Class<?> tokenType) {
  81. this(", ", tokenConverter, tokenType);
  82. }
  83. /**
  84. * Creates converter with given {@code tokenConverter} for convert tokens
  85. * and expected {@code tokenType}.
  86. * <p>
  87. * If {@code tokenConverter} is null then no conversation is done and
  88. * {@link String} is used as token type in resulting model collection.
  89. *
  90. * @param tokenConverter
  91. * converter for token
  92. * @param tokenType
  93. * expected token model type
  94. * @param delimiter
  95. * delimiter in presentation string
  96. */
  97. public StringToCollectionConverter(String delimiter,
  98. Converter<String, ?> tokenConverter, Class<?> tokenClass) {
  99. this(delimiter, tokenConverter, tokenClass,
  100. new DefaultCollectionFactory());
  101. }
  102. /**
  103. * Creates converter with given {@code tokenConverter} for convert tokens
  104. * and expected {@code tokenType}.
  105. * <p>
  106. * If {@code tokenConverter} is null then no conversation is done and
  107. * {@link String} is used as token type in resulting model collection.
  108. *
  109. * @param tokenConverter
  110. * converter for token
  111. * @param tokenType
  112. * expected token model type
  113. * @param delimiter
  114. * delimiter in presentation string
  115. * @param factory
  116. * factory to create resulting collection
  117. */
  118. public StringToCollectionConverter(String delimiter,
  119. Converter<String, ?> tokenConverter, Class<?> tokenClass,
  120. CollectionFactory factory) {
  121. if (delimiter == null || delimiter.isEmpty()) {
  122. throw new IllegalArgumentException(
  123. "Delimiter should be non-empty string");
  124. }
  125. this.delimiter = delimiter;
  126. this.tokenConverter = tokenConverter;
  127. tokenType = tokenClass;
  128. this.factory = factory;
  129. }
  130. @Override
  131. public Class<Collection> getModelType() {
  132. return Collection.class;
  133. }
  134. @Override
  135. public Class<String> getPresentationType() {
  136. return String.class;
  137. }
  138. @Override
  139. public Collection convertToModel(String value,
  140. Class<? extends Collection> targetType, Locale locale)
  141. throws Converter.ConversionException {
  142. if (value == null) {
  143. return null;
  144. }
  145. int index = value.indexOf(delimiter);
  146. int previous = 0;
  147. Collection result = factory.createCollection(targetType);
  148. Converter converter = tokenConverter;
  149. while (index != -1) {
  150. collectToken(value.substring(previous, index), result, converter,
  151. locale);
  152. previous = index + delimiter.length();
  153. index = value.indexOf(delimiter, previous);
  154. }
  155. collectToken(value.substring(previous), result, converter, locale);
  156. return result;
  157. }
  158. @Override
  159. public String convertToPresentation(Collection value,
  160. Class<? extends String> targetType, Locale locale)
  161. throws Converter.ConversionException {
  162. if (value == null) {
  163. return null;
  164. }
  165. StringBuilder builder = new StringBuilder();
  166. Converter converter = tokenConverter;
  167. for (Iterator<?> iterator = value.iterator(); iterator.hasNext();) {
  168. if (converter == null) {
  169. builder.append(iterator.next());
  170. } else {
  171. builder.append(converter.convertToPresentation(iterator.next(),
  172. targetType, locale));
  173. }
  174. builder.append(delimiter);
  175. }
  176. if (builder.length() != 0) {
  177. return builder.substring(0, builder.length() - delimiter.length());
  178. } else {
  179. return builder.toString();
  180. }
  181. }
  182. private void collectToken(String token, Collection collection,
  183. Converter converter, Locale locale) {
  184. if (converter == null) {
  185. collection.add(token);
  186. } else {
  187. collection.add(converter.convertToModel(token, tokenType, locale));
  188. }
  189. }
  190. /**
  191. * Default collection factory implementation.
  192. *
  193. * @author Vaadin Ltd
  194. */
  195. @Deprecated
  196. public static class DefaultCollectionFactory implements CollectionFactory {
  197. @Override
  198. public Collection<?> createCollection(
  199. Class<? extends Collection> type) {
  200. if (type.isAssignableFrom(ArrayList.class)) {
  201. return new ArrayList<Object>();
  202. } else if (type.isAssignableFrom(HashSet.class)) {
  203. return new HashSet<Object>();
  204. } else if (!type.isInterface()
  205. && !Modifier.isAbstract(type.getModifiers())) {
  206. try {
  207. return type.newInstance();
  208. } catch (InstantiationException ignore) {
  209. } catch (IllegalAccessException ignore) {
  210. }
  211. }
  212. return new ArrayList<Object>();
  213. }
  214. }
  215. /**
  216. * Collection factory. Defines a strategy to create collection by collection
  217. * class.
  218. *
  219. * @author Vaadin Ltd
  220. */
  221. @Deprecated
  222. public interface CollectionFactory extends Serializable {
  223. /**
  224. * Create collection by its {@code type}.
  225. *
  226. * @param type
  227. * collection type
  228. * @return instantiated collection with given {@code type}
  229. */
  230. Collection<?> createCollection(Class<? extends Collection> type);
  231. }
  232. }