org.apache.wink.common.internal.type.ArrayType Maven / Gradle / Ivy
The newest version!
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.wink.common.internal.type;
import java.lang.reflect.Array;
/**
* 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 {
/**
* Type of elements in the array.
*/
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.
*/
final Object _emptyArray;
private ArrayType(JavaType componentType, Object emptyInstance) {
super(emptyInstance.getClass(), componentType.hashCode());
_componentType = componentType;
_emptyArray = emptyInstance;
}
public static ArrayType construct(JavaType componentType) {
/* This is bit messy: there is apparently no other way to
* reconstruct actual concrete/raw array class from component
* type, than to construct an instance, get class (same is
* true for GenericArracyType as well; hence we won't bother
* passing that in).
*/
Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0);
return new ArrayType(componentType, emptyInstance);
}
// Since 1.7:
@Override
public ArrayType withTypeHandler(Object h) {
ArrayType newInstance = new ArrayType(_componentType, _emptyArray);
newInstance._typeHandler = h;
return newInstance;
}
// Since 1.7:
@Override
public ArrayType withContentTypeHandler(Object h) {
return new ArrayType(_componentType.withTypeHandler(h), _emptyArray);
}
@Override
protected String buildCanonicalName() {
return _class.getName();
}
/*
/**********************************************************
/* Methods for narrowing conversions
/**********************************************************
*/
/**
* Handling of narrowing conversions for arrays is trickier: for now,
* it is not even allowed.
*/
@Override
protected JavaType _narrow(Class subclass) {
/* Ok: need a bit of indirection here. First, must replace component
* type (and check that it is compatible), then re-construct.
*/
if (!subclass.isArray()) { // sanity check, should never occur
throw new IllegalArgumentException("Incompatible narrowing operation: trying to narrow " + toString()
+ " to class "
+ subclass.getName());
}
/* Hmmh. This is an awkward back reference... but seems like the
* only simple way to do it.
*/
Class newCompClass = subclass.getComponentType();
JavaType newCompType = TypeFactory.type(newCompClass);
return construct(newCompType);
}
/**
* For array types, both main type and content type can be modified;
* but ultimately they are interchangeable.
*/
@Override
public JavaType narrowContentsBy(Class contentClass) {
// Can do a quick check first:
if (contentClass == _componentType.getRawClass()) {
return this;
}
JavaType newComponentType = _componentType.narrowBy(contentClass);
return construct(newComponentType).copyHandlers(this);
}
/*
/**********************************************************
/* 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();
}
/**
* Not sure what symbolic name is used internally, if any;
* let's follow naming of Collection types here.
* Should not really matter since array types have no
* super types.
*/
@Override
public String containedTypeName(int index) {
if (index == 0)
return "E";
return null;
}
/*
/**********************************************************
/* Public API
/**********************************************************
*/
@Override
public boolean isContainerType() {
return true;
}
@Override
public JavaType getContentType() {
return _componentType;
}
@Override
public int containedTypeCount() {
return 1;
}
@Override
public JavaType containedType(int index) {
return (index == 0) ? _componentType : null;
}
@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);
}
}