001/* 002 * Copyright (C) Christian Schulte <cs@schulte.it>, 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 5067 2015-07-06 07:31:18Z schulte $ 029 * 030 */ 031package org.jomc.mojo; 032 033import java.lang.reflect.InvocationTargetException; 034import java.lang.reflect.Method; 035import java.lang.reflect.Modifier; 036import org.apache.commons.lang.builder.ToStringBuilder; 037import org.jomc.modlet.ModelContext; 038import org.jomc.modlet.ModelException; 039 040/** 041 * Datatype holding a {@code key}, {@code value} and {@code type} property. 042 * 043 * @author <a href="mailto:cs@schulte.it">Christian Schulte</a> 044 * @version $JOMC: KeyValueType.java 5067 2015-07-06 07:31:18Z schulte $ 045 * @since 1.2 046 */ 047public class KeyValueType implements Cloneable 048{ 049 050 /** 051 * The key of the type. 052 */ 053 private String key; 054 055 /** 056 * The value of the type. 057 */ 058 private String value; 059 060 /** 061 * The name of the class of the type of {@code value}. 062 */ 063 private String type; 064 065 /** 066 * Creates a new {@code KeyValueType} instance. 067 */ 068 public KeyValueType() 069 { 070 super(); 071 } 072 073 /** 074 * Gets the value of the {@code key} property. 075 * 076 * @return The value of the {@code key} property. 077 * 078 * @see #setKey(java.lang.String) 079 */ 080 public final String getKey() 081 { 082 return this.key; 083 } 084 085 /** 086 * Sets the value of the {@code key} property. 087 * 088 * @param k The new value of the {@code key} property. 089 * 090 * @see #getKey() 091 */ 092 public final void setKey( final String k ) 093 { 094 this.key = k; 095 } 096 097 /** 098 * Gets the value of the {@code value} property. 099 * 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 new InstantiationException( Messages.getMessage( "classNotFound", this.getType() ) ); 264 } 265 266 try 267 { 268 o = javaClass.getConstructor( String.class ).newInstance( o ); 269 } 270 catch ( final NoSuchMethodException e ) 271 { 272 final Method valueOf = javaClass.getMethod( "valueOf", String.class ); 273 274 if ( Modifier.isStatic( valueOf.getModifiers() ) 275 && valueOf.getReturnType().equals( javaClass ) ) 276 { 277 o = valueOf.invoke( null, o ); 278 } 279 else 280 { 281 throw (InstantiationException) new InstantiationException( 282 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(), 283 javaClass.getSimpleName() ) ).initCause( e ); 284 285 } 286 } 287 } 288 } 289 else if ( this.getType() != null ) 290 { 291 javaClass = modelContext.findClass( this.getType() ); 292 293 if ( javaClass == null ) 294 { 295 throw new InstantiationException( Messages.getMessage( "classNotFound", this.getType() ) ); 296 } 297 298 o = javaClass.newInstance(); 299 } 300 301 return o; 302 } 303 catch ( final ModelException e ) 304 { 305 throw (InstantiationException) new InstantiationException( 306 Messages.getMessage( "failedSearchingClass", this.getType() ) ).initCause( e ); 307 308 } 309 catch ( final NoSuchMethodException e ) 310 { 311 throw (InstantiationException) new InstantiationException( 312 Messages.getMessage( "noSuchMethodCreatingObject", this.getType(), this.getValue(), 313 javaClass.getSimpleName() ) ).initCause( e ); 314 315 } 316 catch ( final IllegalAccessException e ) 317 { 318 throw (InstantiationException) new InstantiationException( 319 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e ); 320 321 } 322 catch ( final InvocationTargetException e ) 323 { 324 throw (InstantiationException) new InstantiationException( 325 Messages.getMessage( "failedCreatingObject", this.getType() ) ).initCause( e ); 326 327 } 328 } 329 330 /** 331 * Creates and returns a copy of this object. 332 * 333 * @return A copy of this object. 334 */ 335 @Override 336 public KeyValueType clone() 337 { 338 try 339 { 340 return (KeyValueType) super.clone(); 341 } 342 catch ( final CloneNotSupportedException e ) 343 { 344 throw new AssertionError( e ); 345 } 346 } 347 348 /** 349 * Creates and returns a string representation of the object. 350 * 351 * @return A string representation of the object. 352 */ 353 @Override 354 public String toString() 355 { 356 return ToStringBuilder.reflectionToString( this ); 357 } 358 359}