ContentMine/thresher

View on GitHub
lib/elementTree.js

Summary

Maintainability
A
0 mins
Test Coverage
var ElementTreeNode = function(element, children) {
  this.element = element;
  this.children = children || [];
}

ElementTreeNode.prototype.addChild = function(c) {
  this.children.push(c);
}

var ElementTree = function(elements) {
  this.root = new ElementTreeNode();
  // In addition to being referenced by their parent,
  // every node is stored in the nodes object for O(1)
  // access when adding nodes.
  this.nodes = {};
  // Children of each node are stored in the children
  // object, so children of a node can be accumulated
  // before the node itself has been added
  this.children = {};
  if (elements) {
    this.addElements(elements);
  }
}

ElementTree.prototype.addChild = function(child) {
  if (!(child instanceof ElementTreeNode)) {
    throw new Error("child must be an ElementTreeNode");
  }
  if (!child.element.hasOwnProperty('follow')) {
    throw new Error("cannot add a child whose element doesn't" +
                    "have the 'follow' property");
  }
  // If the parent doesn't already have a child array, create it
  var parentName = child.element.follow;
  if (!this.children[parentName]) {
    this.children[parentName] = [];
  }
  // Add the child to the parent's child array,
  // both in the tree's children object
  this.children[parentName].push(child);
  // and directly in the parent node
  if (this.nodes.hasOwnProperty(parentName)) {
    this.nodes[parentName].addChild(child);
  }
}

// Add an element to the tree
ElementTree.prototype.addElement = function(e) {
  var tree = this;
  var node = new ElementTreeNode(e);
  tree.nodes[e.name] = node;
  if (tree.children.hasOwnProperty(e.name)) {
    node.children = tree.children[e.name];
  }
  if (e.hasOwnProperty('follow')) {
    tree.addChild(node);
  } else {
    tree.root.addChild(node);
  }
}

// Add multiple elements to the tree
ElementTree.prototype.addElements = function(elements) {
  elements.forEach(this.addElement, this);
}

module.exports = {
  ElementTree: ElementTree,
  ElementTreeNode: ElementTreeNode
}