public void process(
      DslStep step, ObjectSink node, Map<String, Object> context, InternalWorkingMemory wm) {
    try {
      List<String[]> cmds = step.getCommands();

      for (String[] cmd : cmds) {
        if (cmd[0].equals("verify")) {
          if ("count".equals(cmd[2])) {
            verifyCount(step, node, wm, cmd, context);
          } else if ("exec".equals(cmd[2])) {
            verifyExec(step, node, wm, cmd, context);
          } else if (cmd.length == 3 || cmd.length == 4) {
            verifyExpression(step, node, wm, cmd, context);
          } else {
            throw new IllegalArgumentException(
                "line "
                    + step.getLine()
                    + ": command '"
                    + cmd[2]
                    + "' does not exist in "
                    + Arrays.toString(cmd));
          }
        } else {
          throw new IllegalArgumentException(
              "line " + step.getLine() + ": command does not exist " + Arrays.toString(cmd));
        }
      }
    } catch (Exception e) {
      throw new IllegalArgumentException(
          "line " + step.getLine() + ": unable to execute step " + step, e);
    }
  }
  @SuppressWarnings("unchecked")
  private void verifyExec(
      DslStep step,
      ObjectSink node,
      InternalWorkingMemory wm,
      String[] cmd,
      Map<String, Object> context)
      throws AssertionError {
    // check that the captor already exists:
    String key = getCaptorKey(node, cmd);
    ArgumentCaptor<InternalFactHandle> captor =
        (ArgumentCaptor<InternalFactHandle>) context.get(key);
    if (captor == null) {
      // create the captor
      verifyCount(step, node, wm, new String[] {"verify", cmd[1], "count", "-1"}, context);
      captor = (ArgumentCaptor<InternalFactHandle>) context.get(key);
    }

    // create a map with all captured tuples as variables
    Map<String, Object> vars = new HashMap<String, Object>();
    int i = 0;
    for (InternalFactHandle handle : captor.getAllValues()) {
      vars.put("handle" + (i++), handle);
    }
    // add all context variables, just in case
    vars.putAll(context);

    // add the static imports for hamcrest matchers
    ParserConfiguration pconf = new ParserConfiguration();
    addStaticImports(pconf, CoreMatchers.class);
    addStaticImports(pconf, JUnitMatchers.class);
    // add import for JUnit assert class
    pconf.addImport("Assert", Assert.class);

    // compile MVEL expression
    ParserContext mvelctx = new ParserContext(pconf);
    String expression = cmd[3].replaceAll("h(\\d+)", "Handles[$1]");
    try {
      Serializable compiled = MVEL.compileExpression(expression, mvelctx);
      // execute the expression
      MVEL.executeExpression(compiled, vars);
    } catch (PropertyAccessException e) {
      String message;
      if (e.getCause() instanceof InvocationTargetException) {
        message = ((InvocationTargetException) e.getCause()).getTargetException().toString();
      } else {
        message = e.getMessage();
      }

      Assert.fail(
          "[ERROR] line "
              + step.getLine()
              + " - Executing expression: '"
              + expression
              + "'\n"
              + message);
    }
  }
 private void verifyCount(
     DslStep step,
     ObjectSink node,
     InternalWorkingMemory wm,
     String[] cmd,
     Map<String, Object> context)
     throws AssertionError {
   int times = Integer.valueOf(cmd[3]);
   VerificationMode counter;
   if (times >= 0) {
     counter = times(times);
   } else {
     counter = atLeastOnce();
   }
   try {
     ArgumentCaptor<InternalFactHandle> captor = ArgumentCaptor.forClass(InternalFactHandle.class);
     if ("assert".equals(cmd[1])) {
       verify(node, counter)
           .assertObject(captor.capture(), any(PropagationContext.class), same(wm));
     } else if ("modify".equals(cmd[1])) {
       verify(node, counter)
           .modifyObject(
               captor.capture(),
               any(ModifyPreviousTuples.class),
               any(PropagationContext.class),
               same(wm));
     } else {
       throw new IllegalArgumentException(
           "line " + step.getLine() + ": command does not exist " + Arrays.toString(cmd));
     }
     String key = getCaptorKey(node, cmd);
     context.put(key, captor);
   } catch (MockitoAssertionError e) {
     AssertionError ae =
         new AssertionError("line " + step.getLine() + ": verify failed: " + e.getMessage());
     ae.setStackTrace(e.getStackTrace());
     throw ae;
   }
 }