src/main/java/com/mxgraph/layout/hierarchical/model/mxGraphHierarchyModel.java
public void initialRank()
	{
		Collection<mxGraphHierarchyNode> internalNodes = vertexMapper.values();
		LinkedList<mxGraphHierarchyNode> startNodes = new LinkedList<mxGraphHierarchyNode>();

		if (roots != null)
		{
			Iterator<Object> iter = roots.iterator();

			while (iter.hasNext())
			{
				mxGraphHierarchyNode internalNode = vertexMapper.get(iter
						.next());

				if (internalNode != null)
				{
					startNodes.add(internalNode);
				}
			}
		}

		Iterator<mxGraphHierarchyNode> iter = internalNodes.iterator();

		while (iter.hasNext())
		{
			mxGraphHierarchyNode internalNode = iter.next();
			// Mark the node as not having had a layer assigned
			internalNode.temp[0] = -1;
		}

		List<mxGraphHierarchyNode> startNodesCopy = new ArrayList<mxGraphHierarchyNode>(
				startNodes);

		while (!startNodes.isEmpty())
		{
			mxGraphHierarchyNode internalNode = startNodes.getFirst();
			Collection<mxGraphHierarchyEdge> layerDeterminingEdges;
			Collection<mxGraphHierarchyEdge> edgesToBeMarked;

			layerDeterminingEdges = internalNode.connectsAsTarget;
			edgesToBeMarked = internalNode.connectsAsSource;

			// flag to keep track of whether or not all layer determining
			// edges have been scanned
			boolean allEdgesScanned = true;

			// Work out the layer of this node from the layer determining
			// edges
			Iterator<mxGraphHierarchyEdge> iter2 = layerDeterminingEdges
					.iterator();

			// The minimum layer number of any node connected by one of
			// the layer determining edges variable. If we are starting
			// from sources, need to start at some huge value and
			// normalise down afterwards
			int minimumLayer = SOURCESCANSTARTRANK;

			while (allEdgesScanned && iter2.hasNext())
			{
				mxGraphHierarchyEdge internalEdge = iter2.next();

				if (internalEdge.temp[0] == 5270620)
				{
					// This edge has been scanned, get the layer of the
					// node on the other end
					mxGraphHierarchyNode otherNode = internalEdge.source;
					minimumLayer = Math.min(minimumLayer,
								otherNode.temp[0] - 1);
				}
				else
				{
					allEdgesScanned = false;
				}
			}

			// If all edge have been scanned, assign the layer, mark all
			// edges in the other direction and remove from the nodes list
			if (allEdgesScanned)
			{
				internalNode.temp[0] = minimumLayer;
				maxRank = Math.min(maxRank, minimumLayer);

				if (edgesToBeMarked != null)
				{
					Iterator<mxGraphHierarchyEdge> iter3 = edgesToBeMarked
							.iterator();

					while (iter3.hasNext())
					{
						mxGraphHierarchyEdge internalEdge = iter3.next();
						// Assign unique stamp ( y/m/d/h )
						internalEdge.temp[0] = 5270620;

						// Add node on other end of edge to LinkedList of
						// nodes to be analysed
						mxGraphHierarchyNode otherNode = internalEdge.target;

						// Only add node if it hasn't been assigned a layer
						if (otherNode.temp[0] == -1)
						{
							startNodes.addLast(otherNode);

							// Mark this other node as neither being
							// unassigned nor assigned so it isn't
							// added to this list again, but it's
							// layer isn't used in any calculation.
							otherNode.temp[0] = -2;
						}
					}
				}

				startNodes.removeFirst();
			}
			else
			{
				// Not all the edges have been scanned, get to the back of
				// the class and put the dunces cap on
				Object removedCell = startNodes.removeFirst();
				startNodes.addLast(internalNode);

				if (removedCell == internalNode && startNodes.size() == 1)
				{
					// This is an error condition, we can't get out of
					// this loop. It could happen for more than one node
					// but that's a lot harder to detect. Log the error
					// TODO make log comment
					break;
				}
			}
		}

		// Normalize the ranks down from their large starting value to place
		// at least 1 sink on layer 0
		iter = internalNodes.iterator();
		while (iter.hasNext())
		{
			mxGraphHierarchyNode internalNode = iter.next();
			// Mark the node as not having had a layer assigned
			internalNode.temp[0] -= maxRank;
		}
		
		// Tighten the roots as far as possible
		for (int i = 0; i < startNodesCopy.size(); i++)
		{
			mxGraphHierarchyNode internalNode = startNodesCopy.get(i);
			int currentMaxLayer = 0;
			Iterator<mxGraphHierarchyEdge> iter2 = internalNode.connectsAsSource
					.iterator();

			while (iter2.hasNext())
			{
				mxGraphHierarchyEdge internalEdge = iter2.next();
				mxGraphHierarchyNode otherNode = internalEdge.target;
				internalNode.temp[0] = Math.max(currentMaxLayer,
						otherNode.temp[0] + 1);
				currentMaxLayer = internalNode.temp[0];
			}
		}

		// Reset the maxRank to that which would be expected for a from-sink
		// scan
		maxRank = SOURCESCANSTARTRANK - maxRank;
	}
/**
	 * Basic determination of minimum layer ranking by working from from sources
	 * or sinks and working through each node in the relevant edge direction.
	 * Starting at the sinks is basically a longest path layering algorithm.
	 */
Basic determination of minimum layer ranking by working from from sources
or sinks and working through each node in the relevant edge direction.
Starting at the sinks is basically a longest path layering algorithm.
Basic determination of minimum layer ranking by working from from sources or sinks and working through each node in the relevant edge direction . Starting at the sinks is basically a longest path layering algorithm .
public void initialRank()
	{
		Collection<mxGraphHierarchyNode> internalNodes = vertexMapper.values();
		LinkedList<mxGraphHierarchyNode> startNodes = new LinkedList<mxGraphHierarchyNode>();
		if (roots != null)
		{
			Iterator<Object> iter = roots.iterator();
			while (iter.hasNext())
			{
				mxGraphHierarchyNode internalNode = vertexMapper.get(iter
						.next());
				if (internalNode != null)
				{
					startNodes.add(internalNode);
				}
			}
		}
		Iterator<mxGraphHierarchyNode> iter = internalNodes.iterator();
		while (iter.hasNext())
		{
			mxGraphHierarchyNode internalNode = iter.next();
			internalNode.temp[0] = -1;
		}
		List<mxGraphHierarchyNode> startNodesCopy = new ArrayList<mxGraphHierarchyNode>(
				startNodes);
		while (!startNodes.isEmpty())
		{
			mxGraphHierarchyNode internalNode = startNodes.getFirst();
			Collection<mxGraphHierarchyEdge> layerDeterminingEdges;
			Collection<mxGraphHierarchyEdge> edgesToBeMarked;
			layerDeterminingEdges = internalNode.connectsAsTarget;
			edgesToBeMarked = internalNode.connectsAsSource;
			boolean allEdgesScanned = true;
			Iterator<mxGraphHierarchyEdge> iter2 = layerDeterminingEdges
					.iterator();
			int minimumLayer = SOURCESCANSTARTRANK;
			while (allEdgesScanned && iter2.hasNext())
			{
				mxGraphHierarchyEdge internalEdge = iter2.next();
				if (internalEdge.temp[0] == 5270620)
				{
					mxGraphHierarchyNode otherNode = internalEdge.source;
					minimumLayer = Math.min(minimumLayer,
								otherNode.temp[0] - 1);
				}
				else
				{
					allEdgesScanned = false;
				}
			}
			 in the other direction and remove from the nodes list
			if (allEdgesScanned)
			{
				internalNode.temp[0] = minimumLayer;
				maxRank = Math.min(maxRank, minimumLayer);
				if (edgesToBeMarked != null)
				{
					Iterator<mxGraphHierarchyEdge> iter3 = edgesToBeMarked
							.iterator();
					while (iter3.hasNext())
					{
						mxGraphHierarchyEdge internalEdge = iter3.next();
						internalEdge.temp[0] = 5270620;
						mxGraphHierarchyNode otherNode = internalEdge.target;
						if (otherNode.temp[0] == -1)
						{
							startNodes.addLast(otherNode);
							otherNode.temp[0] = -2;
						}
					}
				}
				startNodes.removeFirst();
			}
			else
			{
				Object removedCell = startNodes.removeFirst();
				startNodes.addLast(internalNode);
				if (removedCell == internalNode && startNodes.size() == 1)
				{
					break;
				}
			}
		}
		iter = internalNodes.iterator();
		while (iter.hasNext())
		{
			mxGraphHierarchyNode internalNode = iter.next();
			internalNode.temp[0] -= maxRank;
		}
		for (int i = 0; i < startNodesCopy.size(); i++)
		{
			mxGraphHierarchyNode internalNode = startNodesCopy.get(i);
			int currentMaxLayer = 0;
			Iterator<mxGraphHierarchyEdge> iter2 = internalNode.connectsAsSource
					.iterator();
			while (iter2.hasNext())
			{
				mxGraphHierarchyEdge internalEdge = iter2.next();
				mxGraphHierarchyNode otherNode = internalEdge.target;
				internalNode.temp[0] = Math.max(currentMaxLayer,
						otherNode.temp[0] + 1);
				currentMaxLayer = internalNode.temp[0];
			}
		}
		maxRank = SOURCESCANSTARTRANK - maxRank;
	}
public void initialRank ( ) { Collection < mxGraphHierarchyNode > internalNodes = vertexMapper . values ( ) ; LinkedList < mxGraphHierarchyNode > startNodes = new LinkedList < mxGraphHierarchyNode > ( ) ; if ( roots != null ) { Iterator < Object > iter = roots . iterator ( ) ; while ( iter . hasNext ( ) ) { mxGraphHierarchyNode internalNode = vertexMapper . get ( iter . next ( ) ) ; if ( internalNode != null ) { startNodes . add ( internalNode ) ; } } } Iterator < mxGraphHierarchyNode > iter = internalNodes . iterator ( ) ; while ( iter . hasNext ( ) ) { mxGraphHierarchyNode internalNode = iter . next ( ) ; internalNode . temp [ 0 ] = - 1 ; } List < mxGraphHierarchyNode > startNodesCopy = new ArrayList < mxGraphHierarchyNode > ( startNodes ) ; while ( ! startNodes . isEmpty ( ) ) { mxGraphHierarchyNode internalNode = startNodes . getFirst ( ) ; Collection < mxGraphHierarchyEdge > layerDeterminingEdges ; Collection < mxGraphHierarchyEdge > edgesToBeMarked ; layerDeterminingEdges = internalNode . connectsAsTarget ; edgesToBeMarked = internalNode . connectsAsSource ; boolean allEdgesScanned = true ; Iterator < mxGraphHierarchyEdge > iter2 = layerDeterminingEdges . iterator ( ) ; int minimumLayer = SOURCESCANSTARTRANK ; while ( allEdgesScanned && iter2 . hasNext ( ) ) { mxGraphHierarchyEdge internalEdge = iter2 . next ( ) ; if ( internalEdge . temp [ 0 ] == 5270620 ) { mxGraphHierarchyNode otherNode = internalEdge . source ; minimumLayer = Math . min ( minimumLayer , otherNode . temp [ 0 ] - 1 ) ; } else { allEdgesScanned = false ; } } if ( allEdgesScanned ) { internalNode . temp [ 0 ] = minimumLayer ; maxRank = Math . min ( maxRank , minimumLayer ) ; if ( edgesToBeMarked != null ) { Iterator < mxGraphHierarchyEdge > iter3 = edgesToBeMarked . iterator ( ) ; while ( iter3 . hasNext ( ) ) { mxGraphHierarchyEdge internalEdge = iter3 . next ( ) ; internalEdge . temp [ 0 ] = 5270620 ; mxGraphHierarchyNode otherNode = internalEdge . target ; if ( otherNode . temp [ 0 ] == - 1 ) { startNodes . addLast ( otherNode ) ; otherNode . temp [ 0 ] = - 2 ; } } } startNodes . removeFirst ( ) ; } else { Object removedCell = startNodes . removeFirst ( ) ; startNodes . addLast ( internalNode ) ; if ( removedCell == internalNode && startNodes . size ( ) == 1 ) { break ; } } } iter = internalNodes . iterator ( ) ; while ( iter . hasNext ( ) ) { mxGraphHierarchyNode internalNode = iter . next ( ) ; internalNode . temp [ 0 ] -= maxRank ; } for ( int i = 0 ; i < startNodesCopy . size ( ) ; i ++ ) { mxGraphHierarchyNode internalNode = startNodesCopy . get ( i ) ; int currentMaxLayer = 0 ; Iterator < mxGraphHierarchyEdge > iter2 = internalNode . connectsAsSource . iterator ( ) ; while ( iter2 . hasNext ( ) ) { mxGraphHierarchyEdge internalEdge = iter2 . next ( ) ; mxGraphHierarchyNode otherNode = internalEdge . target ; internalNode . temp [ 0 ] = Math . max ( currentMaxLayer , otherNode . temp [ 0 ] + 1 ) ; currentMaxLayer = internalNode . temp [ 0 ] ; } } maxRank = SOURCESCANSTARTRANK - maxRank ; }
Basic determination of minimum layer ranking by working from from sources
 or sinks and working through each node in the relevant edge direction.
Basic determination of minimum layer ranking by working from from sources or sinks and working through each node in the relevant edge direction .
// Mark the node as not having had a layer assigned // flag to keep track of whether or not all layer determining // edges have been scanned // Work out the layer of this node from the layer determining // edges // The minimum layer number of any node connected by one of // the layer determining edges variable. If we are starting // from sources, need to start at some huge value and // normalise down afterwards // This edge has been scanned, get the layer of the // node on the other end // If all edge have been scanned, assign the layer, mark all // edges in the other direction and remove from the nodes list // Assign unique stamp ( y/m/d/h ) // Add node on other end of edge to LinkedList of // nodes to be analysed // Only add node if it hasn't been assigned a layer // Mark this other node as neither being // unassigned nor assigned so it isn't // added to this list again, but it's // layer isn't used in any calculation. // Not all the edges have been scanned, get to the back of // the class and put the dunces cap on // This is an error condition, we can't get out of // this loop. It could happen for more than one node // but that's a lot harder to detect. Log the error // TODO make log comment // Normalize the ranks down from their large starting value to place // at least 1 sink on layer 0 // Mark the node as not having had a layer assigned // Tighten the roots as far as possible // Reset the maxRank to that which would be expected for a from-sink // scan