public void iterateFileNames(IndexEntriesWalkerInterruptable iproc) {
   for (FileEntitiesHolder d : files.values()) {
     //            iproc.process(d.getPath(), Long.toString(d.timeStamp));
     if (!iproc.process(d.getPath(), d.value)) {
       return;
     }
   }
 }
  public void changeFileName(String oldFileName, String newFileName) {
    String fileName = oldFileName.replace(' ', '?').replace('\\', '|').replace('/', '|');
    FileEntitiesHolder fileHolder = files.remove(fileName);
    if (fileHolder == null) {
      // file not found
      return;
    }

    String _newfileName = newFileName.replace(' ', '?').replace('\\', '|').replace('/', '|');
    fileHolder.filePath = _newfileName;
    files.put(_newfileName, fileHolder);
  }
  //  /FL!..$ota_flow_manager_pkg.pks/PS!..$ota_flow_manager_pkg/Va!..$pc_bs_15m_dflt [Value]
  // 1|INTEGER
  public void addContextPath(String ctxPath, String value) {
    String[] path = ctxPath.split("/");

    // validate root context
    if (!("/" + path[1]).startsWith(ContextPath.FILE_CTX_PRX) || ctxPath.indexOf(' ') != -1) {
      throw new ValidationException("Broken Context Path occurred: FILE CTX Path must be first!");
    } else {
      switch (path.length) {
        case 0:
        case 1:
          throw new ValidationException("Broken Context Path occurred");
        case 2: // load file attributes
          String fileName = path[1].substring(6);
          FileEntitiesHolder fileHolder = files.get(fileName);
          if (fileHolder == null) {
            fileHolder = new FileEntitiesHolder(fileName);
            files.put(fileName, fileHolder);
          }
          value = (value == null || value.length() == 0) ? "" : value;
          fileHolder.value = value;
          return;
        default:
          break;
      }
    }

    String encodedName = "/" + path[2];
    String filePath = path[1].substring(6);
    String name = path[2].substring(6); // , path[2].length());
    // try to find existing top node first
    List<TreeNode> addTo = new ArrayList<TreeNode>();
    root.findChildrenBySuffix(name, addTo);
    for (TreeNode node : addTo) {
      final TreeNodeTop top = (TreeNodeTop) node;
      if (encodedName.equals(top.encodedName) && filePath.equals(top.owner.filePath)) {
        // top node found
        addCtxValue(top, path, value);
        return;
      }
    }

    // top node not found, so create one
    int type = ContextPathUtil.prefix2type(encodedName.substring(0, 4));
    TreeNode top = addTopNode(root, type, encodedName, filePath);
    addCtxValue(top, path, value);

    // log adding entry
    println("[Path] " + ctxPath + " [Value] " + value);
  }
  public boolean remove(String ctxPath) {
    String[] path = ctxPath.split("/");

    boolean result = false;
    // validate root context
    if (!("/" + path[1]).startsWith(ContextPath.FILE_CTX_PRX)) {
      throw new ValidationException("Broken Context Path occurred: FILE CTX Path must be first!");
    } else {
      switch (path.length) {
        case 0:
        case 1:
          throw new ValidationException("Broken Context Path occurred");
        case 2: // remove the file and all its children
          String fileName = path[1].substring(6);
          FileEntitiesHolder fileHolder = files.remove(fileName);
          if (fileHolder != null) {
            fileHolder.removeChildren();
            result = true;
          }
          break;
        default:
          TreeNode parent = root;
          TreeNode target = null;
          int i = 2;
          while (true) {
            target = parent.findChildByEncodedName("/" + path[i]);
            if (++i < path.length && target != null) {
              parent = target;
              target = null;
            } else {
              break;
            }
          }

          if (target != null) {
            result = parent.removeNodeByEncodedName(target.getName());
          } else {
            // todo -- handle internal error
          }
          break;
      }
    }

    // NOTE: do not simplify! modCOunter should be incremented!
    return result ? ++modCount > 0 : false;
  }
  public void setFileAttribute(String _fileName, String attributeName, String value) {
    String fileName = _fileName.replace(' ', '?').replace('\\', '|').replace('/', '|');
    FileEntitiesHolder fileHolder = files.get(fileName);
    if (fileHolder == null) {
      fileHolder = new FileEntitiesHolder(fileName);
      files.put(fileName, fileHolder);
    }

    if (fileHolder.value != null) {
      String[] attrs = fileHolder.value.split("\\|");
      int index = -1, i = 0;
      for (String a : attrs) {
        String[] name_value_pair = a.split("\\=");
        if (name_value_pair[0].equals(attributeName)) {
          if (name_value_pair.length > 1) {
            String updatedPair = name_value_pair[0] + "=" + ((value == null) ? "" : value);
            attrs[i] = updatedPair;
          }
          index = i;
          break;
        }
        i++;
      }

      if (index == -1) {
        fileHolder.value =
            fileHolder.value + "|" + attributeName + "=" + ((value == null) ? "" : value);
      } else {
        StringBuffer buff = new StringBuffer();
        for (String a : attrs) {
          if (buff.length() > 0) {
            buff.append("|");
          }
          buff.append(a);
        }

        fileHolder.value = buff.toString();
      }
    } else {
      fileHolder.value = attributeName + "=" + ((value == null) ? "" : value);
    }

    modCount++;
  }
  //  /FL!..$ota_flow_manager_pkg.pks/PS!..$ota_flow_manager_pkg/Va!..$pc_bs_15m_dflt [Value]
  // 1|INTEGER
  public void _addContextPath(String ctxPath, String value) {
    String[] path = ctxPath.split("/");

    // validate root context
    if (!("/" + path[1]).startsWith(ContextPath.FILE_CTX_PRX) || ctxPath.indexOf(' ') != -1) {
      throw new ValidationException("Broken Context Path occurred: FILE CTX Path must be first!");
    } else {
      switch (path.length) {
        case 0:
        case 1:
          throw new ValidationException("Broken Context Path occurred");
        case 2: // load file attributes
          String fileName = path[1].substring(6);
          FileEntitiesHolder fileHolder = files.get(fileName);
          if (fileHolder == null) {
            fileHolder = new FileEntitiesHolder(fileName);
            files.put(fileName, fileHolder);
          }
          value = (value == null || value.length() == 0) ? "" : value;
          fileHolder.value = value;
          return;
        default:
          break;
      }
    }

    TreeNode cycled = root;
    boolean pathCreated = false;
    for (int i = 2; i < path.length; i++) {
      String encodedName = "/" + path[i];
      int type = ContextPathUtil.prefix2type(encodedName.substring(0, 4));
      TreeNode child = cycled.findChildByEncodedName(encodedName);
      if (child == null) {
        if (i == 2) {
          // add node level 1 -
          cycled = addTopNode(root, type, encodedName, path[1].substring(6));
        } else {
          cycled = cycled.addNode(type, encodedName);
        }
        pathCreated = true;
      } else {
        cycled = child;
      }
    }

    /*      todo -- entryCounter not correct any longer, FIXME
            if (cycled.getValue() == null) {
                entryCounter++;
            }
            cycled.addValue(value == null ? "" : value);
    */
    if (pathCreated) {
      entryCounter++;
    }
    if (value != null) {
      cycled.addValue(value);
      modCount++;
    } else {
      // check whether the path was really created
      modCount = (pathCreated) ? modCount + 1 : modCount;
    }

    // log adding entry
    println("[Path] " + ctxPath + " [Value] " + value);
  }
 public String getParentPath() {
   return owner.getPath();
 }
 public String getPath() {
   return owner.getPath() + encodedName;
 }
 protected void dispose() {
   owner.removeChild(this);
 }
 public TreeNodeTop(TreeNodeImpl parent, String encodedName, FileEntitiesHolder owner) {
   super(parent, encodedName);
   this.owner = owner;
   owner.addChild(this);
 }