JAL-3048 allow a chain of responses for a particular response code (needed when inter...
authorJim Procter <jprocter@issues.jalview.org>
Mon, 2 Jul 2018 14:34:02 +0000 (15:34 +0100)
committerJim Procter <jprocter@issues.jalview.org>
Mon, 2 Jul 2018 14:34:34 +0000 (15:34 +0100)
src/jalview/util/dialogrunner/DialogRunner.java
src/jalview/util/dialogrunner/DialogRunnerI.java
test/jalview/util/dialogrunner/DialogRunnerTest.java

index fc1a73d..b631128 100644 (file)
@@ -39,7 +39,7 @@ import java.util.Map;
 public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
 {
 
-  private Map<Response, RunResponse> callbacks = new java.util.HashMap<>();
+  private Map<Response, List<RunResponse>> callbacks = new java.util.HashMap<>();
 
   public T dialog;
 
@@ -54,9 +54,12 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
    */
   public void resetResponses()
   {
-    for (RunResponse response : callbacks.values())
+    for (List<RunResponse> lr : callbacks.values())
     {
-      response.reset();
+      for (RunResponse response : lr)
+      {
+        response.reset();
+      }
     }
     responses.clear();
     firstRunWasCalled = false;
@@ -65,11 +68,59 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
   @Override
   public T response(RunResponse action)
   {
-    callbacks.put(action.ourTrigger, action);
+    return addResponse(false, action);
+  }
+
+  /**
+   * insert a response at the beginning of the chain for the action. Useful to add
+   * pre-action validations local to the Dialog class
+   * 
+   * @param action
+   * @return
+   */
+  public T firstResponse(RunResponse action)
+  {
+    return addResponse(true, action);
+  }
+
+  protected T addResponse(boolean prePend, RunResponse action)
+  {
+    List<RunResponse> laction = callbacks.get(action.ourTrigger);
+    if (laction == null)
+    {
+      laction = new ArrayList<>();
+      callbacks.put(action.ourTrigger, laction);
+    }
+    if (prePend)
+    {
+      laction.add(0,action);
+    } else {
+      laction.add(action);
+    }
     return dialog;
   }
 
   /**
+   * 
+   * @param action
+   * @return true if action is a registered callback
+   */
+  public boolean isRegistered(RunResponse action)
+  {
+    List<RunResponse> resp = callbacks.get(action.ourTrigger);
+    if (resp != null)
+    {
+      for (RunResponse r : resp)
+      {
+        if (r == action)
+        {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+  /**
    * handle a response
    * 
    * @param responseCode
@@ -125,24 +176,36 @@ public class DialogRunner<T extends DialogRunnerI> implements DialogRunnerI
   private void run(Response response)
   {
     responses.add(response);
-    RunResponse action = callbacks.get(response);
-    if (action == null)
+    List<RunResponse> laction = callbacks.get(response);
+
+    if (laction == null)
     {
       System.err.println("Doing nothing for " + response);
       return;
     }
-    if (action.wasRun)
+    boolean wasRun = false;
+    int num = 0;
+    for (RunResponse action : laction)
     {
-      System.err
-              .println("IMPLEMENTATION ERROR: Cycle in DialogRunner ! for "
-                      + action);
+      num++;
+      // find next action to execute
+      if (!action.wasRun)
+      {
+        System.err
+                .println("Executing action (" + num + ") for " + response);
+        wasRun = true;
+        action.wasRun = true;
+        action.run();
+        if (action.returned != null)
+        {
+          run(action.returned);
+        }
+        break;
+      }
     }
-    System.err.println("Executing action for " + response);
-    action.wasRun = true;
-    action.run();
-    if (action.returned != null)
+    if (!wasRun)
     {
-      run(action.returned);
+      System.err.println("Did nothing for " + response);
     }
   }
 
index 9df6d33..aaeb304 100644 (file)
@@ -38,5 +38,4 @@ public interface DialogRunnerI<T extends DialogRunnerI>
    * @return the dialog
    */
   T response(RunResponse action);
-
 }
index e956124..e69ae87 100644 (file)
@@ -42,6 +42,16 @@ public class DialogRunnerTest
         returned = new Response("DONE");
       }
     };
+    final RunResponse befok = new RunResponse("OK")
+    {
+
+      @Override
+      public void run()
+      {
+        returned = new Response("OK");
+      }
+    };
+
     cancel = new RunResponse("CANCEL")
     {
       @Override
@@ -68,8 +78,12 @@ public class DialogRunnerTest
       }
     };
 
+    Assert.assertFalse(dialog.runner.isRegistered(ok));
+
     dialog.response(ok).response(cancel).response(help).response(ineed);
 
+    Assert.assertTrue(dialog.runner.isRegistered(ok));
+
     Assert.assertFalse(dialog.runner.firstRunWasCalled);
     dialog.doDialog("OK");
     // OK called, nothing else.
@@ -97,5 +111,19 @@ public class DialogRunnerTest
     Assert.assertFalse(ok.wasRun);
     Assert.assertEquals(ineed.returned, ooh);
     Assert.assertEquals(dialog.runner.responses.size(), 3);
+
+    // TODO: test prepend and chained execution of tasks for a response.
+    Assert.assertFalse(dialog.runner.isRegistered(befok));
+    dialog.runner.firstResponse(befok);
+
+    Assert.assertTrue(dialog.runner.isRegistered(befok));
+    Assert.assertTrue(dialog.runner.isRegistered(ok));
+
+    dialog.runner.resetResponses();
+
+    dialog.doDialog("OK");
+    Assert.assertTrue(befok.wasRun);
+    Assert.assertTrue(ok.wasRun);
+    Assert.assertEquals(dialog.runner.responses.size(), 3);
   }
 }