From 517cf84d8839d8fd7b34dcd808640ef2a2a1c451 Mon Sep 17 00:00:00 2001
From: Stephane Dallongeville <stephane.dallongeville@pasteur.fr>
Date: Tue, 31 Aug 2021 18:19:32 +0200
Subject: [PATCH] Added methods for easier retrieving of blocks / variables

---
 .../adufour/blocks/lang/BlockDescriptor.java  | 83 +++++++++++++++++--
 .../plugins/adufour/blocks/lang/WorkFlow.java | 58 +++++++++++++
 .../plugins/adufour/blocks/util/VarList.java  | 11 +++
 3 files changed, 145 insertions(+), 7 deletions(-)

diff --git a/src/main/java/plugins/adufour/blocks/lang/BlockDescriptor.java b/src/main/java/plugins/adufour/blocks/lang/BlockDescriptor.java
index b1b284f..334411b 100644
--- a/src/main/java/plugins/adufour/blocks/lang/BlockDescriptor.java
+++ b/src/main/java/plugins/adufour/blocks/lang/BlockDescriptor.java
@@ -6,6 +6,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -25,7 +26,15 @@ import icy.util.StringUtil;
 import icy.util.XMLUtil;
 import plugins.adufour.blocks.tools.Display;
 import plugins.adufour.blocks.tools.input.InputBlock;
-import plugins.adufour.blocks.util.*;
+import plugins.adufour.blocks.tools.output.OutputBlock;
+import plugins.adufour.blocks.util.BlockListener;
+import plugins.adufour.blocks.util.BlocksException;
+import plugins.adufour.blocks.util.BlocksFinder;
+import plugins.adufour.blocks.util.BlocksML;
+import plugins.adufour.blocks.util.BlocksReloadedException;
+import plugins.adufour.blocks.util.NoSuchVariableException;
+import plugins.adufour.blocks.util.VarList;
+import plugins.adufour.blocks.util.VarListListener;
 import plugins.adufour.vars.lang.Var;
 import plugins.adufour.vars.lang.VarMutable;
 import plugins.adufour.vars.lang.VarMutableArray;
@@ -353,9 +362,19 @@ public class BlockDescriptor implements Runnable, VarListener, VarListListener,
         return block instanceof Loop;
     }
 
+    public boolean isInput()
+    {
+        return block instanceof InputBlock;
+    }
+
+    public boolean isOutput()
+    {
+        return block instanceof OutputBlock;
+    }
+
     public boolean isSingleBlock()
     {
-        return block instanceof Display || block instanceof InputBlock;
+        return block instanceof Display || block instanceof InputBlock || block instanceof OutputBlock;
     }
 
     public boolean isWorkFlow()
@@ -824,7 +843,48 @@ public class BlockDescriptor implements Runnable, VarListener, VarListListener,
         return definedName;
     }
 
-    private BlockDescriptor getBlockDescriptor(int blockId, Set<BlockDescriptor> bds)
+    public static BlockDescriptor findBlockDescriptor(int blockId, List<BlockDescriptor> blocks)
+    {
+        for (BlockDescriptor bd : blocks)
+            if (bd.getID().intValue() == blockId)
+                return bd;
+
+        return null;
+    }
+
+    /**
+     * @param commandLineId
+     *        commandLineId (see {@link BlockDescriptor#getCommandLineID()}
+     * @param blocks
+     *        list of {@link BlockDescriptor}
+     * @return Input block {@link InputBlock} with given commandLineId or <i>null</i> if it doesn't exist
+     */
+    public static BlockDescriptor findInputBlockDescriptor(String commandLineId, List<BlockDescriptor> blocks)
+    {
+        for (BlockDescriptor block : blocks)
+            if (block.isInput() && StringUtil.equals(block.getCommandLineID(), commandLineId))
+                return block;
+
+        return null;
+    }
+
+    /**
+     * @param commandLineId
+     *        commandLineId (see {@link BlockDescriptor#getCommandLineID()}
+     * @param blocks
+     *        list of {@link BlockDescriptor}
+     * @return Output block {@link OutputBlock} with given commandLineId or <i>null</i> if it doesn't exist
+     */
+    public static BlockDescriptor findOutputBlockDescriptor(String commandLineId, List<BlockDescriptor> blocks)
+    {
+        for (BlockDescriptor block : blocks)
+            if (block.isOutput() && StringUtil.equals(block.getCommandLineID(), commandLineId))
+                return block;
+
+        return null;
+    }
+
+    private static BlockDescriptor getBlockDescriptor(int blockId, Set<BlockDescriptor> bds)
     {
         for (BlockDescriptor bd : bds)
             if (bd.getID().intValue() == blockId)
@@ -1098,9 +1158,9 @@ public class BlockDescriptor implements Runnable, VarListener, VarListListener,
     }
 
     /**
-     * (This method is used only if the block implements {@link InputBlock})
+     * (This method is used only if the block implements {@link InputBlock} or {@link OutputBlock})
      * 
-     * @return the command-line identifier for the input block's variable
+     * @return the command-line identifier for the input/ouput block's variable
      */
     public String getCommandLineID()
     {
@@ -1108,8 +1168,8 @@ public class BlockDescriptor implements Runnable, VarListener, VarListListener,
     }
 
     /**
-     * (This method is used only if the block implements {@link InputBlock})
-     * Sets the command line identifier for this input block's variable
+     * (This method is used only if the block implements {@link InputBlock} or {@link OutputBlock})
+     * Sets the command line identifier for this input/output block's variable
      * 
      * @param id
      *        Block identifier when using the command line.
@@ -1118,4 +1178,13 @@ public class BlockDescriptor implements Runnable, VarListener, VarListListener,
     {
         commandLineID = id;
     }
+
+    /**
+     * @return the single variable of this block, useful for single input block as {@link InputBlock} or {@link OutputBlock}
+     */
+    public Var<?> getVariable()
+    {
+        // OutputBlock actually store the variable in the input list only
+        return inputVars.first();
+    }
 }
diff --git a/src/main/java/plugins/adufour/blocks/lang/WorkFlow.java b/src/main/java/plugins/adufour/blocks/lang/WorkFlow.java
index 499ac7d..55b5f7b 100644
--- a/src/main/java/plugins/adufour/blocks/lang/WorkFlow.java
+++ b/src/main/java/plugins/adufour/blocks/lang/WorkFlow.java
@@ -7,6 +7,7 @@ import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 
 import icy.gui.dialog.ConfirmDialog;
 import icy.main.Icy;
@@ -16,6 +17,8 @@ import icy.system.IcyHandledException;
 import icy.system.thread.ThreadUtil;
 import icy.util.StringUtil;
 import plugins.adufour.blocks.lang.BlockDescriptor.BlockStatus;
+import plugins.adufour.blocks.tools.input.InputBlock;
+import plugins.adufour.blocks.tools.output.OutputBlock;
 import plugins.adufour.blocks.util.BlockListener;
 import plugins.adufour.blocks.util.BlocksException;
 import plugins.adufour.blocks.util.LinkCutException;
@@ -407,6 +410,61 @@ public class WorkFlow extends Plugin implements Block, Iterable<BlockDescriptor>
         return srcDependsOnDst;
     }
 
+    /**
+     * @param recursive
+     *        if we also want blocks from sub workflow
+     * @return all blocks contained in current workflow
+     */
+    public List<BlockDescriptor> getBlockDescriptors(boolean recursive)
+    {
+        final List<BlockDescriptor> result = new ArrayList<>();
+
+        synchronized (orderedBlocks)
+        {
+            for (BlockDescriptor block : orderedBlocks)
+            {
+                if (recursive && block.isWorkFlow())
+                    result.addAll(((WorkFlow) block.getBlock()).getBlockDescriptors(true));
+
+                result.add(block);
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * @param recursive
+     *        if we also want blocks from sub workflow
+     * @return all Input type blocks ({@link InputBlock} contained in current workflow
+     */
+    public List<BlockDescriptor> getInputBlockDescriptors(boolean recursive)
+    {
+        final List<BlockDescriptor> result = new ArrayList<>();
+
+        for (BlockDescriptor block : getBlockDescriptors(recursive))
+            if (block.isInput())
+                result.add(block);
+
+        return result;
+    }
+
+    /**
+     * @param recursive
+     *        if we also want blocks from sub workflow
+     * @return all Output type blocks ({@link OutputBlock} contained in current workflow
+     */
+    public List<BlockDescriptor> getOutputBlockDescriptors(boolean recursive)
+    {
+        final List<BlockDescriptor> result = new ArrayList<>();
+
+        for (BlockDescriptor block : getBlockDescriptors(recursive))
+            if (block.isOutput())
+                result.add(block);
+
+        return result;
+    }
+
     public BlockDescriptor getBlock(int index)
     {
         return orderedBlocks.get(index);
diff --git a/src/main/java/plugins/adufour/blocks/util/VarList.java b/src/main/java/plugins/adufour/blocks/util/VarList.java
index a484a3b..d93627a 100644
--- a/src/main/java/plugins/adufour/blocks/util/VarList.java
+++ b/src/main/java/plugins/adufour/blocks/util/VarList.java
@@ -155,6 +155,17 @@ public class VarList implements Iterable<Var<?>>
         return varMap.containsValue(variable);
     }
 
+    /**
+     * @return first contained variable in the {@link VarList} and <i>null</i> if VarList is empty
+     */
+    public Var<?> first()
+    {
+        for (Var<?> v : varMap.values())
+            return v;
+
+        return null;
+    }
+
     /**
      * @deprecated Legacy method (used to load old XML work flows).
      * @param <T>
-- 
GitLab