/**
   * Get the shortest possible name of the a class. If there is no conflict, the class is first
   * imported, and only the simple class is returned; otherwise, the its full name is returned.
   *
   * @param name The full class name. It must not be the name of an array type.
   * @param state The state of the type analyzer.
   * @param root The root of the AST. If there is no conflict and the class has not been imported
   *     yet, a new {@link ImportDeclaration} is added to it.
   * @return The shortest possible class name.
   */
  private static String _getNonarrayClassName(
      String name, TypeAnalyzerState state, CompilationUnit root) {
    LocalClassLoader loader = state.getClassLoader();
    int lastDot = name.lastIndexOf('.');
    String packageName = (lastDot == -1) ? "" : name.substring(0, lastDot);
    String className = name.substring(lastDot + 1);
    String simpleName;
    int lastSeparator = lastIndexOf(name, new char[] {'.', '$'});

    if (lastSeparator == -1) {
      return name;
    } else {
      simpleName = name.substring(lastSeparator + 1);
    }

    String currentClassName = state.getCurrentClass().getName();

    if (name.equals(currentClassName)) {
      return simpleName;
    } else {
      int dollarPos = currentClassName.length();

      while (dollarPos >= 0) {
        String baseName = currentClassName.substring(0, dollarPos) + "$";

        if (name.startsWith(baseName)) {
          return name.substring(baseName.length());
        }

        dollarPos = currentClassName.lastIndexOf('$', dollarPos - 1);
      }
    }

    Iterator importedClasses = loader.getImportedClasses().iterator();

    while (importedClasses.hasNext()) {
      ClassImport importedClass = (ClassImport) importedClasses.next();

      if (importedClass.getPackageName().equals(packageName)
          && importedClass.getClassName().equals(className)) {
        // Already imported.
        return simpleName;
      } else {
        String importedName = importedClass.getClassName();
        int lastDollar = importedName.lastIndexOf('$');

        if ((lastDollar == -1) && importedName.equals(simpleName)) {
          return name;
        } else if ((lastDollar >= 0) && importedName.substring(lastDollar + 1).equals(simpleName)) {
          return name;
        }
      }
    }

    Iterator importedPackages = loader.getImportedPackages().iterator();

    while (importedPackages.hasNext()) {
      String importedPackage = (String) importedPackages.next();

      if (importedPackage.equals(packageName)) { // Already imported.
        return simpleName;
      } else {
        try {
          // Test if a class with the same name exists in the
          // package.
          loader.loadClass(importedPackage + "." + simpleName);

          // If exists, conflict.
          return name;
        } catch (ClassNotFoundException e) {
        }
      }
    }

    AST ast = root.getAST();
    ImportDeclaration declaration = ast.newImportDeclaration();
    declaration.setName(createName(ast, name));
    root.imports().add(declaration);
    loader.importClass(name);
    return simpleName;
  }
  @SuppressWarnings("unchecked")
  @Before
  public void setUp() {
    manager = ModelManager.getInstance();
    manager.clearModel();

    AST ast2 = AST.newAST(AST.JLS3);
    CompilationUnit cu2 = ast2.newCompilationUnit();
    PackageDeclaration pack2 = ast2.newPackageDeclaration();
    pack2.setName(ast2.newName("be.ac.ua.test.otherpack"));
    cu2.setPackage(pack2);
    TypeDeclaration type2 = ast2.newTypeDeclaration();
    type2.setName(ast2.newSimpleName("Foo"));

    cu2.types().add(type2); // created mock compilationunit containing package and class

    PackageRecorder prec2 = new PackageRecorder(pack2);
    prec2.storeChange(new Add()); // store the package addition
    ClassRecorder crec2 = new ClassRecorder(type2);
    declaredclassadd = new Add();
    crec2.storeChange(declaredclassadd);

    AST ast = AST.newAST(AST.JLS3);
    CompilationUnit cu = ast.newCompilationUnit();
    PackageDeclaration pack = ast.newPackageDeclaration();
    pack.setName(ast.newName(packname));
    cu.setPackage(pack);
    TypeDeclaration type = ast.newTypeDeclaration();
    type.setName(ast.newSimpleName(classname));

    cu.types().add(type);

    PackageRecorder prec = new PackageRecorder(pack);
    prec.storeChange(new Add()); // store the package addition
    ClassRecorder crec = new ClassRecorder(type);
    classadd = new Add();
    crec.storeChange(classadd);

    // Class and package created and changes logged, now create the Field.

    VariableDeclarationFragment frag1 = ast.newVariableDeclarationFragment();
    frag1.setName(ast.newSimpleName(intfieldname));
    FieldDeclaration field = ast.newFieldDeclaration(frag1);
    field.setType(ast.newPrimitiveType(PrimitiveType.INT)); // field has type int
    type.bodyDeclarations().add(field);

    VariableDeclarationFragment frag2 = ast.newVariableDeclarationFragment();
    frag2.setName(ast.newSimpleName(fieldname));
    FieldDeclaration field2 = ast.newFieldDeclaration(frag2);
    field2.setType(ast.newSimpleType(ast.newName(declaredTypeName))); // field has type Foo
    type.bodyDeclarations().add(field2);

    VariableDeclarationFragment frag3 = ast.newVariableDeclarationFragment();
    frag3.setName(ast.newSimpleName(field3Name));
    FieldDeclaration field3 = ast.newFieldDeclaration(frag3);
    field3.setType(ast.newSimpleType(ast.newName("Foo"))); // field has type Foo
    type.bodyDeclarations().add(field3);

    ImportDeclaration imp = ast.newImportDeclaration();
    imp.setName(ast.newName(declaredTypeName));
    cu.imports().add(imp);

    // created mock compilationunit containing package and class

    recorder1 = new FieldRecorder(field);
    recorder2 = new FieldRecorder(field2);
    recorder3 = new FieldRecorder(field3);
  }