class TypeTemplatePrinter extends TypeSwitch {

  private String varName;
  private final TemplatePrinter p;

  public void printAssign(String v, Type t) {
    String oldName = varName;
    varName = v;
    t.apply(this);
    varName = oldName;
  }

  public TypeTemplatePrinter(TemplatePrinter p) {
    this.p = p;
  }

  public void setVariableName(String name) {
    this.varName = name;
  }

  private void emit(String rhs) {
    p.println("Type " + varName + " = " + rhs + ';');
  }

  private void emitSpecial(String type, String rhs) {
    p.println(type + ' ' + varName + " = " + rhs + ';');
  }

  @Override
  public void caseAnySubType(AnySubType t) {
    throw new IllegalArgumentException("cannot print this type");
  }

  @Override
  public void caseArrayType(ArrayType t) {<FILL_FUNCTION_BODY>}

  @Override
  public void caseBooleanType(BooleanType t) {
    emit("BooleanType.v()");
  }

  @Override
  public void caseByteType(ByteType t) {
    emit("ByteType.v()");
  }

  @Override
  public void caseCharType(CharType t) {
    emit("CharType.v()");
  }

  @Override
  public void defaultCase(Type t) {
    throw new IllegalArgumentException("cannot print this type");
  }

  @Override
  public void caseDoubleType(DoubleType t) {
    emit("DoubleType.v()");
  }

  @Override
  public void caseErroneousType(ErroneousType t) {
    throw new IllegalArgumentException("cannot print this type");
  }

  @Override
  public void caseFloatType(FloatType t) {
    emit("FloatType.v()");
  }

  @Override
  public void caseIntType(IntType t) {
    emit("IntType.v()");
  }

  @Override
  public void caseLongType(LongType t) {
    emit("LongType.v()");
  }

  @Override
  public void caseNullType(NullType t) {
    emit("NullType.v()");
  }

  @Override
  public void caseRefType(RefType t) {
    emitSpecial("RefType", "RefType.v(\"" + t.getClassName() + "\")");
  }

  @Override
  public void caseShortType(ShortType t) {
    emit("ShortType.v()");
  }

  @Override
  public void caseStmtAddressType(StmtAddressType t) {
    throw new IllegalArgumentException("cannot print this type");
  }

  @Override
  public void caseUnknownType(UnknownType t) {
    throw new IllegalArgumentException("cannot print this type");
  }

  @Override
  public void caseVoidType(VoidType t) {
    emit("VoidType.v()");
  }
}

    printAssign("baseType", t.getElementType());

    p.println("int numDimensions=" + t.numDimensions + ';');

    emit("ArrayType.v(baseType, numDimensions)");
  
<methods>public non-sealed void <init>() ,public void caseAnySubType(soot.AnySubType) ,public void caseArrayType(soot.ArrayType) ,public void caseBooleanType(soot.BooleanType) ,public void caseByteType(soot.ByteType) ,public void caseCharType(soot.CharType) ,public void caseDefault(soot.Type) ,public void caseDoubleType(soot.DoubleType) ,public void caseErroneousType(soot.ErroneousType) ,public void caseFloatType(soot.FloatType) ,public void caseIntType(soot.IntType) ,public void caseLongType(soot.LongType) ,public void caseNullType(soot.NullType) ,public void caseRefType(soot.RefType) ,public void caseShortType(soot.ShortType) ,public void caseStmtAddressType(soot.StmtAddressType) ,public void caseUnknownType(soot.UnknownType) ,public void caseVoidType(soot.VoidType) ,public void defaultCase(soot.Type) ,public java.lang.Object getResult() ,public void setResult(java.lang.Object) <variables>java.lang.Object result