class NameHolder {
    private final String originalName;
    private String packageName, className;
    private final ArrayList<NameHolder> children;
    private NameHolder parent;
    private boolean isClass;

    public NameHolder(String name, NameHolder parent, boolean isClass) {
      originalName = name;
      className = name;
      packageName = name;

      this.parent = parent;
      this.isClass = isClass;

      children = new ArrayList<NameHolder>();
    }

    public NameHolder get_Parent() {
      return parent;
    }

    public void set_ClassAttr() {
      isClass = true;
    }

    public boolean is_Class() {
      if (children.isEmpty()) {
        return true;
      } else {
        return isClass;
      }
    }

    public boolean is_Package() {
      return !children.isEmpty();
    }

    public String get_PackageName() {
      return packageName;
    }

    public String get_ClassName() {
      return className;
    }

    public void set_PackageName(String packageName) {
      this.packageName = packageName;
    }

    public void set_ClassName(String className) {
      this.className = className;
    }

    public String get_OriginalName() {
      return originalName;
    }

    public ArrayList<NameHolder> get_Children() {
      return children;
    }

    public String get_FixedPackageName() {
      if (parent == null) {
        return "";
      }

      return parent.retrieve_FixedPackageName();
    }

    public String retrieve_FixedPackageName() {<FILL_FUNCTION_BODY>}

    public String get_FixedName(StringTokenizer st, boolean forClass) {
      if (!st.nextToken().equals(originalName)) {
        throw new RuntimeException("Unable to resolve naming.");
      }

      return retrieve_FixedName(st, forClass);
    }

    private String retrieve_FixedName(StringTokenizer st, boolean forClass) {
      if (!st.hasMoreTokens()) {
        if (forClass) {
          return className;
        } else {
          return packageName;
        }
      }

      String subName = st.nextToken();
      Iterator<NameHolder> cit = children.iterator();
      while (cit.hasNext()) {
        NameHolder h = cit.next();

        if (h.get_OriginalName().equals(subName)) {
          if (forClass) {
            return h.retrieve_FixedName(st, forClass);
          } else {
            return packageName + "." + h.retrieve_FixedName(st, forClass);
          }
        }
      }
      throw new RuntimeException("Unable to resolve naming.");
    }

    public String get_OriginalPackageName(StringTokenizer st) {
      if (!st.hasMoreTokens()) {
        return get_OriginalName();
      }

      String subName = st.nextToken();

      Iterator<NameHolder> cit = children.iterator();
      while (cit.hasNext()) {
        NameHolder h = cit.next();

        if (h.get_PackageName().equals(subName)) {
          String originalSubPackageName = h.get_OriginalPackageName(st);

          if (originalSubPackageName == null) {
            return null;
          } else {
            return get_OriginalName() + "." + originalSubPackageName;
          }
        }
      }

      return null;
    }

    public boolean contains_OriginalName(StringTokenizer st, boolean forClass) {
      if (!get_OriginalName().equals(st.nextToken())) {
        return false;
      }

      return finds_OriginalName(st, forClass);
    }

    private boolean finds_OriginalName(StringTokenizer st, boolean forClass) {
      if (!st.hasMoreTokens()) {
        return (((forClass) && (is_Class())) || ((!forClass) && (is_Package())));
      }

      String subName = st.nextToken();
      Iterator<NameHolder> cit = children.iterator();
      while (cit.hasNext()) {
        NameHolder h = cit.next();

        if (h.get_OriginalName().equals(subName)) {
          return h.finds_OriginalName(st, forClass);
        }
      }

      return false;
    }

    public void fix_ClassNames(String curPackName) {
      if ((is_Class()) && (keywords.contains(className))) {
        String tClassName = className;

        if (Character.isLowerCase(className.charAt(0))) {
          tClassName = tClassName.substring(0, 1).toUpperCase() + tClassName.substring(1);
          className = tClassName;
        }

        for (int i = 0; keywords.contains(className); i++) {
          className = tClassName + "_c" + i;
        }
      }

      Iterator<NameHolder> it = children.iterator();
      while (it.hasNext()) {
        it.next().fix_ClassNames(curPackName + "." + packageName);
      }
    }

    public void fix_PackageNames() {
      if ((is_Package()) && !verify_PackageName()) {
        String tPackageName = packageName;

        if (Character.isUpperCase(packageName.charAt(0))) {
          tPackageName = tPackageName.substring(0, 1).toLowerCase() + tPackageName.substring(1);
          packageName = tPackageName;
        }

        for (int i = 0; !verify_PackageName(); i++) {
          packageName = tPackageName + "_p" + i;
        }
      }

      Iterator<NameHolder> it = children.iterator();
      while (it.hasNext()) {
        it.next().fix_PackageNames();
      }
    }

    public boolean verify_PackageName() {
      return (!keywords.contains(packageName) && !siblingClashes(packageName)
          && (!is_Class() || !className.equals(packageName)));
    }

    public boolean siblingClashes(String name) {
      Iterator<NameHolder> it = null;

      if (parent == null) {

        if (appRoots.contains(this)) {
          it = appRoots.iterator();
        } else {
          throw new RuntimeException("Unable to find package siblings.");
        }
      } else {
        it = parent.get_Children().iterator();
      }

      while (it.hasNext()) {
        NameHolder sibling = it.next();

        if (sibling == this) {
          continue;
        }

        if (((sibling.is_Package()) && (sibling.get_PackageName().equals(name)))
            || ((sibling.is_Class()) && (sibling.get_ClassName().equals(name)))) {
          return true;
        }
      }

      return false;
    }

    public void dump(String indentation) {
      logger.debug("" + indentation + "\"" + originalName + "\", \"" + packageName + "\", \"" + className + "\" (");
      if (is_Class()) {
        logger.debug("c");
      }
      if (is_Package()) {
        logger.debug("p");
      }
      logger.debug("" + ")");

      Iterator<NameHolder> it = children.iterator();
      while (it.hasNext()) {
        it.next().dump(indentation + "  ");
      }
    }
  }

      if (parent == null) {
        return packageName;
      }

      return parent.get_FixedPackageName() + "." + packageName;
    
<no_super_class>