jgraphmodeladapter.java

来自「JAVA图论的算法包。用过觉得还不错」· Java 代码 · 共 1,149 行 · 第 1/3 页

JAVA
1,149
字号
     *
     * @return the JGraph edge cell that corresponds to the specified JGraphT
     * edge, or <code>null</code> if no corresponding cell found.
     */
    public DefaultEdge getEdgeCell(E jGraphTEdge)
    {
        return (DefaultEdge) edgeToCell.get(jGraphTEdge);
    }

    /**
     * Returns the JGraph vertex cell that corresponds to the specified JGraphT
     * vertex. If no corresponding cell found, returns <code>null</code>.
     *
     * @param jGraphTVertex a JGraphT vertex of the JGraphT graph.
     *
     * @return the JGraph vertex cell that corresponds to the specified JGraphT
     * vertex, or <code>null</code> if no corresponding cell found.
     */
    public DefaultGraphCell getVertexCell(Object jGraphTVertex)
    {
        return (DefaultGraphCell) vertexToCell.get(jGraphTVertex);
    }

    /**
     * Returns the JGraph port cell that corresponds to the specified JGraphT
     * vertex. If no corresponding port found, returns <code>null</code>.
     *
     * @param jGraphTVertex a JGraphT vertex of the JGraphT graph.
     *
     * @return the JGraph port cell that corresponds to the specified JGraphT
     * vertex, or <code>null</code> if no corresponding cell found.
     */
    public DefaultPort getVertexPort(Object jGraphTVertex)
    {
        DefaultGraphCell vertexCell = getVertexCell(jGraphTVertex);

        if (vertexCell == null) {
            return null;
        } else {
            return (DefaultPort) vertexCell.getChildAt(0);
        }
    }

    /**
     * Adds/removes an edge to/from the underlying JGraphT graph according to
     * the change in the specified JGraph edge. If both vertices are connected,
     * we ensure to have a corresponding JGraphT edge. Otherwise, we ensure NOT
     * to have a corresponding JGraphT edge.
     *
     * <p>This method is to be called only for edges that have already been
     * changed in the JGraph graph.</p>
     *
     * @param jEdge the JGraph edge that has changed.
     */
    void handleJGraphChangedEdge(org.jgraph.graph.Edge jEdge)
    {
        if (isDangling(jEdge)) {
            if (cellToEdge.containsKey(jEdge)) {
                // a non-dangling edge became dangling -- remove the JGraphT
                // edge by faking as if the edge is removed from the JGraph.
                // TODO: Consider keeping the JGraphT edges outside the graph
                // to avoid loosing user data, such as weights.
                handleJGraphRemovedEdge(jEdge);
            } else {
                // a dangling edge is still dangling -- just ignore.
            }
        } else {
            // edge is not dangling
            if (cellToEdge.containsKey(jEdge)) {
                // edge already has a corresponding JGraphT edge.
                // check if any change to its endpoints.
                E jtEdge = cellToEdge.get(jEdge);

                Object jSource = getSourceVertex(this, jEdge);
                Object jTarget = getTargetVertex(this, jEdge);

                Object jtSource = cellToVertex.get(jSource);
                Object jtTarget = cellToVertex.get(jTarget);

                if ((jtGraph.getEdgeSource(jtEdge) == jtSource)
                    && (jtGraph.getEdgeTarget(jtEdge) == jtTarget))
                {
                    // no change in edge's endpoints -- nothing to do.
                } else {
                    // edge's end-points have changed -- need to refresh the
                    // JGraphT edge. Refresh by faking as if the edge has been
                    // removed from JGraph and then added again.
                    // ALSO HERE: consider an alternative that maintains user
                    // data
                    handleJGraphRemovedEdge(jEdge);
                    handleJGraphInsertedEdge(jEdge);
                }
            } else {
                // a new edge
                handleJGraphInsertedEdge(jEdge);
            }
        }
    }

    /**
     * Adds to the underlying JGraphT graph an edge that corresponds to the
     * specified JGraph edge. If the specified JGraph edge is a dangling edge,
     * it is NOT added to the underlying JGraphT graph.
     *
     * <p>This method is to be called only for edges that have already been
     * added to the JGraph graph.</p>
     *
     * @param jEdge the JGraph edge that has been added.
     */
    void handleJGraphInsertedEdge(org.jgraph.graph.Edge jEdge)
    {
        if (isDangling(jEdge)) {
            // JGraphT forbid dangling edges so we cannot add the edge yet. If
            // later the edge becomes connected, we will add it.
        } else {
            // FIXME hb 28-nov-05: waiting for jgraph to go generic
            Object jSource = getSourceVertex(this, jEdge);
            Object jTarget = getTargetVertex(this, jEdge);

            V jtSource = cellToVertex.get(jSource);
            V jtTarget = cellToVertex.get(jTarget);

            E jtEdge = jtGraph.addEdge(jtSource, jtTarget);

            if (jtEdge != null) {
                cellToEdge.put(jEdge, jtEdge);
                edgeToCell.put(jtEdge, jEdge);
            } else {
                // Adding failed because user is using a JGraphT graph the
                // forbids parallel edges.
                // For consistency, we remove the edge from the JGraph too.
                internalRemoveCell(jEdge);
                System.err.println(
                    "Warning: an edge was deleted because the underlying "
                    + "JGraphT graph refused to create it. "
                    + "This situation can happen when a constraint of the "
                    + "underlying graph is violated, e.g., an attempt to add "
                    + "a parallel edge or a self-loop to a graph that forbids "
                    + "them. To avoid this message, make sure to use a "
                    + "suitable underlying JGraphT graph.");
            }
        }
    }

    /**
     * Adds to the underlying JGraphT graph a vertex corresponding to the
     * specified JGraph vertex. In JGraph, two vertices with the same user
     * object are in principle allowed; in JGraphT, this would lead to duplicate
     * vertices, which is not allowed. So if such vertex already exists, the
     * specified vertex is REMOVED from the JGraph graph and a a warning is
     * printed.
     *
     * <p>This method is to be called only for vertices that have already been
     * added to the JGraph graph.</p>
     *
     * @param jVertex the JGraph vertex that has been added.
     */
    @SuppressWarnings("unchecked")
    void handleJGraphInsertedVertex(GraphCell jVertex)
    {
        V jtVertex;

        if (jVertex instanceof DefaultGraphCell) {
            // FIXME hb 28-nov-05: waiting for jgraph to go generic
            jtVertex = (V) ((DefaultGraphCell) jVertex).getUserObject();
        } else {
            // FIXME: Why toString? Explain if for a good reason otherwise fix.
            jtVertex = (V) jVertex.toString();
        }

        if (vertexToCell.containsKey(jtVertex)) {
            // We have to remove the new vertex, because it would lead to
            // duplicate vertices. We can't use ShieldedGraph.removeVertex for
            // that, because it would remove the wrong (existing) vertex.
            System.err.println(
                "Warning: detected two JGraph vertices with "
                + "the same JGraphT vertex as user object. It is an "
                + "indication for a faulty situation that should NOT happen."
                + "Removing vertex: " + jVertex);
            internalRemoveCell(jVertex);
        } else {
            jtGraph.addVertex(jtVertex);

            cellToVertex.put(jVertex, jtVertex);
            vertexToCell.put(jtVertex, jVertex);
        }
    }

    /**
     * Removes the edge corresponding to the specified JGraph edge from the
     * JGraphT graph. If the specified edge is not contained in {@link
     * #cellToEdge}, it is silently ignored.
     *
     * <p>This method is to be called only for edges that have already been
     * removed from the JGraph graph.</p>
     *
     * @param jEdge the JGraph edge that has been removed.
     */
    void handleJGraphRemovedEdge(org.jgraph.graph.Edge jEdge)
    {
        if (cellToEdge.containsKey(jEdge)) {
            E jtEdge = cellToEdge.get(jEdge);

            jtGraph.removeEdge(jtEdge);

            cellToEdge.remove(jEdge);
            edgeToCell.remove(jtEdge);
        }
    }

    /**
     * Removes the vertex corresponding to the specified JGraph vertex from the
     * JGraphT graph. If the specified vertex is not contained in {@link
     * #cellToVertex}, it is silently ignored.
     *
     * <p>If any edges are incident with this vertex, we first remove them from
     * the both graphs, because otherwise the JGraph graph would leave them
     * intact and the JGraphT graph would throw them out. TODO: Revise this
     * behavior now that we gracefully tolerate dangling edges. It might be
     * possible to remove just the JGraphT edges. The JGraph edges will be left
     * dangling, as a result.</p>
     *
     * <p>This method is to be called only for vertices that have already been
     * removed from the JGraph graph.</p>
     *
     * @param jVertex the JGraph vertex that has been removed.
     */
    void handleJGraphRemovedVertex(GraphCell jVertex)
    {
        if (cellToVertex.containsKey(jVertex)) {
            V jtVertex = cellToVertex.get(jVertex);
            Set<E> jtIncidentEdges = jtGraph.edgesOf(jtVertex);

            if (!jtIncidentEdges.isEmpty()) {
                // We can't just call removeAllEdges with this list: that
                // would throw a ConcurrentModificationException. So we create
                // a shallow copy.
                // This also triggers removal of the corresponding JGraph
                // edges.
                jtGraph.removeAllEdges(new ArrayList<E>(jtIncidentEdges));
            }

            jtGraph.removeVertex(jtVertex);

            cellToVertex.remove(jVertex);
            vertexToCell.remove(jtVertex);
        }
    }

    /**
     * Adds the specified JGraphT edge to be reflected by this graph model. To
     * be called only for edges that already exist in the JGraphT graph.
     *
     * @param jtEdge a JGraphT edge to be reflected by this graph model.
     */
    void handleJGraphTAddedEdge(E jtEdge)
    {
        DefaultEdge edgeCell = cellFactory.createEdgeCell(jtEdge);
        edgeToCell.put(jtEdge, edgeCell);
        cellToEdge.put(edgeCell, jtEdge);

        ConnectionSet cs = new ConnectionSet();
        cs.connect(
            edgeCell,
            getVertexPort(jtGraph.getEdgeSource(jtEdge)),
            getVertexPort(jtGraph.getEdgeTarget(jtEdge)));

        internalInsertCell(edgeCell, createEdgeAttributeMap(edgeCell), cs);
    }

    /**
     * Adds the specified JGraphT vertex to be reflected by this graph model. To
     * be called only for edges that already exist in the JGraphT graph.
     *
     * @param jtVertex a JGraphT vertex to be reflected by this graph model.
     */
    void handleJGraphTAddedVertex(V jtVertex)
    {
        DefaultGraphCell vertexCell = cellFactory.createVertexCell(jtVertex);
        vertexCell.add(new DefaultPort());

        vertexToCell.put(jtVertex, vertexCell);
        cellToVertex.put(vertexCell, jtVertex);

        internalInsertCell(
            vertexCell,
            createVertexAttributeMap(vertexCell),
            null);
    }

    /**
     * Removes the specified JGraphT vertex from being reflected by this graph
     * model. To be called only for vertices that have already been removed from
     * the JGraphT graph.
     *
     * @param jtVertex a JGraphT vertex to be removed from being reflected by
     * this graph model.
     */
    void handleJGraphTRemoveVertex(Object jtVertex)
    {
        DefaultGraphCell vertexCell =
            (DefaultGraphCell) vertexToCell.remove(jtVertex);
        cellToVertex.remove(vertexCell);

        List<Object> ports = new ArrayList<Object>();

        for (Object child : vertexCell.getChildren()) {
            if (this.isPort(child)) {
                ports.add(child);
            }
        }
        this.remove(ports.toArray());

        internalRemoveCell(vertexCell);
    }

    /**
     * Removes the specified JGraphT edge from being reflected by this graph
     * model. To be called only for edges that have already been removed from
     * the JGraphT graph.
     *
     * @param jtEdge a JGraphT edge to be removed from being reflected by this
     * graph model.
     */
    void handleJGraphTRemovedEdge(E jtEdge)
    {
        DefaultEdge edgeCell = (DefaultEdge) edgeToCell.remove(jtEdge);
        cellToEdge.remove(edgeCell);
        internalRemoveCell(edgeCell);
    }

    /**
     * Tests if the specified JGraph edge is 'dangling', that is having at least
     * one endpoint which is not connected to a vertex.
     *
     * @param jEdge the JGraph edge to be tested for being dangling.
     *
     * @return <code>true</code> if the specified edge is dangling, otherwise
     * <code>false</code>.
     */
    private boolean isDangling(org.jgraph.graph.Edge jEdge)
    {
        Object jSource = getSourceVertex(this, jEdge);
        Object jTarget = getTargetVertex(this, jEdge);

        return !cellToVertex.containsKey(jSource)
            || !cellToVertex.containsKey(jTarget);
    }

    @SuppressWarnings("unchecked")
    private AttributeMap createEdgeAttributeMap(DefaultEdge edgeCell)
    {
        AttributeMap attrs = new AttributeMap();

        // FIXME hb 28-nov-05: waiting for graph to go generic
        attrs.put(edgeCell, getDefaultEdgeAttributes().clone());

        return attrs;
    }

    @SuppressWarnings("unchecked")
    private AttributeMap createVertexAttributeMap(GraphCell vertexCell)
    {
        AttributeMap attrs = new AttributeMap();

        // FIXME hb 28-nov-05: waiting for graph to go generic
        attrs.put(vertexCell, getDefaultVertexAttributes().clone());

        return attrs;
    }

    /**
     * Inserts the specified cell into the JGraph graph model.
     *
     * @param cell
     * @param attrs
     * @param cs
     */
    // FIXME hb 28-nov-05: waiting for graph to go generic
    private void internalInsertCell(
        GraphCell cell,
        AttributeMap attrs,
        ConnectionSet cs)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?