package org.etk.model.apt; import java.util.List; import org.etk.model.apt.FormatterStyle; import org.etk.reflect.api.ArrayTypeInfo; import org.etk.reflect.api.ClassTypeInfo; import org.etk.reflect.api.ParameterizedTypeInfo; import org.etk.reflect.api.SimpleTypeInfo; import org.etk.reflect.api.TypeInfo; import org.etk.reflect.api.TypeVariableInfo; import org.etk.reflect.api.VoidTypeInfo; import org.etk.reflect.api.WildcardTypeInfo; public class TypeFormatter { /** . */ private final ClassTypeInfo context; /** . */ private final FormatterStyle style; /** . */ private final StringBuilder s; public TypeFormatter(ClassTypeInfo context, FormatterStyle style, StringBuilder s) { this.context = context; this.style = style; this.s = s; } public void format(TypeInfo ti) { format(ti, false); } private void format(TypeInfo ti, boolean fromArray) { if (ti instanceof ClassTypeInfo) { format((ClassTypeInfo)ti, fromArray); } else if (ti instanceof ParameterizedTypeInfo) { format((ParameterizedTypeInfo)ti, fromArray); } else if (ti instanceof TypeVariableInfo) { format((TypeVariableInfo)ti, fromArray); } else if (ti instanceof ArrayTypeInfo) { format((ArrayTypeInfo)ti, fromArray); } else if (ti instanceof WildcardTypeInfo) { format((WildcardTypeInfo)ti, fromArray); } else { throw new UnsupportedOperationException(); } } private void format(ClassTypeInfo cti, boolean fromArray) { if (cti instanceof VoidTypeInfo) { switch (style) { case CAST: case TYPE_PARAMETER: throw new AssertionError(); case RETURN_TYPE: case LITERAL: s.append("void"); break; } } else { switch (style) { case CAST: if (!fromArray) { if (cti instanceof SimpleTypeInfo) { switch (((SimpleTypeInfo)cti).getLiteralType()) { case INT: s.append("java.lang.Integer"); break; case BOOLEAN: s.append("java.lang.Boolean"); break; case LONG: s.append("java.lang.Long"); break; case DOUBLE: s.append("java.lang.Double"); break; case FLOAT: s.append("java.lang.Float"); break; default: throw new UnsupportedOperationException(); } } else { formatCompileTimeName(cti); } } else { formatCompileTimeName(cti); } break; case LITERAL: case TYPE_PARAMETER: case RETURN_TYPE: formatCompileTimeName(cti); break; } } } private void formatCompileTimeName(ClassTypeInfo cti) { ClassTypeInfo enclosing = cti.getEnclosing(); if (enclosing != null) { formatCompileTimeName(enclosing); s.append('.'); String classElementName = cti.getSimpleName().substring(enclosing.getSimpleName().length() + 1); s.append(classElementName); } else { s.append(cti.getName()); } } private void format(ParameterizedTypeInfo pti, boolean fromArray) { TypeInfo rawType = pti.getRawType(); format(rawType); } private void format(TypeVariableInfo tvi, boolean fromArray) { switch (style) { case LITERAL: format(tvi.getBounds().get(0)); break; case TYPE_PARAMETER: case RETURN_TYPE: case CAST: { TypeInfo resolved = context.resolve(tvi); if (resolved instanceof TypeVariableInfo) { TypeVariableInfo resolvedTVI = (TypeVariableInfo)resolved; List<TypeInfo> bounds = resolvedTVI.getBounds(); if (bounds.size() != 1) { throw new UnsupportedOperationException("Need to add support for multiple bounds"); } TypeInfo bound = bounds.get(0); format(bound); } else { format(resolved); } break; } } } private void format(ArrayTypeInfo ati, boolean fromArray) { switch (style) { case LITERAL: case TYPE_PARAMETER: case RETURN_TYPE: case CAST: { TypeInfo componentTI = ati.getComponentType(); format(componentTI, true); s.append("[]"); break; } } } private void format(WildcardTypeInfo wti, boolean fromArray) { // Do nothing } }