View Javadoc
1   /*
2    *   Copyright (C) Christian Schulte <cs@schulte.it>, 2011-293
3    *   All rights reserved.
4    *
5    *   Redistribution and use in source and binary forms, with or without
6    *   modification, are permitted provided that the following conditions
7    *   are met:
8    *
9    *     o Redistributions of source code must retain the above copyright
10   *       notice, this list of conditions and the following disclaimer.
11   *
12   *     o Redistributions in binary form must reproduce the above copyright
13   *       notice, this list of conditions and the following disclaimer in
14   *       the documentation and/or other materials provided with the
15   *       distribution.
16   *
17   *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18   *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19   *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
20   *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21   *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22   *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23   *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24   *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25   *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26   *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27   *
28   *   $JOMC: KeyValueType.java 5043 2015-05-27 07:03:39Z schulte $
29   *
30   */
31  package org.jomc.mojo;
32  
33  import java.lang.reflect.InvocationTargetException;
34  import java.lang.reflect.Method;
35  import java.lang.reflect.Modifier;
36  import org.apache.commons.lang.builder.ToStringBuilder;
37  import org.jomc.modlet.ModelContext;
38  import org.jomc.modlet.ModelException;
39  
40  /**
41   * Datatype holding a {@code key}, {@code value} and {@code type} property.
42   *
43   * @author <a href="mailto:cs@schulte.it">Christian Schulte</a>
44   * @version $JOMC: KeyValueType.java 5043 2015-05-27 07:03:39Z schulte $
45   * @since 1.2
46   */
47  public class KeyValueType implements Cloneable
48  {
49  
50      /**
51       * The key of the type.
52       */
53      private String key;
54  
55      /**
56       * The value of the type.
57       */
58      private String value;
59  
60      /**
61       * The name of the class of the type of {@code value}.
62       */
63      private String type;
64  
65      /**
66       * Creates a new {@code KeyValueType} instance.
67       */
68      public KeyValueType()
69      {
70          super();
71      }
72  
73      /**
74       * Gets the value of the {@code key} property.
75       *
76       * @return The value of the {@code key} property.
77       *
78       * @see #setKey(java.lang.String)
79       */
80      public final String getKey()
81      {
82          return this.key;
83      }
84  
85      /**
86       * Sets the value of the {@code key} property.
87       *
88       * @param k The new value of the {@code key} property.
89       *
90       * @see #getKey()
91       */
92      public final void setKey( final String k )
93      {
94          this.key = k;
95      }
96  
97      /**
98       * Gets the value of the {@code value} property.
99       *
100      * @return The value of the {@code value} property or {@code null}.
101      *
102      * @see #setValue(java.lang.String)
103      */
104     public final String getValue()
105     {
106         return this.value;
107     }
108 
109     /**
110      * Sets the value of the {@code value} property.
111      *
112      * @param v The new value of the {@code value} property or {@code null}.
113      *
114      * @see #getValue()
115      */
116     public final void setValue( final String v )
117     {
118         this.value = v;
119     }
120 
121     /**
122      * Gets the value of the {@code type} property.
123      *
124      * @return The value of the {@code type} property or {@code null}.
125      *
126      * @see #setType(java.lang.String)
127      */
128     public final String getType()
129     {
130         return this.type;
131     }
132 
133     /**
134      * Sets the value of the {@code type} property.
135      *
136      * @param t The new value of the {@code type} property or {@code null}.
137      *
138      * @see #getType()
139      */
140     public final void setType( final String t )
141     {
142         this.type = t;
143     }
144 
145     /**
146      * Gets the object of the instance.
147      *
148      * @return The object of the instance or {@code null}.
149      *
150      * @throws InstantiationException if getting the object of the instance fails.
151      *
152      * @see #getType()
153      * @see #getValue()
154      * @deprecated As of JOMC 1.8, replaced by method {@link #getObject(org.jomc.modlet.ModelContext)}. This method
155      * will be removed in JOMC 2.0.
156      */
157     @Deprecated
158     public Object getObject() throws InstantiationException // JDK: As of JDK 7, "throws ReflectiveOperationException".
159     {
160         Class<?> javaClass = null;
161         Object o = this.getValue();
162 
163         try
164         {
165             if ( o != null )
166             {
167                 if ( this.getType() != null && !String.class.getName().equals( this.getType() ) )
168                 {
169                     javaClass = Class.forName( this.getType() );
170 
171                     try
172                     {
173                         o = javaClass.getConstructor( String.class ).newInstance( o );
174                     }
175                     catch ( final NoSuchMethodException e )
176                     {
177                         final Method valueOf = javaClass.getMethod( "valueOf", String.class );
178 
179                         if ( Modifier.isStatic( valueOf.getModifiers() )
180                                  && valueOf.getReturnType().equals( javaClass ) )
181                         {
182                             o = valueOf.invoke( null, o );
183                         }
184                         else
185                         {
186                             throw (InstantiationException) new InstantiationException(
187                                 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
188                                                      javaClass.getSimpleName() ) ).initCause( e );
189 
190                         }
191                     }
192                 }
193             }
194             else if ( this.getType() != null )
195             {
196                 o = Class.forName( this.getType() ).newInstance();
197             }
198 
199             return o;
200         }
201         catch ( final ClassNotFoundException e )
202         {
203             throw (InstantiationException) new InstantiationException(
204                 Messages.getMessage( "classNotFound", this.getType() ) ).initCause( e );
205 
206         }
207         catch ( final NoSuchMethodException e )
208         {
209             throw (InstantiationException) new InstantiationException(
210                 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
211                                      javaClass.getSimpleName() ) ).initCause( e );
212 
213         }
214         catch ( final IllegalAccessException e )
215         {
216             throw (InstantiationException) new InstantiationException(
217                 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
218 
219         }
220         catch ( final InvocationTargetException e )
221         {
222             throw (InstantiationException) new InstantiationException(
223                 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
224 
225         }
226     }
227 
228     /**
229      * Gets the object of the instance.
230      *
231      * @param modelContext The context to use for getting the object of the instance.
232      *
233      * @return The object of the instance or {@code null}.
234      *
235      * @throws NullPointerException if {@code modelContext} is {@code null}.
236      * @throws InstantiationException if getting the object of the instance fails.
237      *
238      * @see #getType()
239      * @see #getValue()
240      *
241      * @since 1.8
242      */
243     public Object getObject( final ModelContext modelContext ) throws InstantiationException // JDK: As of JDK 7, "throws ReflectiveOperationException".
244     {
245         if ( modelContext == null )
246         {
247             throw new NullPointerException( "modelContext" );
248         }
249 
250         Class<?> javaClass = null;
251         Object o = this.getValue();
252 
253         try
254         {
255             if ( o != null )
256             {
257                 if ( this.getType() != null && !String.class.getName().equals( this.getType() ) )
258                 {
259                     javaClass = modelContext.findClass( this.getType() );
260 
261                     if ( javaClass == null )
262                     {
263                         throw (InstantiationException) new InstantiationException(
264                             Messages.getMessage( "classNotFound", this.getType() ) );
265 
266                     }
267 
268                     try
269                     {
270                         o = javaClass.getConstructor( String.class ).newInstance( o );
271                     }
272                     catch ( final NoSuchMethodException e )
273                     {
274                         final Method valueOf = javaClass.getMethod( "valueOf", String.class );
275 
276                         if ( Modifier.isStatic( valueOf.getModifiers() )
277                                  && valueOf.getReturnType().equals( javaClass ) )
278                         {
279                             o = valueOf.invoke( null, o );
280                         }
281                         else
282                         {
283                             throw (InstantiationException) new InstantiationException(
284                                 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
285                                                      javaClass.getSimpleName() ) ).initCause( e );
286 
287                         }
288                     }
289                 }
290             }
291             else if ( this.getType() != null )
292             {
293                 javaClass = modelContext.findClass( this.getType() );
294 
295                 if ( javaClass == null )
296                 {
297                     throw (InstantiationException) new InstantiationException(
298                         Messages.getMessage( "classNotFound", this.getType() ) );
299 
300                 }
301 
302                 o = javaClass.newInstance();
303             }
304 
305             return o;
306         }
307         catch ( final ModelException e )
308         {
309             throw (InstantiationException) new InstantiationException(
310                 Messages.getMessage( "failedSearchingClass", this.getType() ) ).initCause( e );
311 
312         }
313         catch ( final NoSuchMethodException e )
314         {
315             throw (InstantiationException) new InstantiationException(
316                 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
317                                      javaClass.getSimpleName() ) ).initCause( e );
318 
319         }
320         catch ( final IllegalAccessException e )
321         {
322             throw (InstantiationException) new InstantiationException(
323                 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
324 
325         }
326         catch ( final InvocationTargetException e )
327         {
328             throw (InstantiationException) new InstantiationException(
329                 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
330 
331         }
332     }
333 
334     /**
335      * Creates and returns a copy of this object.
336      *
337      * @return A copy of this object.
338      */
339     @Override
340     public KeyValueType clone()
341     {
342         try
343         {
344             return (KeyValueType) super.clone();
345         }
346         catch ( final CloneNotSupportedException e )
347         {
348             throw new AssertionError( e );
349         }
350     }
351 
352     /**
353      * Creates and returns a string representation of the object.
354      *
355      * @return A string representation of the object.
356      */
357     @Override
358     public String toString()
359     {
360         return ToStringBuilder.reflectionToString( this );
361     }
362 
363 }