gt: 		if (n instanceof Subgraph) {
context: /*******************************************************************************
   * Copyright (c) 2003, 2010, 2012 IBM Corporation, Gerhardt Informatics Kft. and others.
   * All rights reserved. This program and the accompanying materials
   * are made available under the terms of the Eclipse Public License v1.0
   * which accompanies this distribution, and is available at
   * http://www.eclipse.org/legal/epl-v10.html
   *
   * Contributors:
   *     IBM Corporation - initial API and implementation
   *     Gerhardt Informatics Kft. - GEFGWT port
   *******************************************************************************/
  package org.eclipse.draw2d.graph;
  
  /**
   * This visitor eliminates cycles in the graph via a modified implementation of
   * the greedy cycle removal algorithm for directed graphs. The algorithm has
   * been modified to handle the presence of Subgraphs and compound cycles which
   * may result. This algorithm determines a set of edges which can be inverted
   * and result in a graph without compound cycles.
   * 
   * @author Daniel Lee
   * @author Randy Hudson
   * @since 2.1.2
   */
  class CompoundBreakCycles extends GraphVisitor {
  
  	/*
  	 * Caches all nodes in the graph. Used in identifying cycles and in cycle
  	 * removal. Flag field indicates "presence". If true, the node has been
  	 * removed from the list.
  	 */
  	private NodeList graphNodes;
  	private NodeList sL = new NodeList();
  
  	private boolean allFlagged(NodeList nodes) {
  		for (int i = 0; i < nodes.size(); i++) {
  			if (nodes.getNode(i).flag == false)
  				return false;
  		}
  		return true;
  	}
  
  	private int buildNestingTreeIndices(NodeList nodes, int base) {
  		for (int i = 0; i < nodes.size(); i++) {
  			Node node = (Node) nodes.get(i);
  			if (node instanceof Subgraph) {
  				Subgraph s = (Subgraph) node;
  				s.nestingTreeMin = base;
  				base = buildNestingTreeIndices(s.members, base);
  			}
  			node.nestingIndex = base++;
  		}
  		return base++;
  	}
  
  	private boolean canBeRemoved(Node n) {
  		return !n.flag && getChildCount(n) == 0;
  	}
  
  	private boolean changeInDegree(Node n, int delta) {
  		return (n.workingInts[1] += delta) == 0;
  	}
  
  	private boolean changeOutDegree(Node n, int delta) {
  		return (n.workingInts[2] += delta) == 0;
  	}
  
  	/*
  	 * Execution of the modified greedy cycle removal algorithm.
  	 */
  	private void cycleRemove(NodeList children) {
  		NodeList sR = new NodeList();
  		do {
  			findSinks(children, sR);
  			findSources(children);
  
  			// all sinks and sources added, find node with highest
  			// outDegree - inDegree
  			Node max = findNodeWithMaxDegree(children);
  			if (max != null) {
  				for (int i = 0; i < children.size(); i++) {
  					Node child = (Node) children.get(i);
  					if (child.flag)
  						continue;
  					if (child == max)
  						restoreSinks(max, sR);
  					else
  						restoreSources(child);
  				}
  				remove(max);
  			}
  		} while (!allFlagged(children));
  		while (!sR.isEmpty())
  			sL.add(sR.remove(sR.size() - 1));
  	}
  
  	private void findInitialSinks(NodeList children, NodeList sinks) {
  		for (int i = 0; i < children.size(); i++) {
  			Node node = children.getNode(i);
  			if (node.flag)
  				continue;
  			if (isSink(node) && canBeRemoved(node)) {
  				sinks.add(node);
  				node.flag = true;
  			}
  			if (node instanceof Subgraph)
  				findInitialSinks(((Subgraph) node).members, sinks);
  		}
  	}
  
  	private void findInitialSources(NodeList children, NodeList sources) {
  		for (int i = 0; i < children.size(); i++) {
  			Node node = children.getNode(i);
  			if (isSource(node) && canBeRemoved(node)) {
  				sources.add(node);
  				node.flag = true;
  			}
  			if (node instanceof Subgraph)
  				findInitialSources(((Subgraph) node).members, sources);
  		}
  	}
  
  	private Node findNodeWithMaxDegree(NodeList nodes) {
  		int max = Integer.MIN_VALUE;
  		Node maxNode = null;
  
  		for (int i = 0; i < nodes.size(); i++) {
  			Node node = nodes.getNode(i);
  			if (node.flag)
  				continue;
  			int degree = getNestedOutDegree(node) - getNestedInDegree(node);
  			if (degree >= max && node.flag == false) {
  				max = degree;
  				maxNode = node;
  			}
  		}
  		return maxNode;
  	}
  
  	/*
  	 * Finds all sinks in graphNodes and adds them to the passed NodeList
  	 */
  	private void findSinks(NodeList children, NodeList rightList) {
  		// NodeList rightList = new NodeList();
  		NodeList sinks = new NodeList();
  		findInitialSinks(children, sinks);
  		while (!sinks.isEmpty()) {
  			Node sink = sinks.getNode(sinks.size() - 1);
  			rightList.add(sink);
  			sinks.remove(sink);
  			removeSink(sink, sinks);
  
  			// Check to see if the removal has made the parent node a sink
  			if (sink.getParent() != null) {
  				Node parent = sink.getParent();
  				setChildCount(parent, getChildCount(parent) - 1);
  				if (isSink(parent) && canBeRemoved(parent)) {
  					sinks.add(parent);
  					parent.flag = true;
  				}
  			}
  		}
  	}
  
  	/*
  	 * Finds all sources in graphNodes and adds them to the sL NodeList.
  	 */
  	private void findSources(NodeList children) {
  		NodeList sources = new NodeList();
  		findInitialSources(children, sources);
  		while (!sources.isEmpty()) {
  			Node source = sources.getNode(sources.size() - 1);
  			sL.add(source);
  			sources.remove(source);
  			removeSource(source, sources);
  
  			// Check to see if the removal has made the parent node a source
  			if (source.getParent() != null) {
  				Node parent = source.getParent();
  				setChildCount(parent, getChildCount(parent) - 1);
  				if (isSource(parent) && canBeRemoved(parent)) {
  					sources.add(parent);
  					parent.flag = true;
  				}
  			}
  		}
  	}
  
  	private int getChildCount(Node n) {
  		return n.workingInts[3];
  	}
  
  	private int getInDegree(Node n) {
  		return n.workingInts[1];
  	}
  
  	private int getNestedInDegree(Node n) {
  		int result = getInDegree(n);
  		if (n instanceof Subgraph) {
  			Subgraph s = (Subgraph) n;
  			for (int i = 0; i < s.members.size(); i++)
  				if (!s.members.getNode(i).flag)
  					result += getInDegree(s.members.getNode(i));
  		}
  		return result;
  	}
  
  	private int getNestedOutDegree(Node n) {
  		int result = getOutDegree(n);
  		if (n instanceof Subgraph) {
  			Subgraph s = (Subgraph) n;
  			for (int i = 0; i < s.members.size(); i++)
  				if (!s.members.getNode(i).flag)
  					result += getOutDegree(s.members.getNode(i));
  		}
  		return result;
  	}
  
  	private int getOrderIndex(Node n) {
  		return n.workingInts[0];
  	}
  
  	private int getOutDegree(Node n) {
  		return n.workingInts[2];
  	}
  
  	private void initializeDegrees(DirectedGraph g) {
  		g.nodes.resetFlags();
  		g.edges.resetFlags(false);
  		for (int i = 0; i < g.nodes.size(); i++) {
  			Node n = g.nodes.getNode(i);
  			setInDegree(n, n.incoming.size());
  			setOutDegree(n, n.outgoing.size());
  			if (n instanceof Subgraph)
  				setChildCount(n, ((Subgraph) n).members.size());
  			else
  				setChildCount(n, 0);
  		}
  	}
  
  	private void invertEdges(DirectedGraph g) {
  		// Assign order indices
  		int orderIndex = 0;
  		for (int i = 0; i < sL.size(); i++) {
  			setOrderIndex(sL.getNode(i), orderIndex++);
  		}
  		// Invert edges that are causing a cycle
  		for (int i = 0; i < g.edges.size(); i++) {
  			Edge e = g.edges.getEdge(i);
  			if (getOrderIndex(e.source) > getOrderIndex(e.target)
  					&& !e.source.isNested(e.target)
  					&& !e.target.isNested(e.source)) {
  				e.invert();
  				e.isFeedback = true;
  			}
  		}
  	}
  
  	/**
  	 * Removes all edges connecting the given subgraph to other nodes outside of
  	 * it.
  	 * 
  	 * @param s
  	 * @param n
  	 */
  	private void isolateSubgraph(Subgraph subgraph, Node member) {
  		Edge edge = null;
  		for (int i = 0; i < member.incoming.size(); i++) {
  			edge = member.incoming.getEdge(i);
  			if (!subgraph.isNested(edge.source) && !edge.flag)
  				removeEdge(edge);
  		}
  		for (int i = 0; i < member.outgoing.size(); i++) {
  			edge = member.outgoing.getEdge(i);
  			if (!subgraph.isNested(edge.target) && !edge.flag)
  				removeEdge(edge);
  		}
  		if (member instanceof Subgraph) {
  			NodeList members = ((Subgraph) member).members;
  			for (int i = 0; i < members.size(); i++)
  				isolateSubgraph(subgraph, members.getNode(i));
  		}
  	}
  
  	private boolean isSink(Node n) {
  		return getOutDegree(n) == 0
  				&& (n.getParent() == null || isSink(n.getParent()));
  	}
  
  	private boolean isSource(Node n) {
  		return getInDegree(n) == 0
  				&& (n.getParent() == null || isSource(n.getParent()));
  	}
  
  	private void remove(Node n) {
  		n.flag = true;
  		if (n.getParent() != null)
  			setChildCount(n.getParent(), getChildCount(n.getParent()) - 1);
  		removeSink(n, null);
  		removeSource(n, null);
  		sL.add(n);
  