View Javadoc

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  }