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

marytts.cart.NodeIterator Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2009 DFKI GmbH.
 * All Rights Reserved.  Use is subject to license terms.
 *
 * This file is part of MARY TTS.
 *
 * MARY TTS 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, version 3 of the License.
 *
 * 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 .
 *
 */

package marytts.cart;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author marc
 *
 */
public class NodeIterator implements Iterator {
	private Node root;
	private Node current;
	private boolean showLeafNodes;
	private boolean showDecisionNodes;
	private boolean showDirectedGraphNodes;
	private Set alreadySeen = new HashSet();
	// we need to keep our own map of daughter-mother relationships,
	// because for subgraphs, we could move out of a subgraph if we call node.getMother()
	// if the mother via which we entered a multi-parent node is not the first mother.
	private Map daughterToMother = new HashMap();

	/**
	 * Iterate over all nodes in the graph.
	 * 
	 * @param graph
	 *            graph
	 * @param showLeafNodes
	 *            showLeafNodes
	 * @param showDecisionNodes
	 *            showDecisionNodes
	 * @param showDirectedGraphNodes
	 *            showDirectedGraphNodes
	 */
	protected NodeIterator(DirectedGraph graph, boolean showLeafNodes, boolean showDecisionNodes, boolean showDirectedGraphNodes) {
		this(graph.getRootNode(), showLeafNodes, showDecisionNodes, showDirectedGraphNodes);
	}

	/**
	 * Iterate over the subtree below rootNode.
	 * 
	 * @param rootNode
	 *            rootNode
	 * @param showLeafNodes
	 *            showLeafNodes
	 * @param showDecisionNodes
	 *            showDecisionNodes
	 * @param showDirectedGraphNodes
	 *            showDirectedGraphNodes
	 */
	protected NodeIterator(Node rootNode, boolean showLeafNodes, boolean showDecisionNodes, boolean showDirectedGraphNodes) {
		this.root = rootNode;
		this.showLeafNodes = showLeafNodes;
		this.showDecisionNodes = showDecisionNodes;
		this.showDirectedGraphNodes = showDirectedGraphNodes;
		this.current = root;
		alreadySeen.add(current);
		if (!currentIsSuitable()) {
			nextSuitableNodeDepthFirst();
		}
	}

	public boolean hasNext() {
		return current != null;
	}

	public T next() {
		T ret = (T) current;
		// and already prepare the current one
		nextSuitableNodeDepthFirst();
		return ret;
	}

	private boolean currentIsSuitable() {
		return (current == null || showDecisionNodes && current.isDecisionNode() || showLeafNodes && current.isLeafNode() || showDirectedGraphNodes
				&& current.isDirectedGraphNode());
	}

	private void nextSuitableNodeDepthFirst() {
		do {
			nextNodeDepthFirst();
		} while (!currentIsSuitable());
	}

	private void nextNodeDepthFirst() {
		if (current == null)
			return;
		if (current.isDecisionNode()) {
			DecisionNode dec = (DecisionNode) current;
			for (int i = 0; i < dec.getNumberOfDaugthers(); i++) {
				Node daughter = dec.getDaughter(i);
				if (daughter == null)
					continue;
				daughterToMother.put(daughter, dec);
				if (unseenNode(dec.getDaughter(i)))
					return;
			}
		} else if (current.isDirectedGraphNode()) {
			// Graph nodes return leaf child first, then decision child
			DirectedGraphNode g = (DirectedGraphNode) current;
			Node leaf = g.getLeafNode();
			if (leaf != null) {
				daughterToMother.put(leaf, g);
				if (unseenNode(leaf))
					return;
			}
			Node dec = g.getDecisionNode();
			if (dec != null) {
				daughterToMother.put(dec, g);
				if (unseenNode(dec))
					return;
			}
		}
		// If we didn't find a suitable child, we need to:
		backtrace();
	}

	private void backtrace() {
		// Only go back to mothers we have come from.
		// This has two effects:
		// 1. We cannot go beyond root node;
		// 2. we don't risk to leave the subgraph defined by root node
		// in cases where we enter into a multi-parent node from a not-first mother
		// (in such cases, getMother() would return the first mother).
		current = daughterToMother.get(current);
		nextNodeDepthFirst();
	}

	/**
	 * Test whether the given node is unseen. If so, move current to it, and remember it as a seen node.
	 * 
	 * @param candidate
	 *            candidate
	 * @return True if candidate != null and !alreadySeen.contains(candidate)
	 */
	private boolean unseenNode(Node candidate) {
		if (candidate != null && !alreadySeen.contains(candidate)) {
			current = candidate;
			alreadySeen.add(current);
			return true;
		}
		return false;

	}

	public void remove() {
		throw new UnsupportedOperationException("Cannot remove nodes using this iterator");
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy