package org.dresdenocl.modelinstancetype.java.internal.util;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.dresdenocl.essentialocl.EssentialOclPlugin;
import org.dresdenocl.essentialocl.types.CollectionType;
import org.dresdenocl.model.IModel;
import org.dresdenocl.model.ModelConstants;
import org.dresdenocl.modelinstancetype.java.JavaModelInstanceTypePlugin;
import org.dresdenocl.pivotmodel.PrimitiveType;
import org.dresdenocl.pivotmodel.PrimitiveTypeKind;
import org.dresdenocl.pivotmodel.Type;
/**
* <p>
* This {@link Class} provides some static method that can be used to convert
* the names of Java {@link Class}es into qualified {@link Type} names and vice
* versa.
* </p>
*
* @author Claas Wilke
*/
public class JavaModelInstanceTypeUtility {
/**
* <p>
* This method checks, if a given {@link java.lang.reflect.Type} conforms to
* a given {@link Type}.
* </p>
*
* @param reflectionType
* The {@link java.lang.reflect.Type}.
* @param type
* The {@link Type}.
* @return <code>true</code>, if the types conform. Else <code>false</code>.
*/
public static boolean conformsTypeToType(
java.lang.reflect.Type reflectionType, Type type) {
boolean result;
/* If the reflective type is a class, compare the qualified names. */
if (reflectionType instanceof Class<?>) {
Class<?> clazz;
clazz = (Class<?>) reflectionType;
if (clazz.isArray()) {
result = conformsTypeToType(clazz.getComponentType(), type);
}
else {
if (type instanceof PrimitiveType) {
result = toQualifiedNameList(clazz.getCanonicalName())
.equals(
Arrays
.asList(new String[] { ((PrimitiveType) type)
.getKind().getName() }));
}
else if (clazz.getCanonicalName().equals("void")) {
result = type.equals(EssentialOclPlugin
.getOclLibraryProvider().getOclLibrary()
.getOclVoid());
}
else {
List<String> qualifiedClassName = toQualifiedNameList(clazz
.getCanonicalName());
List<String> qualifiedTypeName = type
.getQualifiedNameList();
result = qualifiedClassName.equals(qualifiedTypeName);
}
}
}
/* If the type is an array, compare its component type with the type. */
else if (reflectionType instanceof GenericArrayType) {
GenericArrayType genericArrayType;
genericArrayType = (GenericArrayType) reflectionType;
result = conformsTypeToType(genericArrayType
.getGenericComponentType(), type);
}
else if (reflectionType instanceof ParameterizedType) {
ParameterizedType parameterizedType;
parameterizedType = (ParameterizedType) reflectionType;
/* Check if exactly one generic parameter is set. */
if (parameterizedType.getActualTypeArguments().length == 1) {
if (type instanceof CollectionType) {
// FIXME Check specific collection type here.
result = conformsTypeToType(parameterizedType
.getActualTypeArguments()[0], ((CollectionType) type).getElementType());
}
else {
result = false;
}
}
/*
* Else a ParameterizedType can contain more than one classes. Thus,
* the result is not unambiguous.
*/
else {
result = false;
}
}
else if (reflectionType instanceof TypeVariable<?>) {
/*
* A TypeVariable can contain more than one classes. Thus, the
* result is not unambiguous.
*/
result = false;
}
else if (reflectionType instanceof WildcardType) {
/*
* A WildcardType can contain more than one classes. Thus, the
* result is not unambiguous.
*/
result = false;
}
/* No Type of the Java standard library. Cannot compare. */
else {
result = false;
}
return result;
}
/**
* <p>
* Converts a given {@link List} of {@link String}s that represent a
* {@link Type}'s qualified name into a Java canonical name.
* </p>
*
* @param qualifiedNameList
* The given qualified name {@link List}.
* @return The converte canonical name.
*/
public static String toCanonicalName(List<String> qualifiedNameList) {
StringBuffer resultBuffer;
resultBuffer = new StringBuffer();
/* Copy the list to avoid side effects. */
qualifiedNameList = new ArrayList<String>(qualifiedNameList);
/* Probably remove the root package from the name. */
if (qualifiedNameList.get(0).equals(ModelConstants.ROOT_PACKAGE_NAME)) {
qualifiedNameList.remove(0);
}
// no else.
for (String aPackageName : qualifiedNameList) {
if (resultBuffer.length() > 0) {
resultBuffer.append(".");
}
// no else.
resultBuffer.append(aPackageName);
}
return resultBuffer.toString();
}
/**
* <p>
* Converts a given Java canonical name into a {@link List} of
* {@link String}s representing a qualified name of an {@link IModel}'s
* {@link Type}.
* </p>
*
* @param canonicalName
* The canonical name that shall be converted.
* @return The qualified name as a {@link List} of {@link String}s.
*/
public static List<String> toQualifiedNameList(String canonicalName) {
List<String> result;
/* Check for primitive types. */
result = toPrimitiveQualifiedName(canonicalName);
if (result == null) {
result = new ArrayList<String>(Arrays.asList(canonicalName
.split("[.]")));
result.add(0, ModelConstants.ROOT_PACKAGE_NAME);
}
// no else.
return result;
}
/**
* <p>
* A helper method that converts a given canonical name of a java
* {@link Class} into the qualified name (as a {@link List} of
* {@link String} s) if the given {@link Class} can be mapped to a
* {@link PrimitiveType} of any {@link PrimitiveTypeKind}. Else
* <code>null</code> is returned.
* </p>
*
* @param canonicalName
* The canonical name that shall be converted.
* @return The qualified name of a {@link PrimitiveType} or
* <code>null</code>.
*/
private static List<String> toPrimitiveQualifiedName(String canonicalName) {
List<String> result;
result = null;
/* Check for the void type. */
if (canonicalName.equalsIgnoreCase(PrimitiveTypeKind.VOID.toString())) {
result = new ArrayList<String>();
result.add(PrimitiveTypeKind.VOID.toString());
}
/* Probably check for a Boolean type. */
if (result == null) {
for (Class<?> clazz : JavaModelInstanceTypePlugin.BOOLEAN_CLASSES) {
if (canonicalName.equals(clazz.getCanonicalName())) {
result = new ArrayList<String>();
result.add(PrimitiveTypeKind.BOOLEAN.toString());
break;
}
// no else.
}
}
// no else.
/* Probably check for an Integer type. */
if (result == null) {
for (Class<?> clazz : JavaModelInstanceTypePlugin.INTEGER_CLASSES) {
if (canonicalName.equals(clazz.getCanonicalName())) {
result = new ArrayList<String>();
result.add(PrimitiveTypeKind.INTEGER.toString());
break;
}
// no else.
}
}
// no else.
/* Probably check for a Real type. */
if (result == null) {
for (Class<?> clazz : JavaModelInstanceTypePlugin.REAL_CLASSES) {
if (canonicalName.equals(clazz.getCanonicalName())) {
result = new ArrayList<String>();
result.add(PrimitiveTypeKind.REAL.toString());
break;
}
// no else.
}
}
// no else.
/* Probably check for a String type. */
if (result == null) {
for (Class<?> clazz : JavaModelInstanceTypePlugin.STRING_CLASSES) {
if (canonicalName.equals(clazz.getCanonicalName())) {
result = new ArrayList<String>();
result.add(PrimitiveTypeKind.STRING.toString());
break;
}
// no else.
}
}
// no else.
return result;
}
}