1 package com.fasterxml.jackson.databind.type;
2
3 import java.lang.reflect.Array;
4
5 import com.fasterxml.jackson.databind.JavaType;
6
7 /**
8  * Array types represent Java arrays, both primitive and object valued.
9  * Further, Object-valued arrays can have element type of any other
10  * legal {@link JavaType}.
11  */

12 public final class ArrayType
13     extends TypeBase
14 {
15     private static final long serialVersionUID = 1L;
16
17     /**
18      * Type of elements in the array.
19      */

20     protected final JavaType _componentType;
21
22     /**
23      * We will also keep track of shareable instance of empty array,
24      * since it usually needs to be constructed any way; and because
25      * it is essentially immutable and thus can be shared.
26      */

27     protected final Object _emptyArray;
28
29     protected ArrayType(JavaType componentType, TypeBindings bindings, Object emptyInstance,
30             Object valueHandler, Object typeHandler, boolean asStatic)
31     {
32         // No super-class, interfaces, for now
33         super(emptyInstance.getClass(), bindings, nullnull,
34                 componentType.hashCode(),
35                 valueHandler, typeHandler, asStatic);
36         _componentType = componentType;
37         _emptyArray = emptyInstance;
38     }
39
40     public static ArrayType construct(JavaType componentType, TypeBindings bindings) {
41         return construct(componentType, bindings, nullnull);
42     }
43
44     public static ArrayType construct(JavaType componentType, TypeBindings bindings,
45             Object valueHandler, Object typeHandler) {
46         // Figuring out raw class for generic array is actually bit tricky...
47         Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0);
48         return new ArrayType(componentType, bindings, emptyInstance, valueHandler, typeHandler, false);
49     }
50
51     @Override
52     public JavaType withContentType(JavaType contentType) {
53         Object emptyInstance = Array.newInstance(contentType.getRawClass(), 0);
54         return new ArrayType(contentType, _bindings, emptyInstance,
55                 _valueHandler, _typeHandler, _asStatic);
56     }
57
58     @Override
59     public ArrayType withTypeHandler(Object h)
60     {
61         if (h == _typeHandler) {
62             return this;
63         }
64         return new ArrayType(_componentType, _bindings, _emptyArray, _valueHandler, h, _asStatic);
65     }
66
67     @Override
68     public ArrayType withContentTypeHandler(Object h)
69     {
70         if (h == _componentType.<Object>getTypeHandler()) {
71             return this;
72         }
73         return new ArrayType(_componentType.withTypeHandler(h), _bindings, _emptyArray,
74                 _valueHandler, _typeHandler, _asStatic);
75     }
76
77     @Override
78     public ArrayType withValueHandler(Object h) {
79         if (h == _valueHandler) {
80             return this;
81         }
82         return new ArrayType(_componentType, _bindings, _emptyArray, h, _typeHandler,_asStatic);
83     }
84
85     @Override
86     public ArrayType withContentValueHandler(Object h) {
87         if (h == _componentType.<Object>getValueHandler()) {
88             return this;
89         }
90         return new ArrayType(_componentType.withValueHandler(h), _bindings, _emptyArray,
91                 _valueHandler, _typeHandler, _asStatic);
92     }
93
94     @Override
95     public ArrayType withStaticTyping() {
96         if (_asStatic) {
97             return this;
98         }
99         return new ArrayType(_componentType.withStaticTyping(), _bindings,
100                 _emptyArray, _valueHandler, _typeHandler, true);
101     }
102
103     /*
104     /**********************************************************
105     /* Methods for narrowing conversions
106     /**********************************************************
107      */

108
109     /**
110      * Handling of narrowing conversions for arrays is trickier: for now,
111      * it is not even allowed.
112      */

113     @Override
114     @Deprecated // since 2.7
115     protected JavaType _narrow(Class<?> subclass) {
116         return _reportUnsupported();
117     }
118
119     // Should not be called, as array types in Java are not extensible; but
120     // let's not freak out even if it is called?
121     @Override
122     public JavaType refine(Class<?> contentClass, TypeBindings bindings,
123             JavaType superClass, JavaType[] superInterfaces) {
124         return null;
125     }
126
127     private JavaType _reportUnsupported() {
128         throw new UnsupportedOperationException("Cannot narrow or widen array types");
129     }
130
131     /*
132     /**********************************************************
133     /* Overridden methods
134     /**********************************************************
135      */

136
137     @Override
138     public boolean isArrayType() { return true; }
139     
140     /**
141      * For some odd reason, modifiers for array classes would
142      * claim they are abstract types. Not so, at least for our
143      * purposes.
144      */

145     @Override
146     public boolean isAbstract() { return false; }
147
148     /**
149      * For some odd reason, modifiers for array classes would
150      * claim they are abstract types. Not so, at least for our
151      * purposes.
152      */

153     @Override
154     public boolean isConcrete() { return true; }
155
156     @Override
157     public boolean hasGenericTypes() {
158         // arrays are not parameterized, but element type may be:
159         return _componentType.hasGenericTypes();
160     }
161
162     /*
163     /**********************************************************
164     /* Public API
165     /**********************************************************
166      */

167
168     @Override
169     public boolean isContainerType() { return true; }
170
171     @Override
172     public JavaType getContentType() { return  _componentType; }
173
174     @Override
175     public Object getContentValueHandler() {
176         return _componentType.getValueHandler();
177     }
178
179     @Override
180     public Object getContentTypeHandler() {
181         return _componentType.getTypeHandler();
182     }
183
184     @Override
185     public boolean hasHandlers() {
186         return super.hasHandlers() || _componentType.hasHandlers();
187     }
188     
189     @Override
190     public StringBuilder getGenericSignature(StringBuilder sb) {
191         sb.append('[');
192         return _componentType.getGenericSignature(sb);
193     }
194
195     @Override
196     public StringBuilder getErasedSignature(StringBuilder sb) {
197         sb.append('[');
198         return _componentType.getErasedSignature(sb);
199     }
200     
201     /*
202     /**********************************************************
203     /* Standard methods
204     /**********************************************************
205      */

206
207     @Override
208     public String toString()
209     {
210         return "[array type, component type: "+_componentType+"]";
211     }
212
213     @Override
214     public boolean equals(Object o)
215     {
216         if (o == thisreturn true;
217         if (o == nullreturn false;
218         if (o.getClass() != getClass()) return false;
219
220         ArrayType other = (ArrayType) o;
221         return _componentType.equals(other._componentType);
222     }
223 }
224