private void addCtxValue(TreeNode cycled, String[] pathParts, String value) {
    boolean pathCreated = false;
    for (int i = 2 + 1; i < pathParts.length; i++) {
      String encodedName = "/" + pathParts[i];
      TreeNode child = cycled.findChildByEncodedName(encodedName);
      if (child == null) {
        int type = ContextPathUtil.prefix2type(encodedName.substring(0, 4));
        cycled = cycled.addNode(type, encodedName);
        pathCreated = true;
      } else {
        cycled = child;
      }
    }

    if (pathCreated) {
      entryCounter++;
    }
    if (value != null) {
      cycled.addValue(value);
      modCount++;
    } else {
      // check whether the path was really created
      modCount = (pathCreated) ? modCount + 1 : 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;
      }
    }

    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 void searchContextTree_DownUp(
      String startCtxPath, String name, int refType, TreeNodeHandler handler) {
    String[] path = startCtxPath.split("/");

    int _1st_ctxType = -1;
    int startWith = ("/" + path[1]).startsWith(ContextPath.FILE_CTX_PRX) ? 2 : 1;
    List<TreeNode> out = new ArrayList<TreeNode>();

    TreeNode cycled = root;
    for (int i = startWith; i < path.length; i++) {
      String encodedName = "/" + path[i];
      int ctxType = ContextPathUtil.prefix2type(encodedName.substring(0, 4));
      if (i == startWith) {
        // save the type of the first context
        _1st_ctxType = ctxType;
      }

      cycled = cycled.findChildByEncodedName(encodedName);
      if (cycled == null) {
        // todo -- is it suggested?
        break;
      } else {
        if (i == path.length - 1) {
          // check type of the last context
          switch (refType) {
            case ContextPath.NESTED_CALL:
              // search for the name in the context only
              for (TreeNode d : cycled.findChildrenBySuffix(name)) {
                handler.handleNode(d);
              }
              return;
            default:
              switch (ctxType) {
                case ContextPath.COLUMN_DEF:
                case ContextPath.RECORD_ITEM:
                case ContextPath.VARIABLE_DECL:
                case ContextPath.ARGUMENT:
                case ContextPath.REF_CURSOR:
                  // skip search in the context
                  // todo -- more types expected
                  continue;
                default:
                  break;
              }
          }
        } else {
          // intermediate context, add to list
        }

        out.add(cycled);
      }
    }

    for (int i = out.size() - 1; i >= 0; i--) {
      TreeNode n = out.get(i);
      for (TreeNode foundNode : n.findChildrenBySuffix(name)) {
        if (handler.handleNode(foundNode)) {
          // iteration terminated by listener
          return;
        }
      }

      //            switch(n.getType()){
      //                case ContextPath.CURSOR_DECL:
      //                    // Cursor decl: closed scope
      //                    return;
      //            }
    }

    if (_1st_ctxType == ContextPath.PACKAGE_BODY) {
      // search package spec for name
      String spec =
          ContextPath.PACKAGE_SPEC_PRX + path[startWith].substring(3, path[startWith].length());
      for (TreeNode pks : findNodeInRelContext(spec, name)) { // findInContext2(spec, name)) {
        if (handler.handleNode(pks)) {
          // iteration terminated by listener
          return;
        }
      }
    }

    switch (refType) {
      case ContextPath.FUNC_CALL:
      case ContextPath.PROC_CALL:
      case ContextPath.TABLE_REF:
      case ContextPath.TYPE_REF:
      case ContextPath.GENERIC_NAME_REF: // package name (coming from sql code)
      case ContextPath.PLSQL_NAME_REF: // package name (coming from pl/sql code)
        // todo -- do we need to limit target ref types?
        // search in the root context
        for (TreeNode d : findNodeInRootContext(name)) {
          if (handler.handleNode(d)) {
            // iteration terminated by listener
            return;
          }
        }
        break;
    }
  }
  //  /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);
  }