1 /*
2 * Copyright 2010-2011 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.InvocationTargetException;
19 import java.lang.reflect.Method;
20
21 /**
22 * Conversion to and from a string using two methods.
23 * <p>
24 * The toString method must meet the following signature:<br />
25 * {@code String anyName()} on Class T.
26 * <p>
27 * The fromString method must meet the following signature:<br />
28 * {@code static T anyName(String)} on any class.
29 * <p>
30 * MethodsStringConverter is thread-safe and immutable.
31 *
32 * @param <T> the type of the converter
33 */
34 final class MethodsStringConverter<T> extends ReflectionStringConverter<T> {
35
36 /** Conversion from a string. */
37 private final Method fromString;
38
39 /**
40 * Creates an instance using two methods.
41 * @param cls the class this converts for, not null
42 * @param toString the toString method, not null
43 * @param fromString the fromString method, not null
44 * @throws RuntimeException (or subclass) if the method signatures are invalid
45 */
46 MethodsStringConverter(Class<T> cls, Method toString, Method fromString) {
47 super(cls, toString);
48 if (fromString.getParameterTypes().length != 1) {
49 throw new IllegalStateException("FromString method must have one parameter");
50 }
51 Class<?> param = fromString.getParameterTypes()[0];
52 if (param != String.class && param != CharSequence.class) {
53 throw new IllegalStateException("FromString method must take a String or CharSequence");
54 }
55 if (fromString.getReturnType().isAssignableFrom(cls) == false) {
56 throw new IllegalStateException("FromString method must return specified class or a superclass");
57 }
58 this.fromString = fromString;
59 }
60
61 //-----------------------------------------------------------------------
62 /**
63 * Converts the {@code String} to an object.
64 * @param cls the class to convert to, not null
65 * @param str the string to convert, not null
66 * @return the converted object, may be null but generally not
67 */
68 public T convertFromString(Class<? extends T> cls, String str) {
69 try {
70 return cls.cast(fromString.invoke(null, str));
71 } catch (IllegalAccessException ex) {
72 throw new IllegalStateException("Method is not accessible");
73 } catch (InvocationTargetException ex) {
74 if (ex.getCause() instanceof RuntimeException) {
75 throw (RuntimeException) ex.getCause();
76 }
77 throw new RuntimeException(ex.getMessage(), ex.getCause());
78 }
79 }
80
81 }