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 }