View Javadoc
1   package org.apache.commons.beanutils2;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import static org.apache.commons.beanutils2.Assertions.checkArgument;
23  import static org.apache.commons.beanutils2.Assertions.checkNotNull;
24  import static org.apache.commons.beanutils2.TypeUtils.isAssignmentCompatible;
25  
26  /**
27   * An argument represents a value of some type that can be passed to a method or
28   * constructor.
29   *
30   * @param <T> the type of the argument.
31   */
32  public final class Argument<T>
33  {
34  
35      /**
36       * Factory method for arguments. Creates an argument by taking a value and determining the type of the given value.
37       *
38       * @param value the value to be wrapped by the new argument object. Must not be {@code null}! If you want to create
39       *            a null argument use {@link #nullArgument(Class)} instead.
40       * @param <A> the type of the argument.
41       * @return a new argument of type {@code value.getClass()}
42       */
43      public static <A> Argument<A> argument( A value )
44      {
45          value = checkNotNull( value, "Null not supported when specifying value only" );
46          @SuppressWarnings( "unchecked" )
47          Class<A> type = (Class<A>) value.getClass();
48          return argument( type, value );
49      }
50  
51      /**
52       * Creates a new null argument of the given type. Shortcut for {@code argument( type, null )}.
53       *
54       * @param type the type of the new argument. Must not be {@code null}!
55       * @param <A> the type of argument.
56       * @return an argument with {@code value == null}.
57       */
58      public static <A> Argument<A> nullArgument( Class<A> type )
59      {
60          return argument( type, null );
61      }
62  
63      /**
64       * Creates a new argument of the given type with the given value.
65       *
66       * @param type the type of the new argument. Must not be {@code null}!
67       * @param value the value of the new argument.
68       * @param <T> the type of the argument.
69       * @param <V> the type of the value of the argument.
70       * @return a new argument of the given type with the given value.
71       */
72      public static <T, V extends T> Argument<T> argument( Class<T> type, V value )
73      {
74          type = checkNotNull( type, "type must be specified (while value is nullable)" );
75          if ( value != null )
76          {
77              // this should never happen since the compiler prevents it. Check it anyway...
78              checkArgument( isAssignmentCompatible( type, value.getClass() ),
79                             "value type %s does not match the given type %s",
80                             value.getClass().getName(),
81                             type.getName() );
82          }
83          return new Argument<T>( type, value );
84      }
85  
86      /**
87       * Determines the types of the given arguments.
88       *
89       * @param arguments the arguments to determine the types of. None must be {@code null}!
90       * @return an array of {@code Class} objects representing the types of the
91       *         given arguments. The first {@code class} object represents the
92       *         type of the first argument and so on.
93       */
94      static Class<?>[] getParameterTypes( Argument<?>...arguments )
95      {
96          int argumentsLength = arguments.length;
97          Class<?>[] parameterTypes = new Class[argumentsLength];
98          for ( int i = 0; i < argumentsLength; i++ )
99          {
100             parameterTypes[i] = arguments[i].getType();
101         }
102         return parameterTypes;
103     }
104 
105     /**
106      * Determines the objects of the given arguments.
107      *
108      * @param arguments the arguments to determine the types of. None must be {@code null}!
109      * @return an array of {@code Object}s representing the values of the given arguments.
110      */
111     static Object[] getParameters( Argument<?>...arguments )
112     {
113         int argumentsLength = arguments.length;
114         Object[] parameters = new Object[argumentsLength];
115         for ( int i = 0; i < argumentsLength; i++ )
116         {
117             parameters[i] = arguments[i].getValue();
118         }
119         return parameters;
120     }
121 
122     private final Class<T> type;
123 
124     private final T value;
125 
126     private Argument( Class<T> type, T value )
127     {
128         this.type = type;
129         this.value = value;
130     }
131 
132     /**
133      * Returns the argument's type. Note that the type returned maybe a super type of the actual type of the value
134      * returned by {@link #getValue()} depending on how the argument was created. For example:
135      * </br>{@code argument( Number.class, Integer.valueOf( 4 ) );}</br>
136      * will create an argument with an Integer as Value but Number.class as type.
137      *
138      * @return the argument's type
139      */
140     public Class<T> getType()
141     {
142         return type;
143     }
144 
145     /**
146      * Returns the value of the argument. Maybe {@code null} if this is a null argument.
147      *
148      * @return the value of the argument.
149      */
150     public T getValue()
151     {
152         return value;
153     }
154 
155 }