001 // Copyright 2007, 2008, 2010, 2011 The Apache Software Foundation
002 //
003 // Licensed under the Apache License, Version 2.0 (the "License");
004 // you may not use this file except in compliance with the License.
005 // You may obtain a copy of the License at
006 //
007 // http://www.apache.org/licenses/LICENSE-2.0
008 //
009 // Unless required by applicable law or agreed to in writing, software
010 // distributed under the License is distributed on an "AS IS" BASIS,
011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012 // See the License for the specific language governing permissions and
013 // limitations under the License.
014
015 package org.apache.tapestry5.util;
016
017 import java.util.Map;
018
019 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
020 import org.apache.tapestry5.ioc.internal.util.InternalUtils;
021 import org.apache.tapestry5.ioc.services.Coercion;
022 import org.apache.tapestry5.ioc.util.AvailableValues;
023 import org.apache.tapestry5.ioc.util.UnknownValueException;
024
025 /**
026 * A {@link org.apache.tapestry5.ioc.services.Coercion} for converting strings into an instance of a particular
027 * enumerated type. The {@link Enum#name() name} is used as the key to identify the enum instance, in a case-insensitive
028 * fashion.
029 * <p>
030 * Moved from tapestry-core to tapestry-ioc is release 5.3, but kept in same package for compatibility.
031 *
032 * @param <T>
033 * the type of enumeration
034 */
035 public final class StringToEnumCoercion<T extends Enum> implements Coercion<String, T>
036 {
037 private final Class<T> enumClass;
038
039 private final Map<String, T> stringToEnum = CollectionFactory.newCaseInsensitiveMap();
040
041 public StringToEnumCoercion(Class<T> enumClass)
042 {
043 this(enumClass, enumClass.getEnumConstants());
044 }
045
046 public StringToEnumCoercion(Class<T> enumClass, T... values)
047 {
048 this.enumClass = enumClass;
049
050 for (T value : values)
051 stringToEnum.put(value.name(), value);
052 }
053
054 public T coerce(String input)
055 {
056 if (InternalUtils.isBlank(input))
057 return null;
058
059 T result = stringToEnum.get(input);
060
061 if (result == null)
062 {
063 String message = String.format("Input '%s' does not identify a value from enumerated type %s.", input,
064 enumClass.getName());
065
066 throw new UnknownValueException(message, new AvailableValues(enumClass.getName() + " enum constants",
067 stringToEnum));
068 }
069
070 return result;
071 }
072
073 /**
074 * Allows an alias value (alternate) string to reference a value.
075 *
076 * @since 5.2.2
077 */
078 public StringToEnumCoercion<T> addAlias(String alias, T value)
079 {
080 stringToEnum.put(alias, value);
081
082 return this;
083 }
084
085 public static <T extends Enum> StringToEnumCoercion<T> create(Class<T> enumClass)
086 {
087 return new StringToEnumCoercion<T>(enumClass);
088 }
089
090 }