1 /* 2 * Copyright 2010 Stephen Colebourne 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 package org.joda.convert; 17 18 import java.lang.reflect.Constructor; 19 import java.lang.reflect.InvocationTargetException; 20 import java.lang.reflect.Method; 21 import java.lang.reflect.Modifier; 22 23 /** 24 * Conversion to and from a string using a toString method and a fromString constructor. 25 * <p> 26 * The toString method must meet the following signature:<br /> 27 * {@code String anyName()} on Class T. 28 * <p> 29 * The fromString constructor must take a single {@code String} parameter. 30 * <p> 31 * MethodConstructorStringConverter is thread-safe and immutable. 32 * 33 * @param <T> the type of the converter 34 */ 35 final class MethodConstructorStringConverter<T> extends ReflectionStringConverter<T> { 36 37 /** Conversion from a string. */ 38 private final Constructor<T> fromString; 39 40 /** 41 * Creates an instance using a method and a constructor. 42 * @param cls the class this converts for, not null 43 * @param toString the toString method, not null 44 * @param fromString the fromString method, not null 45 * @throws RuntimeException (or subclass) if the method signatures are invalid 46 */ 47 MethodConstructorStringConverter(Class<T> cls, Method toString, Constructor<T> fromString) { 48 super(cls, toString); 49 if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers()) || cls.isLocalClass() || cls.isMemberClass()) { 50 throw new IllegalArgumentException("FromString constructor must be on an instantiable class"); 51 } 52 if (fromString.getDeclaringClass() != cls) { 53 throw new IllegalStateException("FromString constructor must be defined on specified class"); 54 } 55 this.fromString = fromString; 56 } 57 58 //----------------------------------------------------------------------- 59 /** 60 * Converts the {@code String} to an object. 61 * @param cls the class to convert to, not null 62 * @param str the string to convert, not null 63 * @return the converted object, may be null but generally not 64 */ 65 public T convertFromString(Class<? extends T> cls, String str) { 66 try { 67 return fromString.newInstance(str); 68 } catch (IllegalAccessException ex) { 69 throw new IllegalStateException("Constructor is not accessible"); 70 } catch (InstantiationException ex) { 71 throw new IllegalStateException("Constructor is not valid"); 72 } catch (InvocationTargetException ex) { 73 if (ex.getCause() instanceof RuntimeException) { 74 throw (RuntimeException) ex.getCause(); 75 } 76 throw new RuntimeException(ex.getMessage(), ex.getCause()); 77 } 78 } 79 80 }