public class Commands
{

    private static final Logger LOGGER = LoggerFactory.getLogger(Commands.class);

    private static final EReference NODES = GraphPackage.Literals.GMODEL__NODES;
    private static final EReference CONNECTIONS = GraphPackage.Literals.GMODEL__CONNECTIONS;

    private static final EAttribute NODE_X = GraphPackage.Literals.GNODE__X;
    private static final EAttribute NODE_Y = GraphPackage.Literals.GNODE__Y;
    private static final EAttribute NODE_WIDTH = GraphPackage.Literals.GNODE__WIDTH;
    private static final EAttribute NODE_HEIGHT = GraphPackage.Literals.GNODE__HEIGHT;
    private static final EReference NODE_CONNECTORS = GraphPackage.Literals.GNODE__CONNECTORS;

    private static final EReference CONNECTOR_CONNECTIONS = GraphPackage.Literals.GCONNECTOR__CONNECTIONS;

    private static final EAttribute JOINT_X = GraphPackage.Literals.GJOINT__X;
    private static final EAttribute JOINT_Y = GraphPackage.Literals.GJOINT__Y;

    /**
     * Static class, not to be instantiated.
     */
    private Commands()
    {
    }

    /**
     * Adds a node to the model.
     *
     * <p>
     * The node's x, y, width, and height values should be set before calling this method.
     * </p>
     *
     * @param model the {@link GModel} to which the node should be added
     * @param node the {@link GNode} to add to the model
     */
    public static void addNode(final GModel model, final GNode node)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null)
        {
            final Command command = AddCommand.create(editingDomain, model, NODES, node);

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Removes a node from the model.
     *
     * <p>
     * Also removes any connections that were attached to the node.
     * </p>
     *
     * @param model the {@link GModel} from which the node should be removed
     * @param node the {@link GNode} to remove from the model
     */
    public static void removeNode(final GModel model, final GNode node)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();
            command.append(RemoveCommand.create(editingDomain, model, NODES, node));

            final List<GConnection> connectionsToDelete = new ArrayList<>();

            for (final GConnector connector : node.getConnectors())
            {
                for (final GConnection connection : connector.getConnections())
                {
                    if (connection != null && !connectionsToDelete.contains(connection))
                    {
                        connectionsToDelete.add(connection);
                    }
                }
            }

            for (final GConnection connection : connectionsToDelete)
            {
                command.append(RemoveCommand.create(editingDomain, model, CONNECTIONS, connection));

                final GConnector source = connection.getSource();
                final GConnector target = connection.getTarget();

                if (!node.equals(source.getParent()))
                {
                    command.append(RemoveCommand.create(editingDomain, source, CONNECTOR_CONNECTIONS, connection));
                }

                if (!node.equals(target.getParent()))
                {
                    command.append(RemoveCommand.create(editingDomain, target, CONNECTOR_CONNECTIONS, connection));
                }
            }

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Clears everything in the given model.
     *
     * @param model the {@link GModel} to be cleared
     */
    public static void clear(final GModel model)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            command.append(RemoveCommand.create(editingDomain, model, CONNECTIONS, model.getConnections()));
            command.append(RemoveCommand.create(editingDomain, model, NODES, model.getNodes()));

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Removes all connectors from the given nodes, and all connections attached to them.
     *
     * @param model the {@link GModel} being edited
     * @param nodes a list of {@link GNode} instances whose connectors should be removed
     */
    public static void clearConnectors(final GModel model, final List<GNode> nodes)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            final Set<GConnection> connectionsToRemove = new HashSet<>();
            final Set<GConnector> connectorsToRemove = new HashSet<>();

            for (final GNode node : nodes)
            {
                command.append(RemoveCommand.create(editingDomain, node, NODE_CONNECTORS, node.getConnectors()));
                connectorsToRemove.addAll(node.getConnectors());

                for (final GConnector connector : node.getConnectors())
                {
                    connectionsToRemove.addAll(connector.getConnections());
                }
            }

            for (final GConnection connection : connectionsToRemove)
            {
                final GConnector source = connection.getSource();
                final GConnector target = connection.getTarget();

                if (!connectorsToRemove.contains(source))
                {
                    command.append(RemoveCommand.create(editingDomain, source, CONNECTOR_CONNECTIONS, connection));
                }

                if (!connectorsToRemove.contains(target))
                {
                    command.append(RemoveCommand.create(editingDomain, target, CONNECTOR_CONNECTIONS, connection));
                }
            }

            command.append(RemoveCommand.create(editingDomain, model, CONNECTIONS, connectionsToRemove));

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Updates the model's layout values to match those in the skin instances.
     *
     * <p>
     * This method adds set operations to the given compound command but does <b>not</b> execute it.
     * </p>
     *
     * @param command a {@link CompoundCommand} to which the set commands will be added
     * @param model the {@link GModel} whose layout values should be updated
     * @param skinLookup the {@link SkinLookup} in use for this graph editor instance
     */
    public static void updateLayoutValues(final CompoundCommand command, final GModel model,
            final SkinLookup skinLookup)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null)
        {
            for (final GNode node : model.getNodes())
            {
                final GNodeSkin nodeSkin = skinLookup.lookupNode(node);
                if (nodeSkin != null && checkNodeChanged(node, nodeSkin))
                {
                    final Region nodeRegion = nodeSkin.getRoot();
                    command.append(SetCommand.create(editingDomain, node, NODE_X, nodeRegion.getLayoutX()));
                    command.append(SetCommand.create(editingDomain, node, NODE_Y, nodeRegion.getLayoutY()));
                    command.append(SetCommand.create(editingDomain, node, NODE_WIDTH, nodeRegion.getWidth()));
                    command.append(SetCommand.create(editingDomain, node, NODE_HEIGHT, nodeRegion.getHeight()));
                }
            }

            for (final GConnection connection : model.getConnections())
            {
                updateConnector(connection.getSource(), command, editingDomain, skinLookup);
                updateConnector(connection.getTarget(), command, editingDomain, skinLookup);

                for (final GJoint joint : connection.getJoints())
                {
                    final GJointSkin jointSkin = skinLookup.lookupJoint(joint);
                    if (jointSkin != null && checkJointChanged(joint, jointSkin))
                    {
                        final Region jointRegion = jointSkin.getRoot();
                        final double x = jointRegion.getLayoutX() + jointSkin.getWidth() / 2;
                        final double y = jointRegion.getLayoutY() + jointSkin.getHeight() / 2;

                        command.append(SetCommand.create(editingDomain, joint, JOINT_X, x));
                        command.append(SetCommand.create(editingDomain, joint, JOINT_Y, y));
                    }
                }
            }
        }
    }

    private static void updateConnector(final GConnector connector, final CompoundCommand command,
            final EditingDomain editingDomain, final SkinLookup skinLookup)
    {
        final GNode node = connector.getParent();
        final GConnectorSkin connectorSkin = skinLookup.lookupConnector(connector);
        final GNodeSkin nodeSkin = skinLookup.lookupNode(node);
        if (nodeSkin != null && connectorSkin != null)
        {
            final Point2D connectorPosition = nodeSkin.getConnectorPosition(connectorSkin);
            if (checkConnectorChanged(connector, connectorPosition))
            {
                command.append(SetCommand.create(editingDomain, connector, GraphPackage.Literals.GCONNECTOR__X,
                        connectorPosition.getX()));
                command.append(SetCommand.create(editingDomain, connector, GraphPackage.Literals.GCONNECTOR__Y,
                        connectorPosition.getY()));
            }
        }
    }

    /**
     * Checks if a connector's JavaFX region has different layout values than those
     * currently stored in the model.
     *
     * @param connector
     *            the model instance for the connector
     *
     * @return {@code true} if any layout value has changed, {@code false if not}
     */
    private static boolean checkConnectorChanged(final GConnector connector, final Point2D connectorPosition)
    {
        if (connectorPosition.getX() != connector.getX())
        {
            return true;
        }
        else if (connectorPosition.getY() != connector.getY())
        {
            return true;
        }
        return false;
    }

    /**
     * Checks if a node's JavaFX region has different layout values than those
     * currently stored in the model.
     *
     * @param node
     *            the model instance for the node
     *
     * @return {@code true} if any layout value has changed,
     *         {@code false if not}
     */
    private static boolean checkNodeChanged(final GNode node, final GNodeSkin nodeSkin)
    {
        final Region nodeRegion = nodeSkin.getRoot();

        if (nodeRegion.getLayoutX() != node.getX())
        {
            return true;
        }
        else if (nodeRegion.getLayoutY() != node.getY())
        {
            return true;
        }
        else if (nodeRegion.getWidth() != node.getWidth())
        {
            return true;
        }
        else if (nodeRegion.getHeight() != node.getHeight())
        {
            return true;
        }
        return false;
    }

    /**
     * Checks if a joint's JavaFX region has different layout values than those
     * currently stored in the model.
     *
     * @param joint
     *            the model instance for the joint
     *
     * @return {@code true} if any layout value has changed,
     *         {@code false if not}
     */
    private static boolean checkJointChanged(final GJoint joint, final GJointSkin jointSkin)
    {
        final Region jointRegion = jointSkin.getRoot();

        final double jointRegionX = jointRegion.getLayoutX() + jointSkin.getWidth() / 2;
        final double jointRegionY = jointRegion.getLayoutY() + jointSkin.getHeight() / 2;

        if (jointRegionX != joint.getX())
        {
            return true;
        }
        else if (jointRegionY != joint.getY())
        {
            return true;
        }
        return false;
    }

    /**
     * Attempts to undo the given model to its previous state.
     *
     * @param model the {@link GModel} to undo
     */
    public static void undo(final GModel model)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null && editingDomain.getCommandStack().canUndo())
        {
            editingDomain.getCommandStack().undo();
        }
    }

    /**
     * Attempts to redo the given model to its next state.
     *
     * @param model the {@link GModel} to redo
     */
    public static void redo(final GModel model)
    {
        final EditingDomain editingDomain = getEditingDomain(model);

        if (editingDomain != null && editingDomain.getCommandStack().canRedo())
        {
            editingDomain.getCommandStack().redo();
        }
    }

    /**
     * Gets the editing domain associated to the model.
     *
     * <p>
     * Logs an error if none is found.
     * </p>
     *
     * @param model a {@link GModel} instance
     * @return the {@link EditingDomain} associated to this model instance
     */
    private static EditingDomain getEditingDomain(final GModel model)
    {
        final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

        if (editingDomain == null)
        {
            LOGGER.error("No editing domain found for this model. Maybe it hasn't been set inside a graph editor?"); //$NON-NLS-1$
        }

        return editingDomain;
    }
} public interface GraphEditor extends GraphEditorSkins {

    /**
     * Sets a custom connector validator.
     *
     * <p>
     * This will be used to decide which connections are allowed / forbidden during drag and drop events in the editor.
     * </p>
     *
     * @param validator a custom validator implements {@link GConnectorValidator}, or null to use the default validator
     */
    void setConnectorValidator(final GConnectorValidator validator);

    /**
     * Sets the graph model to be edited.
     *
     * @param model the {@link GModel} to be edited
     */
    void setModel(final GModel model);

    /**
     * Gets the graph model that is currently being edited.
     *
     * @return the {@link GModel} being edited, or {@code null} if no model was ever set
     */
    GModel getModel();

    /**
     * Reloads the graph model currently being edited.
     *
     * <p>
     * <b>Note: </b><br>
     * If the model is updated via EMF commands, as is recommended, it should rarely be necessary to call this method.
     * The model will be reloaded automatically via a command-stack listener.
     * </p>
     */
    void reload();

    /**
     * The property containing the graph model being edited.
     *
     * @return a property containing the {@link GModel} being edited
     */
    ObjectProperty<GModel> modelProperty();

    /**
     * Gets the view where the graph is displayed and edited.
     *
     * <p>
     * The view is a JavaFX {@link Region}. It should be added to the scene
     * graph in the usual way.
     * </p>
     *
     * @return the {@link Region} where the graph is displayed and edited
     */
    Region getView();

    /**
     * Gets the properties of the editor.
     *
     * <p>
     * This provides access to global properties such as:
     *
     * <ul>
     * <li>Show/hide alignment grid.</li>
     * <li>Toggle snap-to-grid on/off.</li>
     * <li>Toggle editor bounds on/off.</li>
     * </ul>
     *
     * </p>
     *
     * @return an {@link GraphEditorProperties} instance containing the properties of the editor
     */
    GraphEditorProperties getProperties();

    /**
     * Gets the skin lookup.
     *
     * <p>
     * The skin lookup is used to get any skin instance associated to a model element instance.
     * </p>
     *
     * @return a {@link SkinLookup} used to lookup skins
     */
    SkinLookup getSkinLookup();

    /**
     * Gets the selection manager.
     *
     * <p>
     * The selection manager keeps track of the selected nodes, connections,
     * etc.
     * </p>
     *
     * @return the {@link SelectionManager}
     */
    SelectionManager getSelectionManager();

    /**
     * Sets a method to be called when a connection is created in the editor.
     *
     * <p>
     * This can be used to append additional commands to the one that created the connection.
     * </p>
     *
     * @param consumer a consumer to append additional commands
     */
    void setOnConnectionCreated(Function<GConnection, Command> consumer);

    /**
     * Sets a method to be called when a connection is removed in the editor.
     *
     * <p>
     * This can be used to create additional commands to the one that removed
     * the connection.
     * </p>
     *
     * @param pOnConnectionRemoved
     *            a {@link BiFunction} creating the additional command
     */
    void setOnConnectionRemoved(BiFunction<RemoveContext, GConnection, Command> pOnConnectionRemoved);

    /**
     * Sets a method to be called when a node is removed in the editor.
     *
     * <p>
     * This can be used to create additional commands to the one that removed
     * the node.
     * </p>
     *
     * @param pOnNodeRemoved
     *            a {@link BiFunction} creating the additional command
     */
    void setOnNodeRemoved(BiFunction<RemoveContext, GNode, Command> pOnNodeRemoved);

    /**
     * Deletes all elements that are currently selected.
     *
     * @param pItems
     *            the items to remove from the graph
     */
    void delete(Collection<EObject> pItems);
} public interface SkinLookup {

    /**
     * Gets the skin for the given node.
     *
     * @param node a {@link GNode} instance
     *
     * @return the associated {@link GNodeSkin} instance
     */
    GNodeSkin lookupNode(final GNode node);

    /**
     * Gets the skin for the given connector.
     *
     * @param connector a {@link GConnector} instance
     *
     * @return the associated {@link GConnectorSkin} instance
     */
    GConnectorSkin lookupConnector(final GConnector connector);

    /**
     * Gets the skin for the given connection.
     *
     * @param connection a {@link GConnection} instance
     *
     * @return the associated {@link GConnectionSkin} instance
     */
    GConnectionSkin lookupConnection(final GConnection connection);

    /**
     * Gets the skin for the given joint.
     *
     * @param joint a {@link GJoint} instance
     *
     * @return the associated {@link GJointSkin} instance
     */
    GJointSkin lookupJoint(final GJoint joint);

    /**
     * Gets the tail skin for the given connector.
     *
     * @param connector a {@link GConnector} instance
     *
     * @return the associated {@link GTailSkin} instance
     */
    GTailSkin lookupTail(final GConnector connector);
} public class ConnectionCommands
{

    /**
     * Static class, not to be instantiated.
     */
    private ConnectionCommands()
    {
    }

    /**
     * Adds a connection to the model.
     *
     * @param model
     *            the {@link GModel} to which the connection should be added
     * @param source
     *            the source {@link GConnector} of the new connection
     * @param target
     *            the target {@link GConnector} of the new connection
     * @param type
     *            the type attribute for the new connection
     * @param joints
     *            the list of {@link GJoint} instances to be added inside the
     *            new connection
     */
    public static void addConnection(final GModel model, final GConnector source, final GConnector target, final String type,
            final List<GJoint> joints, final ConnectionEventManager connectionEventManager)
    {
        final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            // prepare new connection:
            final GConnection connection = GraphFactory.eINSTANCE.createGConnection();
            connection.setType(type);
            connection.setSource(source);
            connection.setTarget(target);
            connection.getJoints().addAll(joints);

            // attributes that involve other members of the model, are modified through commands:
            command.append(AddCommand.create(editingDomain, model, GraphPackage.Literals.GMODEL__CONNECTIONS, connection));
            command.append(AddCommand.create(editingDomain, source, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));
            command.append(AddCommand.create(editingDomain, target, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));

            final Command onCreate;
            if (connectionEventManager != null && (onCreate = connectionEventManager.notifyConnectionAdded(connection)) != null)
            {
                command.append(onCreate);
            }

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }
        }
    }

    /**
     * Removes a connection from the model.
     *
     * @param model
     *            the {@link GModel} from which the connection should be removed
     * @param connection
     *            the {@link GConnection} to be removed
     * @param connectionEventManager
     */
    public static void removeConnection(final GModel model, final GConnection connection, ConnectionEventManager connectionEventManager)
    {
        final EditingDomain editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);

        if (editingDomain != null)
        {
            final CompoundCommand command = new CompoundCommand();

            final GConnector source = connection.getSource();
            final GConnector target = connection.getTarget();

            command.append(RemoveCommand.create(editingDomain, model, GraphPackage.Literals.GMODEL__CONNECTIONS, connection));
            command.append(RemoveCommand.create(editingDomain, source, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));
            command.append(RemoveCommand.create(editingDomain, target, GraphPackage.Literals.GCONNECTOR__CONNECTIONS, connection));

            final Command onRemove;
            if (connectionEventManager != null && (onRemove = connectionEventManager.notifyConnectionRemoved(connection)) != null)
            {
                command.append(onRemove);
            }

            if (command.canExecute())
            {
                editingDomain.getCommandStack().execute(command);
            }

        }
    }
}
 public class FXTestUtils {

    /**
     * Forces an update of the {@link Parent}'s layout.
     *
     * @param parent the {@link Parent} whose layout should be updated
     */
    public static void forceLayoutUpdate(final Parent parent) {
        parent.autosize();
        parent.snapshot(null, null);
        parent.layout();
    }

    /**
     * Drags the given {@link Node} by the given x and y displacements.
     *
     * @param node the {@link Node} which should be dragged
     * @param dx the x displacement to move the node by
     * @param dy the y displacement to move the node by
     */
    public static void dragBy(final Node node, final double dx, final double dy) {
        dragTo(node, node.getLayoutX() + dx, node.getLayoutY() + dy);
    }

    /**
     * Drags the given {@link Node} by the given x and y displacements.
     *
     * @param node the {@link Node} which should be dragged
     * @param offsetX the x offset on the node where the drag gesture starts from
     * @param offsetY the y offset on the node where the drag gesture starts from
     * @param dx the x displacement to move the {@link Node} by
     * @param dy the y displacement to move the {@link Node} by
     */
    public static void dragBy(final Node node, final double offsetX, final double offsetY, final double dx,
            final double dy) {

        dragTo(node, offsetX, offsetY, node.getLayoutX() + dx, node.getLayoutY() + dy);
    }

    /**
     * Drags the given {@link Node} from the start location to the end location.
     *
     * @param node the {@link Node} which should be dragged
     * @param endX the x coordinate of the targeted location
     * @param endY the y coordinate of the targeted location
     */
    public static void dragTo(final Node node, final double endX, final double endY) {
        dragTo(node, 0, 0, endX, endY);
    }

    /**
     * Drags the given {@link Node} from the start location to the end location.
     *
     * @param node the {@link Node} which should be dragged
     * @param offsetX the x offset on the node where the drag gesture starts from
     * @param offsetY the y offset on the node where the drag gesture starts from
     * @param endX the x coordinate of the targeted location
     * @param endY the y coordinate of the targeted location
     */
    public static void dragTo(final Node node, final double offsetX, final double offsetY, final double endX,
            final double endY) {

        final double startX = node.getLayoutX() + offsetX;
        final double startY = node.getLayoutY() + offsetY;

        final double dragX = startX + (endX - node.getLayoutX());
        final double dragY = startY + (endY - node.getLayoutY());

        final MouseEvent pressed = createMouseEvent(MouseEvent.MOUSE_PRESSED, startX, startY);
        final MouseEvent dragged = createMouseEvent(MouseEvent.MOUSE_DRAGGED, dragX, dragY);
        final MouseEvent released = createMouseEvent(MouseEvent.MOUSE_RELEASED, dragX, dragY);

        Event.fireEvent(node, pressed);
        Event.fireEvent(node, dragged);
        Event.fireEvent(node, released);
    }

    /**
     * Creates a new {@link MouseEvent}.
     *
     * @param type the {@link EventType} of the event
     * @param x the x coordinate of the event
     * @param y the y coordinate of the event
     * @return the newly-created {@link MouseEvent}
     */
    private static MouseEvent createMouseEvent(final EventType<MouseEvent> type, final double x, final double y) {

        return new MouseEvent(type, // event type
                x, y, // x and y
                0, 0, MouseButton.PRIMARY, 0, // screen x, screen y, mouse button, click count
                false, false, false, false, true, false, false, false, false, false, null);
    }
} public interface GConnection extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Source</b></em>' reference.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Source</em>' reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Source</em>' reference.
	 * @see #setSource(GConnector)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Source()
	 * @model required="true"
	 * @generated
	 */
	GConnector getSource();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getSource <em>Source</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Source</em>' reference.
	 * @see #getSource()
	 * @generated
	 */
	void setSource(GConnector value);

	/**
	 * Returns the value of the '<em><b>Target</b></em>' reference.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Target</em>' reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Target</em>' reference.
	 * @see #setTarget(GConnector)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Target()
	 * @model required="true"
	 * @generated
	 */
	GConnector getTarget();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnection#getTarget <em>Target</em>}' reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Target</em>' reference.
	 * @see #getTarget()
	 * @generated
	 */
	void setTarget(GConnector value);

	/**
	 * Returns the value of the '<em><b>Joints</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GJoint}.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GJoint#getConnection <em>Connection</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Joints</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Joints</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnection_Joints()
	 * @see de.tesis.dynaware.grapheditor.model.GJoint#getConnection
	 * @model opposite="connection" containment="true"
	 * @generated
	 */
	EList<GJoint> getJoints();

} // GConnection public interface GConnector extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Parent</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GNode#getConnectors <em>Connectors</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Parent</em>' container reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Parent</em>' container reference.
	 * @see #setParent(GNode)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Parent()
	 * @see de.tesis.dynaware.grapheditor.model.GNode#getConnectors
	 * @model opposite="connectors" required="true" transient="false"
	 * @generated
	 */
	GNode getParent();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getParent <em>Parent</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Parent</em>' container reference.
	 * @see #getParent()
	 * @generated
	 */
	void setParent(GNode value);

	/**
	 * Returns the value of the '<em><b>Connections</b></em>' reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnection}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connections</em>' reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connections</em>' reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Connections()
	 * @model
	 * @generated
	 */
	EList<GConnection> getConnections();

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_X()
	 * @model
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_Y()
	 * @model
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

	/**
	 * Returns the value of the '<em><b>Connection Detached On Drag</b></em>' attribute.
	 * The default value is <code>"true"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connection Detached On Drag</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connection Detached On Drag</em>' attribute.
	 * @see #setConnectionDetachedOnDrag(boolean)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGConnector_ConnectionDetachedOnDrag()
	 * @model default="true" required="true"
	 * @generated
	 */
	boolean isConnectionDetachedOnDrag();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GConnector#isConnectionDetachedOnDrag <em>Connection Detached On Drag</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Connection Detached On Drag</em>' attribute.
	 * @see #isConnectionDetachedOnDrag()
	 * @generated
	 */
	void setConnectionDetachedOnDrag(boolean value);

} // GConnector public interface GJoint extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Connection</b></em>' container reference.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GConnection#getJoints <em>Joints</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connection</em>' container reference isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connection</em>' container reference.
	 * @see #setConnection(GConnection)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Connection()
	 * @see de.tesis.dynaware.grapheditor.model.GConnection#getJoints
	 * @model opposite="joints" required="true" transient="false"
	 * @generated
	 */
	GConnection getConnection();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getConnection <em>Connection</em>}' container reference.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Connection</em>' container reference.
	 * @see #getConnection()
	 * @generated
	 */
	void setConnection(GConnection value);

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_X()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGJoint_Y()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GJoint#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

} // GJoint public interface GModel extends EObject {
	/**
	 * Returns the value of the '<em><b>Nodes</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GNode}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Nodes</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Nodes</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Nodes()
	 * @model containment="true"
	 * @generated
	 */
	EList<GNode> getNodes();

	/**
	 * Returns the value of the '<em><b>Connections</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnection}.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connections</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connections</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Connections()
	 * @model containment="true"
	 * @generated
	 */
	EList<GConnection> getConnections();

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>Content Width</b></em>' attribute.
	 * The default value is <code>"3000"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Content Width</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Content Width</em>' attribute.
	 * @see #setContentWidth(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_ContentWidth()
	 * @model default="3000" required="true"
	 * @generated
	 */
	double getContentWidth();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getContentWidth <em>Content Width</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Content Width</em>' attribute.
	 * @see #getContentWidth()
	 * @generated
	 */
	void setContentWidth(double value);

	/**
	 * Returns the value of the '<em><b>Content Height</b></em>' attribute.
	 * The default value is <code>"2250"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Content Height</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Content Height</em>' attribute.
	 * @see #setContentHeight(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGModel_ContentHeight()
	 * @model default="2250" required="true"
	 * @generated
	 */
	double getContentHeight();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GModel#getContentHeight <em>Content Height</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Content Height</em>' attribute.
	 * @see #getContentHeight()
	 * @generated
	 */
	void setContentHeight(double value);

} // GModel public interface GNode extends EObject {
	/**
	 * Returns the value of the '<em><b>Id</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Id</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Id</em>' attribute.
	 * @see #setId(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Id()
	 * @model id="true"
	 * @generated
	 */
	String getId();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getId <em>Id</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Id</em>' attribute.
	 * @see #getId()
	 * @generated
	 */
	void setId(String value);

	/**
	 * Returns the value of the '<em><b>Type</b></em>' attribute.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Type</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Type</em>' attribute.
	 * @see #setType(String)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Type()
	 * @model
	 * @generated
	 */
	String getType();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getType <em>Type</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Type</em>' attribute.
	 * @see #getType()
	 * @generated
	 */
	void setType(String value);

	/**
	 * Returns the value of the '<em><b>X</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>X</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>X</em>' attribute.
	 * @see #setX(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_X()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getX();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getX <em>X</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>X</em>' attribute.
	 * @see #getX()
	 * @generated
	 */
	void setX(double value);

	/**
	 * Returns the value of the '<em><b>Y</b></em>' attribute.
	 * The default value is <code>"0"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Y</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Y</em>' attribute.
	 * @see #setY(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Y()
	 * @model default="0" required="true"
	 * @generated
	 */
	double getY();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getY <em>Y</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Y</em>' attribute.
	 * @see #getY()
	 * @generated
	 */
	void setY(double value);

	/**
	 * Returns the value of the '<em><b>Width</b></em>' attribute.
	 * The default value is <code>"151"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Width</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Width</em>' attribute.
	 * @see #setWidth(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Width()
	 * @model default="151" required="true"
	 * @generated
	 */
	double getWidth();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getWidth <em>Width</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Width</em>' attribute.
	 * @see #getWidth()
	 * @generated
	 */
	void setWidth(double value);

	/**
	 * Returns the value of the '<em><b>Height</b></em>' attribute.
	 * The default value is <code>"101"</code>.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Height</em>' attribute isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Height</em>' attribute.
	 * @see #setHeight(double)
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Height()
	 * @model default="101" required="true"
	 * @generated
	 */
	double getHeight();

	/**
	 * Sets the value of the '{@link de.tesis.dynaware.grapheditor.model.GNode#getHeight <em>Height</em>}' attribute.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @param value the new value of the '<em>Height</em>' attribute.
	 * @see #getHeight()
	 * @generated
	 */
	void setHeight(double value);

	/**
	 * Returns the value of the '<em><b>Connectors</b></em>' containment reference list.
	 * The list contents are of type {@link de.tesis.dynaware.grapheditor.model.GConnector}.
	 * It is bidirectional and its opposite is '{@link de.tesis.dynaware.grapheditor.model.GConnector#getParent <em>Parent</em>}'.
	 * <!-- begin-user-doc -->
	 * <p>
	 * If the meaning of the '<em>Connectors</em>' containment reference list isn't clear,
	 * there really should be more of a description here...
	 * </p>
	 * <!-- end-user-doc -->
	 * @return the value of the '<em>Connectors</em>' containment reference list.
	 * @see de.tesis.dynaware.grapheditor.model.GraphPackage#getGNode_Connectors()
	 * @see de.tesis.dynaware.grapheditor.model.GConnector#getParent
	 * @model opposite="parent" containment="true"
	 * @generated
	 */
	EList<GConnector> getConnectors();

} // GNode public interface GraphFactory extends EFactory {
	/**
	 * The singleton instance of the factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @generated
	 */
	GraphFactory eINSTANCE = de.tesis.dynaware.grapheditor.model.impl.GraphFactoryImpl.init();

	/**
	 * Returns a new object of class '<em>GModel</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GModel</em>'.
	 * @generated
	 */
	GModel createGModel();

	/**
	 * Returns a new object of class '<em>GNode</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GNode</em>'.
	 * @generated
	 */
	GNode createGNode();

	/**
	 * Returns a new object of class '<em>GConnection</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GConnection</em>'.
	 * @generated
	 */
	GConnection createGConnection();

	/**
	 * Returns a new object of class '<em>GConnector</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GConnector</em>'.
	 * @generated
	 */
	GConnector createGConnector();

	/**
	 * Returns a new object of class '<em>GJoint</em>'.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return a new object of class '<em>GJoint</em>'.
	 * @generated
	 */
	GJoint createGJoint();

	/**
	 * Returns the package supported by this factory.
	 * <!-- begin-user-doc -->
	 * <!-- end-user-doc -->
	 * @return the package supported by this factory.
	 * @generated
	 */
	GraphPackage getGraphPackage();

} //GraphFactory
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import org.eclipse.emf.common.command.CommandStack;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.junit.Before;
import org.junit.Test;
import de.tesis.dynaware.grapheditor.Commands;
import de.tesis.dynaware.grapheditor.GraphEditor;
import de.tesis.dynaware.grapheditor.SkinLookup;
import de.tesis.dynaware.grapheditor.core.data.DummyDataFactory;
import de.tesis.dynaware.grapheditor.core.skins.defaults.utils.ConnectionCommands;
import de.tesis.dynaware.grapheditor.core.utils.FXTestUtils;
import de.tesis.dynaware.grapheditor.model.GConnection;
import de.tesis.dynaware.grapheditor.model.GConnector;
import de.tesis.dynaware.grapheditor.model.GJoint;
import de.tesis.dynaware.grapheditor.model.GModel;
import de.tesis.dynaware.grapheditor.model.GNode;
import de.tesis.dynaware.grapheditor.model.GraphFactory;
import javafx.application.Platform;
/*
 * Copyright (C) 2005 - 2014 by TESIS DYNAware GmbH
 */
package de.tesis.dynaware.grapheditor.core;





/**
 * This test treats the graph editor as a single unit.
 *
 * <p>
 * A fully-functional {@link DefaultGraphEditor} instance is created and populated with a dummy {@link GModel}. We make
 * some changes to the model and check that the graph editor is reinitialized correctly.
 * </p>
 */
public class GraphEditorTest {

    private GraphEditor graphEditor;
    private GModel model;
    private SkinLookup skinLookup;

    private EditingDomain editingDomain;
    private CommandStack commandStack;

    @Before
    public void setUp() throws InterruptedException
    {
        graphEditor = new DefaultGraphEditor();
        model = DummyDataFactory.createModel();
        skinLookup = graphEditor.getSkinLookup();

        graphEditor.setModel(model);

        editingDomain = AdapterFactoryEditingDomain.getEditingDomainFor(model);
        if (editingDomain != null) {
            commandStack = editingDomain.getCommandStack();
        }

        final CountDownLatch waitInit = new CountDownLatch(1);
        try
        {
            Platform.startup(waitInit::countDown);
        }
        catch (Exception e)
        {
            waitInit.countDown();
        }
        waitInit.await();

        reloadEditor();

        graphEditor.getView().autosize();
        graphEditor.getView().layout();
    }

    private void reloadEditor() throws InterruptedException
    {
        final CountDownLatch wait = new CountDownLatch(1);
        Platform.runLater(() ->
        {
            graphEditor.reload();
            wait.countDown();
        });
        wait.await();
    }

    @Test
    public void checkInitializedCorrectly() {

        assertNotNull("Editing domain should exist.", editingDomain);
        assertNotNull("Command stack should exist.", commandStack);
        assertNotNull("Skin lookup should exist.", skinLookup);
    }

    @Test
    public void undoRedoNode() throws InterruptedException
    {

        final GNode node = addNodeToModel();
        reloadEditor();

        assertNotNull("Node skin instance should exist.", skinLookup.lookupNode(node));
        assertTrue("Undo should be possible.", commandStack.canUndo());

        editingDomain.getCommandStack().undo();
        reloadEditor();

        assertFalse("Node should have been removed.", model.getNodes().contains(node));
        assertNull("Node skin instance should no longer exist.", skinLookup.lookupNode(node));
        assertTrue("Redo should be possible.", commandStack.canRedo());

        editingDomain.getCommandStack().redo();
        reloadEditor();

        assertTrue("Node should be back in again.", model.getNodes().contains(node));
        assertNotNull("Node skin instance should exist again.", skinLookup.lookupNode(node));
    }

    @Test
    public void undoRedoConnection() throws InterruptedException
    {

        Commands.clear(model);

        final GNode firstNode = addNodeToModel();
        final GNode secondNode = addNodeToModel();

        final GConnector firstNodeOutput = firstNode.getConnectors().get(1);
        final GConnector secondNodeInput = secondNode.getConnectors().get(0);

        final List<GJoint> joints = new ArrayList<>();
        joints.add(GraphFactory.eINSTANCE.createGJoint());
        joints.add(GraphFactory.eINSTANCE.createGJoint());

        ConnectionCommands.addConnection(model, firstNodeOutput, secondNodeInput, null, joints, null);