All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.named_data.jndn.util.BoostInfoTree Maven / Gradle / Ivy

/**
 * Copyright (C) 2015-2018 Regents of the University of California.
 * @author: Jeff Thompson 
 * From PyNDN boost_info_parser by Adeola Bannis.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see .
 * A copy of the GNU Lesser General Public License is in the file COPYING.
 */

package net.named_data.jndn.util;

import java.util.ArrayList;

/**
 * BoostInfoTree is provided for compatibility with the Boost INFO property list
 * format used in ndn-cxx.
 *
 * Each node in the tree may have a name and a value as well as associated
 * sub-trees. The sub-tree names are not unique, and so sub-trees are stored as
 * dictionaries where the key is a sub-tree name and the values are the
 * sub-trees sharing the same name.
 *
 * Nodes can be accessed with a path syntax, as long as nodes in the path do not
 * contain the path separator '/' in their names.
 */
public class BoostInfoTree {
  public BoostInfoTree(String value, BoostInfoTree parent)
  {
    value_ = value;
    parent_ = parent;
  }

  public BoostInfoTree(String value)
  {
    value_ = value;
  }

  public BoostInfoTree()
  {
  }

  /**
   * Insert a BoostInfoTree as a sub-tree with the given name.
   * @param treeName The name of the new sub-tree.
   * @param newTree The sub-tree to add.
   */
  public final void
  addSubtree(String treeName, BoostInfoTree newTree)
  {
    ArrayList subtreeList = find(treeName);
    if (subtreeList != null)
      subtreeList.add(newTree);
    else {
      TreeEntry entry = new TreeEntry(treeName);
      subtrees_.add(entry);
      entry.subtreeList_.add(newTree);
    }

    newTree.parent_ = this;
    lastChild_ = newTree;
  }

  /**
   * Create a new BoostInfoTree and insert it as a sub-tree with the given name.
   * @param treeName The name of the new sub-tree.
   * @param value The value associated with the new sub-tree.
   * @return The created sub-tree.
   */
  public final BoostInfoTree
  createSubtree(String treeName, String value)
  {
    BoostInfoTree newTree = new BoostInfoTree(value, this);
    addSubtree(treeName, newTree);
    return newTree;
  }

  /**
   * Create a new BoostInfoTree with where the value is an empty string,
   * and insert it as a sub-tree with the given name.
   * @param treeName The name of the new sub-tree.
   * @return The created sub-tree.
   */
  public final BoostInfoTree
  createSubtree(String treeName)
  {
    return createSubtree(treeName, "");
  }

  /**
   * Look up using the key and return a list of the subtrees.
   * @param key The key which may be a path separated with '/'.
   * @return A new ArrayList of BoostInfoTree which are the subtrees.
   */
  public final ArrayList
  get(String key)
  {
    ArrayList foundVals = new ArrayList();

    // Strip beginning '/'.
    key = key.replaceFirst("^/+", "");
    if (key.length() == 0) {
      foundVals.add(this);
      return foundVals;
    }
    String[] path = key.split("/");

    ArrayList subtrees = find(path[0]);
    if (subtrees == null)
      return foundVals;
    if (path.length == 1)
      return (ArrayList)subtrees.clone();

    // newPath = path.slice(1).join('/')
    // Implement manually because older Java versions don't have join.
    String newPath = "";
    for (int i = 1; i < path.length; ++i) {
      if (i > 1)
        newPath += "/";
      newPath += path[i];
    }

    for (int i = 0; i < subtrees.size(); ++i) {
      BoostInfoTree t = subtrees.get(i);
      ArrayList partial = t.get(newPath);
      foundVals.addAll(partial);
    }

    return foundVals;
  }

  /**
   * Look up using the key and return string value of the first subtree.
   * @param key The key which may be a path separated with '/'.
   * @return A pointer to the string value or null if not found.
   */
  public final String
  getFirstValue(String key)
  {
    ArrayList list = get(key);
    if (list.size() >= 1)
      return list.get(0).value_;
    else
      return null;
  }

  public final String
  getValue() { return value_; }

  public final BoostInfoTree
  getParent() { return parent_; }

  public final BoostInfoTree
  getLastChild() { return lastChild_; }

  public final String
  prettyPrint(int indentLevel)
  {
    // Set prefix to indentLevel spaces.
    String prefix = new String(new char[indentLevel]).replace("\0", " ");
    String s = "";

    if (parent_ != null) {
      if (value_.length() > 0)
        s += "\"" + value_ + "\"";
      s += "\n";
    }

    if (subtrees_.size() > 0) {
      if (parent_ != null)
        s += prefix+ "{\n";
      String nextLevel = new String(new char[indentLevel + 2]).replace("\0", " ");
      for (int i = 0; i < subtrees_.size(); ++i) {
        TreeEntry entry = subtrees_.get(i);
        for (int iSubTree = 0; iSubTree < entry.subtreeList_.size(); ++iSubTree)
          s += nextLevel + entry.treeName_ + " " +
            (entry.subtreeList_.get(iSubTree)).prettyPrint(indentLevel + 2);
      }

      if (parent_ != null)
        s +=  prefix + "}\n";
    }

    return s;
  }

  public final String
  prettyPrint()
  {
    return prettyPrint(1);
  }

  public String
  toString() { return prettyPrint(); }

  private class TreeEntry {
    public TreeEntry(String treeName)
    {
      treeName_ = treeName;
    }

    public String treeName_;
    public ArrayList subtreeList_ = new ArrayList();
  }

  /**
   * Use treeName to find the vector of BoostInfoTree in subtrees_.
   * @param value The key in subtrees_ to search for.  This does a flat search
   * in subtrees_.  It does not split by '/' into a path.
   * @return A list of BoostInfoTree, or null if not found.
   */
  private ArrayList
  find(String treeName)
  {
    for (int i = 0; i < subtrees_.size(); ++i) {
      TreeEntry entry = subtrees_.get(i);
      if (entry.treeName_.equals(treeName))
        return entry.subtreeList_;
    }

    return null;
  }

  // We can't use a map for subtrees_ because we want the keys to be in order.
  private ArrayList subtrees_ = new ArrayList();
  private String value_ = "";
  private BoostInfoTree parent_ = null;
  private BoostInfoTree lastChild_ = null;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy