@Test
  public void testBatchAddInvalidState2() {
    // Add one more TestDummyNode and related Edges to the existing graph. However we attach the
    // TestDummyNode
    // to the existing StartProcessNode. This is invalid as a StartProcessNode can only contain one
    // outgoing Edge
    // and hence the batch should fail.
    final TestDummyNode testNode1 = new TestDummyNode();
    final BpmnEdge testEdge1 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final AddGraphNodeCommand testCmd1 = new AddGraphNodeCommand(process, testNode1);
    final AddEdgeCommand testCmd2 = new AddEdgeCommand(node1, testNode1, testEdge1);
    final Results results1 =
        commandManager.execute(ruleManager, new BatchCommand(testCmd1, testCmd2));

    assertNotNull(results1);
    assertEquals(1, results1.getMessages().size());
    assertEquals(1, results1.getMessages(ResultType.ERROR).size());

    assertEquals(3, process.size());
    assertProcessNotContainsNodes(process, testNode1);
    assertEquals(1, node2.getOutEdges().size());
    assertNodeContainsOutgoingEdges(node2, e2);

    assertEquals(0, testNode1.getInEdges().size());
    assertEquals(0, testNode1.getOutEdges().size());
  }
  @Test
  public void testBatchAddInvalidState1() {
    // Add one more TestDummyNode and another EndProcessNode plus related Edges to the existing
    // graph.
    // This is invalid as a Process can only contain one EndProcessNode and hence the batch should
    // fail.
    final TestDummyNode testNode1 = new TestDummyNode();
    final EndProcessNode testNode2 = new EndProcessNode();
    final BpmnEdge testEdge1 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final BpmnEdge testEdge2 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final AddGraphNodeCommand testCmd1 = new AddGraphNodeCommand(process, testNode1);
    final AddGraphNodeCommand testCmd2 = new AddGraphNodeCommand(process, testNode2);
    final AddEdgeCommand testCmd3 = new AddEdgeCommand(node2, testNode1, testEdge1);
    final AddEdgeCommand testCmd4 = new AddEdgeCommand(testNode1, testNode2, testEdge2);
    final Results results1 =
        commandManager.execute(
            ruleManager, new BatchCommand(testCmd1, testCmd2, testCmd3, testCmd4));

    assertNotNull(results1);
    assertEquals(1, results1.getMessages().size());
    assertEquals(1, results1.getMessages(ResultType.ERROR).size());

    assertEquals(3, process.size());
    assertProcessNotContainsNodes(process, testNode1, testNode2);
    assertEquals(1, node2.getOutEdges().size());
    assertNodeContainsOutgoingEdges(node2, e2);

    assertEquals(0, testNode1.getInEdges().size());
    assertEquals(0, testNode1.getOutEdges().size());
    assertEquals(0, testNode2.getInEdges().size());
  }
  @Test
  public void testBatchAddValidState() {
    // Add two more TestDummyNodes and related Edges to the existing graph. This is valid.
    final TestDummyNode testNode1 = new TestDummyNode();
    final TestDummyNode testNode2 = new TestDummyNode();
    final BpmnEdge testEdge1 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final BpmnEdge testEdge2 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final AddGraphNodeCommand testCmd1 = new AddGraphNodeCommand(process, testNode1);
    final AddGraphNodeCommand testCmd2 = new AddGraphNodeCommand(process, testNode2);
    final AddEdgeCommand testCmd3 = new AddEdgeCommand(node2, testNode1, testEdge1);
    final AddEdgeCommand testCmd4 = new AddEdgeCommand(testNode1, testNode2, testEdge2);
    final Results results1 =
        commandManager.execute(
            ruleManager, new BatchCommand(testCmd1, testCmd2, testCmd3, testCmd4));

    assertNotNull(results1);
    assertEquals(0, results1.getMessages().size());

    assertEquals(5, process.size());
    assertProcessContainsNodes(process, testNode1, testNode2);
    assertEquals(2, node2.getOutEdges().size());
    assertNodeContainsOutgoingEdges(node2, e2, testEdge1);

    assertEquals(1, testNode1.getInEdges().size());
    assertNodeContainsIncomingEdges(testNode1, testEdge1);
    assertEquals(1, testNode1.getOutEdges().size());
    assertNodeContainsOutgoingEdges(testNode1, testEdge2);

    assertEquals(1, testNode2.getInEdges().size());
    assertNodeContainsIncomingEdges(testNode2, testEdge2);
  }
  @Test
  public void testDeleteEdgeBetweenDummyNodeAndEndNode() {
    // Delete edge between DummyNode and EndNode
    final Results results1 =
        commandManager.execute(ruleManager, new DeleteEdgeCommand(node3, node4, e3));

    assertNotNull(results1);
    assertEquals(0, results1.getMessages().size());

    assertEquals(2, node3.getInEdges().size());
    assertEquals(0, node3.getOutEdges().size());
    assertEquals(0, node4.getInEdges().size());
    assertEquals(0, node4.getOutEdges().size());

    // Try to delete the same edge between DummyNode and EndNode again
    final Results results2 =
        commandManager.execute(ruleManager, new DeleteEdgeCommand(node3, node4, e3));

    assertNotNull(results2);
    assertEquals(1, results2.getMessages().size());
    assertEquals(1, results2.getMessages(ResultType.WARNING).size());

    assertEquals(2, node3.getInEdges().size());
    assertEquals(0, node3.getOutEdges().size());
    assertEquals(0, node4.getInEdges().size());
    assertEquals(0, node4.getOutEdges().size());
  }
  @Before
  public void setupNodes() {
    // Dummy process for each test consists of 3 connected nodes
    // ---------------------------------------------------------
    //
    // [StartNode]--e1-->[DummyNode]--e2-->[EndNode]
    //
    process = new ProcessNode();
    ruleManager = new DefaultRuleManagerImpl();
    node1 = new StartProcessNode();
    node2 = new TestDummyNode();
    node3 = new EndProcessNode();
    commandManager = new DefaultCommandManagerImpl();

    for (Rule rule : getConnectionRules()) {
      ruleManager.addRule(rule);
    }
    for (Rule rule : getCardinalityRules()) {
      ruleManager.addRule(rule);
    }

    // Add StartProcessNode
    final Results results1 =
        commandManager.execute(ruleManager, new AddGraphNodeCommand(process, node1));

    assertNotNull(results1);
    assertEquals(0, results1.getMessages().size());

    // Add TestDummyNode
    final Results results2 =
        commandManager.execute(ruleManager, new AddGraphNodeCommand(process, node2));

    assertNotNull(results2);
    assertEquals(0, results2.getMessages().size());

    // Add EndProcessNode
    final Results results3 =
        commandManager.execute(ruleManager, new AddGraphNodeCommand(process, node3));

    assertNotNull(results3);
    assertEquals(0, results3.getMessages().size());

    // Add Edge between StartNode and DummyNode1
    e1 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final Results results4 =
        commandManager.execute(ruleManager, new AddEdgeCommand(node1, node2, e1));

    assertNotNull(results4);
    assertEquals(0, results4.getMessages().size());

    // Add Edge between DummyNode2 and EndNode
    e2 = new BpmnEdgeImpl(new DefaultRoleImpl("general_edge"));
    final Results results5 =
        commandManager.execute(ruleManager, new AddEdgeCommand(node2, node3, e2));

    assertNotNull(results5);
    assertEquals(0, results5.getMessages().size());
  }
  @Test
  public void testDeleteOutgoingCardinalityIncomingMinimum() {
    ruleManager.addRule(
        new CardinalityRuleImpl(
            "DummyNode Incoming Cardinality Rule",
            new DefaultRoleImpl("dummy"),
            0,
            2,
            Collections.EMPTY_SET,
            new HashSet<CardinalityRule.ConnectorRule>() {
              {
                add(
                    new CardinalityRule.ConnectorRule() {
                      @Override
                      public long getMinOccurrences() {
                        return 1;
                      }

                      @Override
                      public long getMaxOccurrences() {
                        return 2;
                      }

                      @Override
                      public Role getRole() {
                        return new DefaultRoleImpl("general_edge");
                      }

                      @Override
                      public String getName() {
                        return "End Node DummyNode Connector Rule 1";
                      }
                    });
              }
            }));

    // Delete edge between DummyNode1 and DummyNode2
    final Results results1 =
        commandManager.execute(ruleManager, new DeleteEdgeCommand(node2, node3, e2));

    assertNotNull(results1);
    assertEquals(0, results1.getMessages().size());

    assertEquals(1, node2.getInEdges().size());
    assertEquals(1, node2.getOutEdges().size());
    assertEquals(1, node3.getInEdges().size());
    assertEquals(1, node3.getOutEdges().size());

    // Try to delete the other edge between DummyNode1 and DummyNode2 again. This should fail
    // validation.
    final Results results2 =
        commandManager.execute(ruleManager, new DeleteEdgeCommand(node2, node3, e4));

    assertNotNull(results2);
    assertEquals(1, results2.getMessages().size());
    assertEquals(1, results2.getMessages(ResultType.ERROR).size());

    assertEquals(1, node2.getInEdges().size());
    assertEquals(1, node2.getOutEdges().size());
    assertEquals(1, node3.getInEdges().size());
    assertEquals(1, node3.getOutEdges().size());
  }