/* * Copyright 2000-2016 Vaadin Ltd. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.vaadin.v7.data.util.converter; import com.vaadin.data.Binder; import java.io.Serializable; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; import java.util.Locale; /** * A converter that converts from {@link String} to {@link Collection} of tokens * and back. * <p> * Allows to break a string into tokens using delimiter. Each token can be * converted to its own model using provided converter. * <p> * Default constructor uses <code>", "</code> as delimiter string and * {@link String} for token types. Other constructors allow to configure * delimiter and token types. * * @since 7.5.0 * * @author Vaadin Ltd * * @deprecated As of 8.0, a lightweight lambda-based converter can be build with * {@link Binder}{@code .forField(...).withConverter(...)} methods. */ @Deprecated public class StringToCollectionConverter implements Converter<String, Collection> { private final String delimiter; private final Converter<String, ?> tokenConverter; private final Class<?> tokenType; private final CollectionFactory factory; /** * Creates converter with <code>", "</code> as delimiter and {@link String} * as token model type in collection. */ public StringToCollectionConverter() { this(", ", null, String.class); } /** * Creates converter with given {@code delimiter} and {@link String} as * token model type in collection. * * @param delimiter * custom delimiter */ public StringToCollectionConverter(String delimiter) { this(delimiter, null, String.class); } /** * Creates converter with given {@code tokenConverter} for convert tokens * and expected {@code tokenType}. * <p> * If {@code tokenConverter} is null then no conversation is done and * {@link String} is used as token type in resulting model collection. * * @param tokenConverter * converter for token * @param tokenType * expected token model type */ public StringToCollectionConverter(Converter<String, ?> tokenConverter, Class<?> tokenType) { this(", ", tokenConverter, tokenType); } /** * Creates converter with given {@code tokenConverter} for convert tokens * and expected {@code tokenType}. * <p> * If {@code tokenConverter} is null then no conversation is done and * {@link String} is used as token type in resulting model collection. * * @param tokenConverter * converter for token * @param tokenType * expected token model type * @param delimiter * delimiter in presentation string */ public StringToCollectionConverter(String delimiter, Converter<String, ?> tokenConverter, Class<?> tokenClass) { this(delimiter, tokenConverter, tokenClass, new DefaultCollectionFactory()); } /** * Creates converter with given {@code tokenConverter} for convert tokens * and expected {@code tokenType}. * <p> * If {@code tokenConverter} is null then no conversation is done and * {@link String} is used as token type in resulting model collection. * * @param tokenConverter * converter for token * @param tokenType * expected token model type * @param delimiter * delimiter in presentation string * @param factory * factory to create resulting collection */ public StringToCollectionConverter(String delimiter, Converter<String, ?> tokenConverter, Class<?> tokenClass, CollectionFactory factory) { if (delimiter == null || delimiter.isEmpty()) { throw new IllegalArgumentException( "Delimiter should be non-empty string"); } this.delimiter = delimiter; this.tokenConverter = tokenConverter; tokenType = tokenClass; this.factory = factory; } @Override public Class<Collection> getModelType() { return Collection.class; } @Override public Class<String> getPresentationType() { return String.class; } @Override public Collection convertToModel(String value, Class<? extends Collection> targetType, Locale locale) throws Converter.ConversionException { if (value == null) { return null; } int index = value.indexOf(delimiter); int previous = 0; Collection result = factory.createCollection(targetType); Converter converter = tokenConverter; while (index != -1) { collectToken(value.substring(previous, index), result, converter, locale); previous = index + delimiter.length(); index = value.indexOf(delimiter, previous); } collectToken(value.substring(previous), result, converter, locale); return result; } @Override public String convertToPresentation(Collection value, Class<? extends String> targetType, Locale locale) throws Converter.ConversionException { if (value == null) { return null; } StringBuilder builder = new StringBuilder(); Converter converter = tokenConverter; for (Iterator<?> iterator = value.iterator(); iterator.hasNext();) { if (converter == null) { builder.append(iterator.next()); } else { builder.append(converter.convertToPresentation(iterator.next(), targetType, locale)); } builder.append(delimiter); } if (builder.length() > 0) { return builder.substring(0, builder.length() - delimiter.length()); } else { return builder.toString(); } } private void collectToken(String token, Collection collection, Converter converter, Locale locale) { if (converter == null) { collection.add(token); } else { collection.add(converter.convertToModel(token, tokenType, locale)); } } /** * Default collection factory implementation. * * @author Vaadin Ltd */ @Deprecated public static class DefaultCollectionFactory implements CollectionFactory { @Override public Collection<?> createCollection( Class<? extends Collection> type) { if (type.isAssignableFrom(ArrayList.class)) { return new ArrayList<Object>(); } else if (type.isAssignableFrom(HashSet.class)) { return new HashSet<Object>(); } else if (!type.isInterface() && !Modifier.isAbstract(type.getModifiers())) { try { return type.newInstance(); } catch (InstantiationException ignore) { } catch (IllegalAccessException ignore) { } } return new ArrayList<Object>(); } } /** * Collection factory. Defines a strategy to create collection by collection * class. * * @author Vaadin Ltd */ @Deprecated public interface CollectionFactory extends Serializable { /** * Create collection by its {@code type}. * * @param type * collection type * @return instantiated collection with given {@code type} */ Collection<?> createCollection(Class<? extends Collection> type); } }