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 }