public mxGraphHierarchyModel(mxHierarchicalLayout layout,
			Object[] vertices, List<Object> roots, Object parent,
			boolean ordered, boolean deterministic, boolean scanRanksFromSinks)
	{
		mxGraph graph = layout.getGraph();
		this.deterministic = deterministic;
		this.scanRanksFromSinks = scanRanksFromSinks;
		this.roots = roots;
		this.parent = parent;

		if (vertices == null)
		{
			vertices = graph.getChildVertices(parent);
		}

		if (ordered)
		{
			formOrderedHierarchy(layout, vertices, parent);
		}
		else
		{
			// map of cells to internal cell needed for second run through
			// to setup the sink of edges correctly. Guess size by number
			// of edges is roughly same as number of vertices.
			vertexMapper = new Hashtable<Object, mxGraphHierarchyNode>(
					vertices.length);
			edgeMapper = new Hashtable<Object, mxGraphHierarchyEdge>(
					vertices.length);
			if (scanRanksFromSinks)
			{
				maxRank = 0;
			}
			else
			{
				maxRank = SOURCESCANSTARTRANK;
			}
			mxGraphHierarchyNode[] internalVertices = new mxGraphHierarchyNode[vertices.length];
			createInternalCells(layout, vertices, internalVertices);

			// Go through edges set their sink values. Also check the
			// ordering if and invert edges if necessary
			for (int i = 0; i < vertices.length; i++)
			{
				Collection<mxGraphHierarchyEdge> edges = internalVertices[i].connectsAsSource;
				Iterator<mxGraphHierarchyEdge> iter = edges.iterator();

				while (iter.hasNext())
				{
					mxGraphHierarchyEdge internalEdge = iter.next();
					Collection<Object> realEdges = internalEdge.edges;
					Iterator<Object> iter2 = realEdges.iterator();

					if (iter2.hasNext())
					{
						Object realEdge = iter2.next();
						Object targetCell = graph.getView().getVisibleTerminal(
								realEdge, false);
						mxGraphHierarchyNode internalTargetCell = vertexMapper
								.get(targetCell);

						if (internalTargetCell != null
								&& internalVertices[i] != internalTargetCell)
						{
							internalEdge.target = internalTargetCell;

							if (internalTargetCell.connectsAsTarget.size() == 0)
							{
								internalTargetCell.connectsAsTarget = new LinkedHashSet<mxGraphHierarchyEdge>(
										4);
							}

							internalTargetCell.connectsAsTarget
									.add(internalEdge);
						}
					}
				}

				// Use the temp variable in the internal nodes to mark this
				// internal vertex as having been visited.
				internalVertices[i].temp[0] = 1;
			}
		}
	}