All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cristalise.kernel.graph.model.GraphModel Maven / Gradle / Ivy

/**
 * This file is part of the CRISTAL-iSE kernel.
 * Copyright (c) 2001-2015 The CRISTAL Consortium. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * http://www.fsf.org/licensing/licenses/lgpl.html
 */
package org.cristalise.kernel.graph.model;

import java.util.Hashtable;

import org.cristalise.kernel.graph.event.ClearedEvent;
import org.cristalise.kernel.graph.event.EdgeRemovedEvent;
import org.cristalise.kernel.graph.event.EdgesChangedEvent;
import org.cristalise.kernel.graph.event.ForcedNotifyEvent;
import org.cristalise.kernel.graph.event.GraphModelEvent;
import org.cristalise.kernel.graph.event.GraphModelResizedEvent;
import org.cristalise.kernel.graph.event.NewEdgeEndPointChangedEvent;
import org.cristalise.kernel.graph.event.StartVertexIdChangedEvent;
import org.cristalise.kernel.graph.event.VertexAddedEvent;
import org.cristalise.kernel.graph.event.VertexCreatedEvent;
import org.cristalise.kernel.graph.event.VertexMovedEvent;
import org.cristalise.kernel.graph.event.VertexRemovedEvent;
import org.cristalise.kernel.graph.event.VerticesChangedEvent;
import org.cristalise.kernel.utils.Logger;


public class GraphModel {
    /* Persistent data */

    private int mWidth = 0;
    private int mHeight = 0;
    private int mNextId = 0;
    protected int mStartVertexId = -1;
    protected Hashtable mVertexHashtable = new Hashtable();
    protected Hashtable mEdgeHashtable = new Hashtable();
    private GraphableVertex mContainingVertex;

    /* Transient data */

    protected transient Vertex            mNewEdgeOriginVertex = null;
    protected transient GraphPoint        mNewEdgeEndPoint = null;

    private transient GraphModelManager mManager = null;

    /* External factories */

    private VertexFactory mExternalVertexFactory = null;
    private EdgeFactory mExternalEdgeFactory = null;

    /* Vertex outline creator */

    private VertexOutlineCreator mVertexOutlineCreator = null;

    /* Notification Events */

    private final ClearedEvent mClearedEvent = new ClearedEvent();
    private final EdgeRemovedEvent mEdgeRemovedEvent = new EdgeRemovedEvent();
    private final EdgesChangedEvent mEdgesChangedEvent = new EdgesChangedEvent();
    private final ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent();
    private final NewEdgeEndPointChangedEvent mNewEdgeEndPointChangedEvent = new NewEdgeEndPointChangedEvent();
    private final StartVertexIdChangedEvent mStartVertexIdChangedEvent = new StartVertexIdChangedEvent();
    private final VertexAddedEvent mVertexAddedEvent = new VertexAddedEvent();
    private final VertexCreatedEvent mVertexCreatedEvent = new VertexCreatedEvent();
    private final VertexMovedEvent mVertexMovedEvent = new VertexMovedEvent();
    private final VertexRemovedEvent mVertexRemovedEvent = new VertexRemovedEvent();
    private final VerticesChangedEvent mVerticesChangedEvent = new VerticesChangedEvent();
    private final GraphModelResizedEvent mGraphModelResizedEvent = new GraphModelResizedEvent();

    // Calling this constructor does not create a vertex outline creator
    // which is required by the method addVertexAndCreateId()

    private static int count=0;

    // count instances for debugging
    private int number;

    public GraphModel() {
        number=++count;

    }

    public int getNumber() {
        return number;
    }

    public void setNextId(int id) {
        mNextId = id;
    }

    public int getNextId() {
        return mNextId;
    }

    public void setManager(GraphModelManager mgr) {
        mManager = mgr;
    }

    public GraphModelManager getManager() {
        return mManager;
    }

    public GraphModel(VertexOutlineCreator vertexOutlineCreator) {
        mVertexOutlineCreator = vertexOutlineCreator;
    }

    public void setWidth(int width) {

        mWidth = width;
    }

    public int getWidth() {
        return mWidth;
    }

    public void setHeight(int height) {

        mHeight = height;
    }

    public int getHeight() {
        return mHeight;
    }

    public void checkSize(Vertex v) {
        boolean resized = false;
        GraphPoint centre = v.getCentrePoint();
        if (getWidth() < centre.x + v.getWidth()/2 +10 ) {
            setWidth( centre.x + v.getWidth()/2 +10 );
            resized = true;
        }

        if (getHeight() < centre.y + v.getHeight()/2 +10 ) {
            setHeight(centre.y + v.getHeight()/2 +10 );
            resized = true;
        }

        if (resized) {
            publishEvent(mGraphModelResizedEvent);
        }

    }

    public void setStartVertexId(int id) {
        mStartVertexId = id;
        publishEvent(mStartVertexIdChangedEvent);
    }

    public int getStartVertexId() {
        return mStartVertexId;
    }

    public Vertex getStartVertex() {
        return resolveVertex(getStartVertexId());
    }

    /**
     * @return Returns the mParentVertex.
     */
    public GraphableVertex getContainingVertex() {
        return mContainingVertex;
    }
    /**
     * @param vertex The mParentVertex to set.
     */
    public void setContainingVertex(GraphableVertex vertex) {
        mContainingVertex = vertex;
    }

    public void setVertices(Vertex[] vertices) {
        mVertexHashtable = new Hashtable();
        for (Vertex vertice : vertices) {
            mVertexHashtable.put(String.valueOf(vertice.getID()), vertice);
            checkSize(vertice);

        }
        publishEvent(mVerticesChangedEvent);
    }

    public Vertex[] getVertices() {
        Object[] vertexObjs = mVertexHashtable.values().toArray();
        Vertex[] vertices = new Vertex[vertexObjs.length];
        int i = 0;
        for (i = 0; i < vertices.length; i++) {
            vertices[i] = (Vertex)vertexObjs[i];
        }
        return vertices;
    }

    public void setEdges(DirectedEdge[] edges) {
        mEdgeHashtable = new Hashtable();
        for (DirectedEdge edge : edges) {
            mEdgeHashtable.put(String.valueOf(edge.getID()), edge);
        }
        publishEvent(mEdgesChangedEvent);
    }

    public DirectedEdge[] getEdges() {
        Object[] edgeObjs = mEdgeHashtable.values().toArray();
        DirectedEdge[] edges = new DirectedEdge[edgeObjs.length];
        int i = 0;
        for (i = 0; i < edges.length; i++) {
            edges[i] = (DirectedEdge)edgeObjs[i];
        }
        return edges;
    }

	public Vertex getVertexById(int id) {
		return mVertexHashtable.get(String.valueOf(id));
	}


    public int addEdgeAndCreateId(DirectedEdge e, int originId, int terminusId) {
        return addEdgeAndCreateId(e, resolveVertex(originId), resolveVertex(terminusId));
    }

    public int addEdgeAndCreateId(DirectedEdge e, Vertex origin, Vertex terminus) {
        e.setID(mNextId);
        e.setOriginVertexId(origin.getID());
        e.setOriginPoint(origin.getCentrePoint());
        e.setTerminusVertexId(terminus.getID());
        e.setTerminusPoint(terminus.getCentrePoint());
        origin.addOutEdgeId(mNextId);
        terminus.addInEdgeId(mNextId);
        mEdgeHashtable.put(String.valueOf(mNextId), e);
        mNextId++;
        return mNextId - 1;
    }

    // Removes an edge, but does not modify the selection
    public void removeEdge(DirectedEdge e) {
        Vertex origin = getOrigin(e);
        Vertex terminus = getTerminus(e);
        int edgeId = e.getID();
        // Remove the id of the edge from the origin and terminus vertices
        origin.removeOutEdgeId(edgeId);
        terminus.removeInEdgeId(edgeId);
        // Remove the edge
        mEdgeHashtable.remove(String.valueOf(e.getID()));
        publishEvent(mEdgeRemovedEvent);
    }

    public int addVertexAndCreateId(Vertex v, GraphPoint location) {
        if (location != null) {
	        if (mVertexOutlineCreator == null) {
	            Logger.warning("You cannot add a vertex with no outline creator");
	            return -1;
	        }
	        placeVertex(v, location);
	    }
        mVertexHashtable.put(String.valueOf(mNextId), v);
		v.setID(mNextId);
        return mNextId++;
    }

    public void placeVertex(Vertex v, GraphPoint location) {
        v.setCentrePoint(location);
        if (mVertexOutlineCreator != null) {
            mVertexOutlineCreator.setOutline(v);
        }
        publishEvent(mVertexAddedEvent);
        checkSize(v);
    }

    // Removes a vertex, but does not modify the selection
    public void removeVertex(Vertex v) {
        DirectedEdge[] inEdges = getInEdges(v);
        DirectedEdge[] outEdges = getOutEdges(v);
        Vertex origin = null;
        Vertex terminus = null;
        int edgeId = -1;
        int i = 0;
        // For each in edge
        for (i = 0; i < inEdges.length; i++) {
            edgeId = inEdges[i].getID();
            origin = getOrigin(inEdges[i]);
            // Remove the id of the edge from the origin vertex
            origin.removeOutEdgeId(edgeId);
            // Remove the edge
            mEdgeHashtable.remove(String.valueOf(edgeId));
        }
        // Remove all the out edges
        for (i = 0; i < outEdges.length; i++) {
            edgeId = outEdges[i].getID();
            terminus = getTerminus(outEdges[i]);
            // Remove the id of the edge from the terminus vertex
            terminus.removeInEdgeId(edgeId);
            // Remove the edge
            mEdgeHashtable.remove(String.valueOf(edgeId));
        }
        // Remove the vertex
        mVertexHashtable.remove(String.valueOf(v.getID()));
        publishEvent(mVertexRemovedEvent);
    }

    public void moveAbsoluteVertex(Vertex v, GraphPoint p) {
        // Make sure the new position stays within the graph
        if (p.x < 0) p.x = 0;
        if (p.y < 0) p.y = 0;
        if (p.x > mWidth) p.x = mWidth;
        if (p.y > mHeight) p.y = mHeight;
        moveAbsoluteVertexAndConnectingEdges(v, p);
        publishEvent(mVertexMovedEvent);
    }

    private void moveAbsoluteVertexAndConnectingEdges(Vertex v, GraphPoint p) {
        DirectedEdge[] inEdges = getInEdges(v);
        DirectedEdge[] outEdges = getOutEdges(v);
        int i = 0;
        // Move the vertex to the new position
        v.moveAbsolute(p);
        // Move the ends of the incoming edges to the new position
        for (i = 0; i < inEdges.length; i++) {
            inEdges[i].setTerminusPoint(p);
        }
        // Move the ends of the outgoing edges to the new position
        for (i = 0; i < outEdges.length; i++) {
            outEdges[i].setOriginPoint(p);
        }
        checkSize(v);
    }



    public Vertex resolveVertex(int id) {
        return mVertexHashtable.get(String.valueOf(id));
    }

    public DirectedEdge resolveEdge(int id) {
        return mEdgeHashtable.get(String.valueOf(id));
    }

    public DirectedEdge[] getInEdges(Vertex v) {
        int[] ids = v.getInEdgeIds();
        return resolveEdges(ids);
    }

    public DirectedEdge[] getOutEdges(Vertex v) {
        int[] ids = v.getOutEdgeIds();
        return resolveEdges(ids);
    }

    private DirectedEdge[] resolveEdges(int[] ids) {
        DirectedEdge[] edges = new DirectedEdge[ids.length];
        int i = 0;
        for (i = 0; i < ids.length; i++) {
            edges[i] = resolveEdge(ids[i]);
        }
        return edges;
    }

    public Vertex getOrigin(DirectedEdge e) {
        return resolveVertex(e.getOriginVertexId());
    }

    public Vertex getTerminus(DirectedEdge e) {
        return resolveVertex(e.getTerminusVertexId());
    }

    public Vertex[] getInVertices(Vertex v) {
        DirectedEdge[] inEdges = getInEdges(v);
        Vertex[] inVertices = new Vertex[inEdges.length];
        int i = 0;
        for (i = 0; i < inEdges.length; i++) {
            inVertices[i] = getOrigin(inEdges[i]);
        }
        return inVertices;
    }

    public Vertex[] getOutVertices(Vertex v) {
        DirectedEdge[] outEdges = getOutEdges(v);
        Vertex[] outVertices = new Vertex[outEdges.length];
        int i = 0;
        for (i = 0; i < outEdges.length; i++) {
            outVertices[i] = getTerminus(outEdges[i]);
        }
        return outVertices;
    }

    public DirectedEdge[] getConnectingEdges(int originVertexId, int terminusVertexId) {
        Vertex origin = resolveVertex(originVertexId);
        DirectedEdge[] outEdges = null;
        int numEdgesFound = 0;
        DirectedEdge[] edgesFound = null;
        int i = 0;
        int j = 0;
        if (origin == null) return null;
        outEdges = getOutEdges(origin);
        for (i = 0; i < outEdges.length; i++) {
            if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
                numEdgesFound++;
            }
        }
        edgesFound = new DirectedEdge[numEdgesFound];
        for (i = 0; i < outEdges.length; i++) {
            if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
                edgesFound[j] = outEdges[i];
                j++;
            }
        }
        return edgesFound;
    }

    public void clearTags(Object tag) {
        Vertex vertex = null;
        Object[] vertexObjs = mVertexHashtable.values().toArray();
        int i = 0;
        for (i = 0; i < vertexObjs.length; i++) {
            vertex = (Vertex)vertexObjs[i];
            vertex.clearTag(tag);
        }
    }

    public void forceNotify() {
        publishEvent(mForcedNotifyEvent);
    }

    public void clear() {
        mVertexHashtable = new Hashtable();
        mEdgeHashtable = new Hashtable();
        mStartVertexId = -1;
        publishEvent(mClearedEvent);
    }



    public void setNewEdgeOriginVertex(Vertex v) {
        mNewEdgeOriginVertex = v;
    }

    public Vertex getNewEdgeOriginVertex() {
        return mNewEdgeOriginVertex;
    }

    public void setNewEdgeEndPoint(GraphPoint p) {
        mNewEdgeEndPoint = p;
        publishEvent(mNewEdgeEndPointChangedEvent);
    }

    public GraphPoint getNewEdgeEndPoint() {
        return mNewEdgeEndPoint;
    }

    public void setExternalVertexFactory(VertexFactory factory) {
        mExternalVertexFactory = factory;
    }

    public void createVertex(GraphPoint location, TypeNameAndConstructionInfo typeNameAndConstructionInfo) throws Exception {
        if (mExternalVertexFactory != null) {
            mExternalVertexFactory.create(mManager, location, typeNameAndConstructionInfo);
            publishEvent(mVertexCreatedEvent);
        }
    }

    private void publishEvent(GraphModelEvent event) {
		if (mManager!=null)
			mManager.notifyObservers(event);
		
	}

	public void setExternalEdgeFactory(EdgeFactory factory) {
        mExternalEdgeFactory = factory;
    }

    public void setVertexOutlineCreator(VertexOutlineCreator outlineCreator) {
        mVertexOutlineCreator = outlineCreator;
    }

    public void createDirectedEdge(Vertex origin, Vertex terminus, TypeNameAndConstructionInfo typeNameAndConstructionInfo) {
        if (mExternalEdgeFactory != null) {
            mExternalEdgeFactory.create(mManager, origin, terminus, typeNameAndConstructionInfo);
        }
    }



    public void resetVertexOutlines() {
        Vertex[] vertices = getVertices();
        int i = 0;
        for (i = 0; i < vertices.length; i++) {
            mVertexOutlineCreator.setOutline(vertices[i]);
        }
    }

    public void setGraphModelCastorData(GraphModelCastorData data) {
        int i = 0;

        // Create and populate the vertex hashtable
        mVertexHashtable = new Hashtable();
        for (i = 0; i < data.mVertexImpls.length; i++) {
            mVertexHashtable.put(String.valueOf(data.mVertexImpls[i].getID()), data.mVertexImpls[i]);
            checkSize(data.mVertexImpls[i]);
        }
        // Create and populate the edge hastable
        mEdgeHashtable = new Hashtable();
        for (i = 0; i < data.mEdgeImpls.length; i++) {
            mEdgeHashtable.put(String.valueOf(data.mEdgeImpls[i].getID()), data.mEdgeImpls[i]);
        }
        // Set the start vertex id and the id generation counter
        mStartVertexId = data.mStartVertexId;
        mNextId = data.mNextId;
    }

    public GraphModelCastorData getGraphModelCastorData() {
        Object[] vertexObjs = mVertexHashtable.values().toArray();
        Vertex[] vertexImpls = new Vertex[vertexObjs.length];
        Object[] edgeObjs = mEdgeHashtable.values().toArray();
        DirectedEdge[] directedEdgeImpls = new DirectedEdge[edgeObjs.length];
        String className = null;
        int i = 0;
        // Put in the vertices
        for (i = 0; i < vertexImpls.length; i++) {
            vertexImpls[i] = (Vertex)vertexObjs[i];
        }
        // Put in the edges
        for (i = 0; i < directedEdgeImpls.length; i++) {
            directedEdgeImpls[i] = (DirectedEdge)edgeObjs[i];
        }
        // Disable persistency of the vertex outline creator: determined by container
        // Determine the class name of the vertex outline creator
//        if (mVertexOutlineCreator == null) {
//            className = "";
//        }
//        else {
//            className = mVertexOutlineCreator.getClass().getName();
//        }
        return new GraphModelCastorData(className, vertexImpls, directedEdgeImpls, mStartVertexId, mNextId);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy