001    /*
002     *   Copyright (C) Christian Schulte, 2011-293
003     *   All rights reserved.
004     *
005     *   Redistribution and use in source and binary forms, with or without
006     *   modification, are permitted provided that the following conditions
007     *   are met:
008     *
009     *     o Redistributions of source code must retain the above copyright
010     *       notice, this list of conditions and the following disclaimer.
011     *
012     *     o Redistributions in binary form must reproduce the above copyright
013     *       notice, this list of conditions and the following disclaimer in
014     *       the documentation and/or other materials provided with the
015     *       distribution.
016     *
017     *   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
018     *   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
019     *   AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
020     *   THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY DIRECT, INDIRECT,
021     *   INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022     *   NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023     *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024     *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025     *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026     *   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027     *
028     *   $JOMC: KeyValueType.java 3956 2011-11-18 22:29:49Z schulte2005 $
029     *
030     */
031    package org.jomc.mojo;
032    
033    import java.lang.reflect.InvocationTargetException;
034    import java.lang.reflect.Method;
035    import java.lang.reflect.Modifier;
036    import org.apache.commons.lang.builder.ToStringBuilder;
037    
038    /**
039     * Datatype holding a {@code key}, {@code value} and {@code type} property.
040     *
041     * @author <a href="mailto:schulte2005@users.sourceforge.net">Christian Schulte</a>
042     * @version $JOMC: KeyValueType.java 3956 2011-11-18 22:29:49Z schulte2005 $
043     * @since 1.2
044     */
045    public class KeyValueType implements Cloneable
046    {
047    
048        /** The key of the type. */
049        private String key;
050    
051        /** The value of the type. */
052        private String value;
053    
054        /** The name of the class of the type of {@code value}. */
055        private String type;
056    
057        /** Creates a new {@code KeyValueType} instance. */
058        public KeyValueType()
059        {
060            super();
061        }
062    
063        /**
064         * Gets the value of the {@code key} property.
065         *
066         * @return The value of the {@code key} property.
067         *
068         * @see #setKey(java.lang.String)
069         */
070        public final String getKey()
071        {
072            return this.key;
073        }
074    
075        /**
076         * Sets the value of the {@code key} property.
077         *
078         * @param k The new value of the {@code key} property.
079         *
080         * @see #getKey()
081         */
082        public final void setKey( final String k )
083        {
084            this.key = k;
085        }
086    
087        /**
088         * Gets the value of the {@code value} property.
089         *
090         * @return The value of the {@code value} property or {@code null}.
091         *
092         * @see #setValue(java.lang.String)
093         */
094        public final String getValue()
095        {
096            return this.value;
097        }
098    
099        /**
100         * Sets the value of the {@code value} property.
101         *
102         * @param v The new value of the {@code value} property or {@code null}.
103         *
104         * @see #getValue()
105         */
106        public final void setValue( final String v )
107        {
108            this.value = v;
109        }
110    
111        /**
112         * Gets the value of the {@code type} property.
113         *
114         * @return The value of the {@code type} property or {@code null}.
115         *
116         * @see #setType(java.lang.String)
117         */
118        public final String getType()
119        {
120            return this.type;
121        }
122    
123        /**
124         * Sets the value of the {@code type} property.
125         *
126         * @param t The new value of the {@code type} property or {@code null}.
127         *
128         * @see #getType()
129         */
130        public final void setType( final String t )
131        {
132            this.type = t;
133        }
134    
135        /**
136         * Gets the object of the instance.
137         *
138         * @return The object of the instance or {@code null}.
139         *
140         * @throws InstantiationException if getting the object of the instance fails.
141         *
142         * @see #getType()
143         * @see #getValue()
144         */
145        public Object getObject() throws InstantiationException // JDK: As of JDK 7, "throws ReflectiveOperationException".
146        {
147            Class<?> javaClass = null;
148            Object o = this.getValue();
149    
150            try
151            {
152                if ( o != null )
153                {
154                    if ( this.getType() != null && !String.class.getName().equals( this.getType() ) )
155                    {
156                        javaClass = Class.forName( this.getType() );
157    
158                        try
159                        {
160                            o = javaClass.getConstructor( String.class ).newInstance( o );
161                        }
162                        catch ( final NoSuchMethodException e )
163                        {
164                            final Method valueOf = javaClass.getMethod( "valueOf", String.class );
165    
166                            if ( Modifier.isStatic( valueOf.getModifiers() )
167                                 && valueOf.getReturnType().equals( javaClass ) )
168                            {
169                                o = valueOf.invoke( null, o );
170                            }
171                            else
172                            {
173                                throw (InstantiationException) new InstantiationException(
174                                    Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
175                                                         javaClass.getSimpleName() ) ).initCause( e );
176    
177                            }
178                        }
179                    }
180                }
181                else if ( this.getType() != null )
182                {
183                    o = Class.forName( this.getType() ).newInstance();
184                }
185    
186                return o;
187            }
188            catch ( final ClassNotFoundException e )
189            {
190                throw (InstantiationException) new InstantiationException(
191                    Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
192    
193            }
194            catch ( final NoSuchMethodException e )
195            {
196                throw (InstantiationException) new InstantiationException(
197                    Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(),
198                                         javaClass.getSimpleName() ) ).initCause( e );
199    
200            }
201            catch ( final IllegalAccessException e )
202            {
203                throw (InstantiationException) new InstantiationException(
204                    Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
205    
206            }
207            catch ( final InvocationTargetException e )
208            {
209                throw (InstantiationException) new InstantiationException(
210                    Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e );
211    
212            }
213        }
214    
215        /**
216         * Creates and returns a copy of this object.
217         *
218         * @return A copy of this object.
219         */
220        @Override
221        public KeyValueType clone()
222        {
223            try
224            {
225                return (KeyValueType) super.clone();
226            }
227            catch ( final CloneNotSupportedException e )
228            {
229                throw new AssertionError( e );
230            }
231        }
232    
233        /**
234         * Creates and returns a string representation of the object.
235         *
236         * @return A string representation of the object.
237         */
238        @Override
239        public String toString()
240        {
241            return ToStringBuilder.reflectionToString( this );
242        }
243    
244    }