View Javadoc
1   /*
2    *  Copyright 2010, 2011 Chris Pheby
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.jadira.bindings.core.general.unmarshaller;
17  
18  import java.lang.reflect.Constructor;
19  import java.lang.reflect.InvocationTargetException;
20  import java.lang.reflect.Modifier;
21  
22  import org.jadira.bindings.core.api.BindingException;
23  import org.jadira.bindings.core.api.FromUnmarshaller;
24  
25  /**
26   * Unmarshaller supports constructor parameterised by a target object
27   * @param <S> Source type for the conversion
28   * @param <T> Target type
29   */
30  public final class ConstructorFromUnmarshaller<S, T> implements FromUnmarshaller<S, T> {
31  
32      private final Constructor<S> unmarshal;
33  
34      private final Class<S> boundClass;
35      
36      private final Class<T> targetClass;
37      
38      /**
39       * Create a new instance
40       * @param unmarshal Constructor to be used
41       */
42      public ConstructorFromUnmarshaller(Constructor<S> unmarshal) {
43          
44          this.boundClass = unmarshal.getDeclaringClass();
45          
46          if (getBoundClass().isInterface() 
47                  || Modifier.isAbstract(getBoundClass().getModifiers()) 
48                  || getBoundClass().isLocalClass() 
49                  || getBoundClass().isMemberClass()) {
50              throw new IllegalStateException("unmarshal constructor must have an instantiable target class");
51          }
52          
53          if (unmarshal.getParameterTypes().length != 1) {
54          	throw new IllegalStateException("unmarshal constructor must have a single parameter");
55          }
56          
57          this.unmarshal = unmarshal;
58          
59          @SuppressWarnings("unchecked")
60          Class<T> myTarget = (Class<T>)unmarshal.getParameterTypes()[0];
61          this.targetClass = myTarget;
62      }
63  
64  	/**
65  	 * {@inheritDoc}
66  	 */
67  	/* @Override */
68      public S unmarshal(T object) {
69      	
70      	if (object != null && !targetClass.isAssignableFrom(object.getClass())) {
71      		throw new IllegalArgumentException("Supplied object was not instance of target class");
72      	}
73      	
74          try {
75              return unmarshal.newInstance(object);
76          } catch (IllegalAccessException ex) {
77              throw new IllegalStateException("Constructor is not accessible");
78          } catch (InstantiationException ex) {
79              throw new IllegalStateException("Constructor is not valid");
80          } catch (InvocationTargetException ex) {
81              if (ex.getCause() instanceof RuntimeException) {
82                  throw (RuntimeException) ex.getCause();
83              }
84              throw new BindingException(ex.getMessage(), ex.getCause());
85          }
86      }
87      
88  	/**
89  	 * {@inheritDoc}
90  	 */
91  	/* @Override */
92      public Class<S> getBoundClass() {
93          return boundClass;
94      }
95      
96  	/**
97  	 * {@inheritDoc}
98  	 */
99  	/* @Override */
100     public Class<T> getTargetClass() {
101         return targetClass;
102     }
103 }