blob: d4543a2ac0bda5212265745947075a82a9177ae3 [file] [log] [blame]
package com.fasterxml.jackson.databind.type;
import java.lang.reflect.Array;
import com.fasterxml.jackson.databind.JavaType;
/**
* Array types represent Java arrays, both primitive and object valued.
* Further, Object-valued arrays can have element type of any other
* legal {@link JavaType}.
*/
public final class ArrayType
extends TypeBase
{
private static final long serialVersionUID = 1L;
/**
* Type of elements in the array.
*/
protected final JavaType _componentType;
/**
* We will also keep track of shareable instance of empty array,
* since it usually needs to be constructed any way; and because
* it is essentially immutable and thus can be shared.
*/
protected final Object _emptyArray;
protected ArrayType(JavaType componentType, TypeBindings bindings, Object emptyInstance,
Object valueHandler, Object typeHandler, boolean asStatic)
{
// No super-class, interfaces, for now
super(emptyInstance.getClass(), bindings, null, null,
componentType.hashCode(),
valueHandler, typeHandler, asStatic);
_componentType = componentType;
_emptyArray = emptyInstance;
}
public static ArrayType construct(JavaType componentType, TypeBindings bindings) {
return construct(componentType, bindings, null, null);
}
public static ArrayType construct(JavaType componentType, TypeBindings bindings,
Object valueHandler, Object typeHandler) {
// Figuring out raw class for generic array is actually bit tricky...
Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0);
return new ArrayType(componentType, bindings, emptyInstance, valueHandler, typeHandler, false);
}
@Override
public JavaType withContentType(JavaType contentType) {
Object emptyInstance = Array.newInstance(contentType.getRawClass(), 0);
return new ArrayType(contentType, _bindings, emptyInstance,
_valueHandler, _typeHandler, _asStatic);
}
@Override
public ArrayType withTypeHandler(Object h)
{
if (h == _typeHandler) {
return this;
}
return new ArrayType(_componentType, _bindings, _emptyArray, _valueHandler, h, _asStatic);
}
@Override
public ArrayType withContentTypeHandler(Object h)
{
if (h == _componentType.<Object>getTypeHandler()) {
return this;
}
return new ArrayType(_componentType.withTypeHandler(h), _bindings, _emptyArray,
_valueHandler, _typeHandler, _asStatic);
}
@Override
public ArrayType withValueHandler(Object h) {
if (h == _valueHandler) {
return this;
}
return new ArrayType(_componentType, _bindings, _emptyArray, h, _typeHandler,_asStatic);
}
@Override
public ArrayType withContentValueHandler(Object h) {
if (h == _componentType.<Object>getValueHandler()) {
return this;
}
return new ArrayType(_componentType.withValueHandler(h), _bindings, _emptyArray,
_valueHandler, _typeHandler, _asStatic);
}
@Override
public ArrayType withStaticTyping() {
if (_asStatic) {
return this;
}
return new ArrayType(_componentType.withStaticTyping(), _bindings,
_emptyArray, _valueHandler, _typeHandler, true);
}
/*
/**********************************************************
/* Methods for narrowing conversions
/**********************************************************
*/
/**
* Handling of narrowing conversions for arrays is trickier: for now,
* it is not even allowed.
*/
@Override
@Deprecated // since 2.7
protected JavaType _narrow(Class<?> subclass) {
return _reportUnsupported();
}
// Should not be called, as array types in Java are not extensible; but
// let's not freak out even if it is called?
@Override
public JavaType refine(Class<?> contentClass, TypeBindings bindings,
JavaType superClass, JavaType[] superInterfaces) {
return null;
}
private JavaType _reportUnsupported() {
throw new UnsupportedOperationException("Can not narrow or widen array types");
}
/*
/**********************************************************
/* Overridden methods
/**********************************************************
*/
@Override
public boolean isArrayType() { return true; }
/**
* For some odd reason, modifiers for array classes would
* claim they are abstract types. Not so, at least for our
* purposes.
*/
@Override
public boolean isAbstract() { return false; }
/**
* For some odd reason, modifiers for array classes would
* claim they are abstract types. Not so, at least for our
* purposes.
*/
@Override
public boolean isConcrete() { return true; }
@Override
public boolean hasGenericTypes() {
// arrays are not parameterized, but element type may be:
return _componentType.hasGenericTypes();
}
/*
/**********************************************************
/* Public API
/**********************************************************
*/
@Override
public boolean isContainerType() { return true; }
@Override
public JavaType getContentType() { return _componentType; }
@Override
public Object getContentValueHandler() {
return _componentType.getValueHandler();
}
@Override
public Object getContentTypeHandler() {
return _componentType.getTypeHandler();
}
@Override
public StringBuilder getGenericSignature(StringBuilder sb) {
sb.append('[');
return _componentType.getGenericSignature(sb);
}
@Override
public StringBuilder getErasedSignature(StringBuilder sb) {
sb.append('[');
return _componentType.getErasedSignature(sb);
}
/*
/**********************************************************
/* Standard methods
/**********************************************************
*/
@Override
public String toString()
{
return "[array type, component type: "+_componentType+"]";
}
@Override
public boolean equals(Object o)
{
if (o == this) return true;
if (o == null) return false;
if (o.getClass() != getClass()) return false;
ArrayType other = (ArrayType) o;
return _componentType.equals(other._componentType);
}
}