package io.trygvis.container.compiler.model; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import java.util.Collections; import java.util.List; import static java.util.Arrays.asList; import static org.apache.commons.lang.StringUtils.join; public class TypeRef implements Comparable { public static final TypeRef VOID = new TypeRef("void"); public static final TypeRef BOOLEAN = new PrimitiveTypeRef("boolean"); public static final TypeRef BYTE = new PrimitiveTypeRef("byte"); public static final TypeRef SHORT = new PrimitiveTypeRef("short"); public static final TypeRef CHAR = new PrimitiveTypeRef("char"); public static final TypeRef INT = new PrimitiveTypeRef("int"); public static final TypeRef LONG = new PrimitiveTypeRef("long"); public static final TypeRef FLOAT = new PrimitiveTypeRef("float"); public static final TypeRef DOUBLE = new PrimitiveTypeRef("double"); private static class PrimitiveTypeRef extends TypeRef { private PrimitiveTypeRef(String name) { super(name); } } /** * The name of a class used within a class file. Is either the just the name or the fully qualified name. */ public final String plainName; public final String className; public final String fqName; private final boolean primitive; public final boolean array; public final List args; private TypeRef(String fqName, String name, boolean primitive, boolean array, List args) { this.fqName = fqName; this.plainName = name; this.primitive = primitive; this.array = array; this.args = args; int i = this.fqName.lastIndexOf('.'); if (i == -1) { this.className = this.fqName; } else { this.className = this.fqName.substring(i + 1, this.fqName.length()); } } public TypeRef(TypeMirror type) { this(type.toString()); } public TypeRef(Class klass) { this(fqName(klass), fqName(klass), false, klass.isArray(), Collections.emptyList()); } private static String fqName(Class klass) { String name = klass.getCanonicalName(); if (!klass.isArray()) { return name; } return name.substring(0, name.length() - 2); } public TypeRef(String fqName) { this(fqName, fqName, false, false, Collections.emptyList()); } public TypeRef(String fqName, String name, boolean array, List args) { this(fqName, name, false, array, args); } public TypeRef args(List args) { return new TypeRef(fqName, plainName, primitive, array, args); } public boolean isPrimitive() { return primitive; } public boolean inUnnamedPackage() { return fqName.indexOf('.') == -1; } public String packageName() { int i = fqName.lastIndexOf('.'); if (i == -1) { throw new RuntimeException("This type is in the unnamed package: " + toString()); } return fqName.substring(0, i); } public String importName() { return fqName; } public TypeRef args(TypeRef... args) { return args(asList(args)); } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof TypeRef)) return false; TypeRef classRef = (TypeRef) o; return fqName.equals(classRef.fqName) && array == classRef.array; } @Override public int hashCode() { return fqName.hashCode(); } @Override public int compareTo(@SuppressWarnings("NullableProblems") TypeRef o) { return fqName.compareTo(o.fqName); } public String toString() { String s = plainName; if (!args.isEmpty()) { s += "<" + join(args, ", ") + ">"; } if (array) { s += "[]"; } return s; } public static TypeRef find(TypeKind kind) { switch (kind) { case BOOLEAN: return BOOLEAN; case BYTE: return BYTE; case SHORT: return SHORT; case CHAR: return CHAR; case INT: return INT; case LONG: return LONG; case FLOAT: return FLOAT; case DOUBLE: return DOUBLE; } throw new RuntimeException("Unknown kind: " + kind); } }