/* * Copyright (c) 2005, David Benson * * All rights reserved. * * This file is licensed under the JGraph software license, a copy of which * will have been provided to you in the file LICENSE at the root of your * installation directory. If you are unable to locate this file please * contact JGraph sales for another copy. */ package com.mxgraph.layout.hierarchical.model; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; /** * An abstraction of an internal node in the hierarchy layout */ public class mxGraphHierarchyNode extends mxGraphAbstractHierarchyCell { /** * Shared empty connection map to return instead of null in applyMap. */ public static Collection<mxGraphHierarchyEdge> emptyConnectionMap = new ArrayList<mxGraphHierarchyEdge>(0); /** * The graph cell this object represents. */ public Object cell = null; /** * Collection of hierarchy edges that have this node as a target */ public Collection<mxGraphHierarchyEdge> connectsAsTarget = emptyConnectionMap; /** * Collection of hierarchy edges that have this node as a source */ public Collection<mxGraphHierarchyEdge> connectsAsSource = emptyConnectionMap; /** * Assigns a unique hashcode for each node. Used by the model dfs instead * of copying HashSets */ public int[] hashCode; /** * Constructs an internal node to represent the specified real graph cell * @param cell the real graph cell this node represents */ public mxGraphHierarchyNode(Object cell) { this.cell = cell; } /** * Returns the integer value of the layer that this node resides in * @return the integer value of the layer that this node resides in */ public int getRankValue() { return maxRank; } /** * Returns the cells this cell connects to on the next layer up * @param layer the layer this cell is on * @return the cells this cell connects to on the next layer up */ @SuppressWarnings("unchecked") public List<mxGraphAbstractHierarchyCell> getNextLayerConnectedCells(int layer) { if (nextLayerConnectedCells == null) { nextLayerConnectedCells = new ArrayList[1]; nextLayerConnectedCells[0] = new ArrayList<mxGraphAbstractHierarchyCell>(connectsAsTarget.size()); Iterator<mxGraphHierarchyEdge> iter = connectsAsTarget.iterator(); while (iter.hasNext()) { mxGraphHierarchyEdge edge = iter.next(); if (edge.maxRank == -1 || edge.maxRank == layer + 1) { // Either edge is not in any rank or // no dummy nodes in edge, add node of other side of edge nextLayerConnectedCells[0].add(edge.source); } else { // Edge spans at least two layers, add edge nextLayerConnectedCells[0].add(edge); } } } return nextLayerConnectedCells[0]; } /** * Returns the cells this cell connects to on the next layer down * @param layer the layer this cell is on * @return the cells this cell connects to on the next layer down */ @SuppressWarnings("unchecked") public List<mxGraphAbstractHierarchyCell> getPreviousLayerConnectedCells(int layer) { if (previousLayerConnectedCells == null) { previousLayerConnectedCells = new ArrayList[1]; previousLayerConnectedCells[0] = new ArrayList<mxGraphAbstractHierarchyCell>(connectsAsSource .size()); Iterator<mxGraphHierarchyEdge> iter = connectsAsSource.iterator(); while (iter.hasNext()) { mxGraphHierarchyEdge edge = iter.next(); if (edge.minRank == -1 || edge.minRank == layer - 1) { // No dummy nodes in edge, add node of other side of edge previousLayerConnectedCells[0].add(edge.target); } else { // Edge spans at least two layers, add edge previousLayerConnectedCells[0].add(edge); } } } return previousLayerConnectedCells[0]; } /** * * @return whether or not this cell is an edge */ public boolean isEdge() { return false; } /** * * @return whether or not this cell is a node */ public boolean isVertex() { return true; } /** * Gets the value of temp for the specified layer * * @param layer * the layer relating to a specific entry into temp * @return the value for that layer */ public int getGeneralPurposeVariable(int layer) { return temp[0]; } /** * Set the value of temp for the specified layer * * @param layer * the layer relating to a specific entry into temp * @param value * the value for that layer */ public void setGeneralPurposeVariable(int layer, int value) { temp[0] = value; } public boolean isAncestor(mxGraphHierarchyNode otherNode) { // Firstly, the hash code of this node needs to be shorter than the // other node if (otherNode != null && hashCode != null && otherNode.hashCode != null && hashCode.length < otherNode.hashCode.length) { if (hashCode == otherNode.hashCode) { return true; } if (hashCode == null) { return false; } // Secondly, this hash code must match the start of the other // node's hash code. Arrays.equals cannot be used here since // the arrays are different length, and we do not want to // perform another array copy. for (int i = 0; i < hashCode.length; i++) { if (hashCode[i] != otherNode.hashCode[i]) { return false; } } return true; } return false; } }