Coverage Report - joptsimple.internal.Reflection
 
Classes in this File Line Coverage Branch Coverage Complexity
Reflection
97%
34/35
85%
17/20
4
 
 1  
 /*
 2  
  The MIT License
 3  
 
 4  
  Copyright (c) 2004-2015 Paul R. Holser, Jr.
 5  
 
 6  
  Permission is hereby granted, free of charge, to any person obtaining
 7  
  a copy of this software and associated documentation files (the
 8  
  "Software"), to deal in the Software without restriction, including
 9  
  without limitation the rights to use, copy, modify, merge, publish,
 10  
  distribute, sublicense, and/or sell copies of the Software, and to
 11  
  permit persons to whom the Software is furnished to do so, subject to
 12  
  the following conditions:
 13  
 
 14  
  The above copyright notice and this permission notice shall be
 15  
  included in all copies or substantial portions of the Software.
 16  
 
 17  
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 18  
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 19  
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 20  
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 21  
  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 22  
  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 23  
  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 24  
 */
 25  
 
 26  
 package joptsimple.internal;
 27  
 
 28  
 import java.lang.reflect.Constructor;
 29  
 import java.lang.reflect.InvocationTargetException;
 30  
 import java.lang.reflect.Method;
 31  
 
 32  
 import static java.lang.reflect.Modifier.*;
 33  
 
 34  
 import joptsimple.ValueConverter;
 35  
 
 36  
 import static joptsimple.internal.Classes.*;
 37  
 
 38  
 /**
 39  
  * Helper methods for reflection.
 40  
  *
 41  
  * @author <a href="mailto:pholser@alumni.rice.edu">Paul Holser</a>
 42  
  */
 43  
 public final class Reflection {
 44  1
     private Reflection() {
 45  1
         throw new UnsupportedOperationException();
 46  
     }
 47  
 
 48  
     /**
 49  
      * Finds an appropriate value converter for the given class.
 50  
      *
 51  
      * @param <V> a constraint on the class object to introspect
 52  
      * @param clazz class to introspect on
 53  
      * @return a converter method or constructor
 54  
      */
 55  
     public static <V> ValueConverter<V> findConverter( Class<V> clazz ) {
 56  145
         Class<V> maybeWrapper = wrapperOf( clazz );
 57  
 
 58  143
         ValueConverter<V> valueOf = valueOfConverter( maybeWrapper );
 59  143
         if ( valueOf != null )
 60  93
             return valueOf;
 61  
 
 62  50
         ValueConverter<V> constructor = constructorConverter( maybeWrapper );
 63  50
         if ( constructor != null )
 64  47
             return constructor;
 65  
 
 66  3
         throw new IllegalArgumentException( clazz + " is not a value type" );
 67  
     }
 68  
 
 69  
     private static <V> ValueConverter<V> valueOfConverter( Class<V> clazz ) {
 70  
         try {
 71  143
             Method valueOf = clazz.getDeclaredMethod( "valueOf", String.class );
 72  95
             if ( meetsConverterRequirements( valueOf, clazz ) )
 73  93
                 return new MethodInvokingValueConverter<V>( valueOf, clazz );
 74  
 
 75  2
             return null;
 76  
         }
 77  48
         catch ( NoSuchMethodException ignored ) {
 78  48
             return null;
 79  
         }
 80  
     }
 81  
 
 82  
     private static <V> ValueConverter<V> constructorConverter( Class<V> clazz ) {
 83  
         try {
 84  50
             return new ConstructorInvokingValueConverter<V>( clazz.getConstructor( String.class ) );
 85  
         }
 86  3
         catch ( NoSuchMethodException ignored ) {
 87  3
             return null;
 88  
         }
 89  
     }
 90  
 
 91  
     /**
 92  
      * Invokes the given constructor with the given arguments.
 93  
      *
 94  
      * @param <T> constraint on the type of the objects yielded by the constructor
 95  
      * @param constructor constructor to invoke
 96  
      * @param args arguments to hand to the constructor
 97  
      * @return the result of invoking the constructor
 98  
      * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions
 99  
      */
 100  
     public static <T> T instantiate( Constructor<T> constructor, Object... args ) {
 101  
         try {
 102  55
             return constructor.newInstance( args );
 103  
         }
 104  5
         catch ( Exception ex ) {
 105  5
             throw reflectionException( ex );
 106  
         }
 107  
     }
 108  
 
 109  
     /**
 110  
      * Invokes the given static method with the given arguments.
 111  
      *
 112  
      * @param method method to invoke
 113  
      * @param args arguments to hand to the method
 114  
      * @return the result of invoking the method
 115  
      * @throws ReflectionException in lieu of the gaggle of reflection-related exceptions
 116  
      */
 117  
     public static Object invoke( Method method, Object... args ) {
 118  
         try {
 119  173
             return method.invoke( null, args );
 120  
         }
 121  6
         catch ( Exception ex ) {
 122  6
             throw reflectionException( ex );
 123  
         }
 124  
     }
 125  
 
 126  
     @SuppressWarnings( "unchecked" )
 127  
     public static <V> V convertWith( ValueConverter<V> converter, String raw ) {
 128  635
         return converter == null ? (V) raw : converter.convert( raw );
 129  
     }
 130  
 
 131  
     private static boolean meetsConverterRequirements( Method method, Class<?> expectedReturnType ) {
 132  95
         int modifiers = method.getModifiers();
 133  95
         return isPublic( modifiers ) && isStatic( modifiers ) && expectedReturnType.equals( method.getReturnType() );
 134  
     }
 135  
 
 136  
     private static RuntimeException reflectionException( Exception ex ) {
 137  11
         if ( ex instanceof IllegalArgumentException )
 138  2
             return new ReflectionException( ex );
 139  9
         if ( ex instanceof InvocationTargetException )
 140  6
             return new ReflectionException( ex.getCause() );
 141  3
         if ( ex instanceof RuntimeException )
 142  0
             return (RuntimeException) ex;
 143  
 
 144  3
         return new ReflectionException( ex );
 145  
     }
 146  
 }