/**
* Copyright 2011-2017 Asakusa Framework Team.
*
* Licensed 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 com.asakusafw.operator.description;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* Represents primitive types and void type.
*/
public class BasicTypeDescription extends ReifiableTypeDescription {
private final BasicTypeKind basicTypeKind;
/**
* Creates a new instance.
* @param basicTypeKind the type kind
*/
public BasicTypeDescription(BasicTypeKind basicTypeKind) {
this.basicTypeKind = Objects.requireNonNull(basicTypeKind);
}
/**
* Returns an instance.
* @param aClass the reflective object
* @return the related instance
*/
public static BasicTypeDescription of(Class<?> aClass) {
if (aClass.isPrimitive() == false) {
throw new IllegalArgumentException(MessageFormat.format(
"must be basic type: {0}", //$NON-NLS-1$
aClass.getName()));
}
BasicTypeDescription.BasicTypeKind kind = BasicTypeDescription.BasicTypeKind.of(aClass);
return new BasicTypeDescription(kind);
}
@Override
public TypeKind getTypeKind() {
return TypeKind.BASIC;
}
@Override
public BasicTypeDescription getErasure() {
return this;
}
/**
* Returns the basic type kind.
* @return the basic type kind
*/
public BasicTypeKind getBasicTypeKind() {
return basicTypeKind;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + basicTypeKind.hashCode();
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
BasicTypeDescription other = (BasicTypeDescription) obj;
if (basicTypeKind != other.basicTypeKind) {
return false;
}
return true;
}
@Override
public String toString() {
return basicTypeKind.getKeyword();
}
/**
* Represents a kind of {@link BasicTypeDescription}.
*/
public enum BasicTypeKind {
/**
* {@code void} type.
*/
VOID('V', void.class, Void.class),
/**
* {@code int} type.
*/
INT('I', int.class, Integer.class),
/**
* {@code long} type.
*/
LONG('J', long.class, Long.class),
/**
* {@code float} type.
*/
FLOAT('F', float.class, Float.class),
/**
* {@code double} type.
*/
DOUBLE('D', double.class, Double.class),
/**
* {@code short} type.
*/
SHORT('S', short.class, Short.class),
/**
* {@code char} type.
*/
CHAR('C', char.class, Character.class),
/**
* {@code byte} type.
*/
BYTE('B', byte.class, Byte.class),
/**
* {@code boolean} type.
*/
BOOLEAN('Z', boolean.class, Boolean.class),
;
private Class<?> reflectiveObject;
private Class<?> wrapperType;
BasicTypeKind(char descriptor, Class<?> reflectiveObject, Class<?> wrapperType) {
assert reflectiveObject != null;
assert reflectiveObject.isPrimitive();
this.reflectiveObject = reflectiveObject;
this.wrapperType = wrapperType;
}
/**
* Returns the reflective object.
* @return the reflective object
*/
public Class<?> getReflectiveObject() {
return reflectiveObject;
}
/**
* Returns the corresponded wrapper type.
* @return the wrapper type
*/
public Class<?> getWrapperType() {
return wrapperType;
}
/**
* Returns the constant from its reflective object.
* @param aClass the reflective object
* @return the constant, or {@code null} if it is not defined
*/
public static BasicTypeKind of(Class<?> aClass) {
return ClassToBasicTypeKind.get(aClass);
}
/**
* Returns the keyword of this basic type.
* @return the keyword
*/
public String getKeyword() {
return name().toLowerCase();
}
/**
* Returns the constant from its keyword.
* @param keyword the basic type keyword
* @return the constant, or {@code null} if it is not defined
*/
public static BasicTypeKind of(String keyword) {
return KeywordToBasicTypeKind.get(keyword);
}
@Override
public String toString() {
return getKeyword();
}
private static class ClassToBasicTypeKind {
private static final Map<Class<?>, BasicTypeKind> REVERSE_DICTIONARY;
static {
Map<Class<?>, BasicTypeKind> map = new HashMap<>();
for (BasicTypeKind elem : BasicTypeKind.values()) {
map.put(elem.getReflectiveObject(), elem);
}
REVERSE_DICTIONARY = Collections.unmodifiableMap(map);
}
static BasicTypeKind get(Class<?> key) {
return REVERSE_DICTIONARY.get(key);
}
}
private static class KeywordToBasicTypeKind {
private static final Map<String, BasicTypeKind> REVERSE_DICTIONARY;
static {
Map<String, BasicTypeKind> map = new HashMap<>();
for (BasicTypeKind elem : BasicTypeKind.values()) {
map.put(elem.getKeyword(), elem);
}
REVERSE_DICTIONARY = Collections.unmodifiableMap(map);
}
static BasicTypeKind get(String key) {
return REVERSE_DICTIONARY.get(key);
}
}
}
}