private boolean getSubNodesAndEdges(
      String tag, int distance, Collection<DAGEdge> edges, Collection<DAGNode> nodes) {
    RelatedEdgeModule relatedEdgeModule =
        (RelatedEdgeModule) dag_.getModule(RelatedEdgeModule.class);

    if (!taggedNodes_.containsKey(tag)) return false;

    // 1. Identify tagged nodes
    Collection<DAGNode> newlyAddedNodes = new HashSet<>(taggedNodes_.get(tag));
    logger.debug("Identify tagged nodes: {}", newlyAddedNodes);

    boolean loop = false;
    do {
      // 2. Find links/ancestry of tagged nodes
      logger.debug("Find links/ancestry of tagged nodes {}", distance);
      findLinks(newlyAddedNodes, nodes, distance, relatedEdgeModule);
      logger.debug("Number of nodes: {}", newlyAddedNodes.size());

      // 3. Find other links between new nodes
      logger.debug("Linking nodes");
      edges.addAll(incorporateNewAndLinkEdges(nodes, newlyAddedNodes, relatedEdgeModule));
      logger.debug("Found {} linking edges.", edges.size());

      loop = !newlyAddedNodes.isEmpty();
      distance = 0;
    } while (loop);
    return true;
  }
 public Collection<DAGNode> getTagged(String tag) {
   String alterTag = TAG_PREFIX + tag;
   Collection<DAGNode> allTagged = new ArrayList<>();
   if (taggedNodes_.containsKey(alterTag)) allTagged.addAll(taggedNodes_.get(alterTag));
   String nonCoreTag = NON_CORE_PREFIX + tag;
   if (taggedNodes_.containsKey(nonCoreTag)) allTagged.addAll(taggedNodes_.get(nonCoreTag));
   return allTagged;
 }
 @Override
 public String toString() {
   if (taggedNodes_ == null) return "SubDAG Extractor Module (not yet initialised)";
   return "SubDAG Extractor Module: "
       + taggedNodes_.sizeTotal()
       + " tagged nodes from "
       + taggedNodes_.size()
       + " tags";
 }
 public synchronized void removeTagDAGObject(DAGNode dagObj, String tag) {
   String[] coreAndNonCore = {TAG_PREFIX + tag, NON_CORE_PREFIX + tag};
   for (String alterTag : coreAndNonCore) {
     dag_.removeProperty(dagObj, alterTag);
     Collection<DAGNode> tagged = taggedNodes_.get(alterTag);
     if (tagged != null) {
       taggedNodes_.get(alterTag).remove(dagObj);
       if (taggedNodes_.isValueEmpty(alterTag)) taggedNodes_.remove(alterTag);
     }
   }
 }
 @Override
 public boolean initialisationComplete(
     TIndexedCollection<DAGNode> nodes, TIndexedCollection<DAGEdge> edges, boolean forceRebuild) {
   if (taggedNodes_ == null) {
     taggedNodes_ = MultiMap.createSortedSetMultiMap();
     TIntObjectIterator<DAGNode> iter = nodes.iterator();
     for (int i = nodes.size(); i-- > 0; ) {
       iter.advance();
       DAGNode n = iter.value();
       String[] props = n.getProperties();
       for (String prop : props) {
         if (prop.startsWith(TAG_PREFIX)) {
           taggedNodes_.put(prop, n);
         }
       }
     }
   }
   return super.initialisationComplete(nodes, edges, forceRebuild);
 }
  public synchronized void tagDAGObject(DAGNode dagObj, String tag, boolean coreTag) {
    String alterTag = TAG_PREFIX + tag;
    String nonCoreTag = NON_CORE_PREFIX + tag;
    String appliedTag = (coreTag) ? alterTag : nonCoreTag;
    if (coreTag && dagObj.getProperty(nonCoreTag) != null) {
      // Upgrade non-core to core
      removeTagDAGObject(dagObj, tag);
    } else if (!coreTag && dagObj.getProperty(alterTag) != null)
      // Do not revert to non-core
      return;

    dag_.addProperty(dagObj, appliedTag, "T");
    taggedNodes_.put(appliedTag, dagObj);
  }
 public SubDAGExtractorModule() {
   taggedNodes_ = MultiMap.createSortedSetMultiMap();
 }