* Bug #12796 fixed - Mismatch with superblock ports between implicit 79/12479/21
Alexandre HERISSE [Tue, 10 Sep 2013 15:22:54 +0000 (17:22 +0200)]
and explicit ports.

Change-Id: I454c3a0b0f9cfc5222ba3e34cde04970a0de74a2

scilab/CHANGES_5.5.X
scilab/modules/xcos/src/java/org/scilab/modules/xcos/block/SuperBlock.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/block/io/ContextUpdate.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/graph/XcosDiagram.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/DiagramElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/utils/BlockPositioning.java

index b3d53ae..2a1daca 100644 (file)
@@ -196,7 +196,10 @@ Xcos
 
 * Bug #12732 fixed - Improper Copyright comments in the files generated by the code generation tool.
 
-* Bug #12797 fixed - I/O blocks generated by "Selection to Superblocks" had a
+* Bug #12796 fixed - There was some mismatches between implicit
+                     and explicit ports of superblocks.
+
+* Bug #12797 fixed - I/O blocks generated by "Selection to Superblocks" had
                      wrong size.
 
 * Bug #12868 fixed - There were several problems with PULSE_SC block.
index 6ef38d7..3d3088c 100644 (file)
@@ -13,6 +13,7 @@
 package org.scilab.modules.xcos.block;
 
 import java.io.IOException;
+import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
@@ -345,42 +346,337 @@ public final class SuperBlock extends BasicBlock {
     }
 
     /**
-     * update super block ports in parent diagram
+     * Function that insert one port on the concerned superblock
+     * and gives it the right order.
+     * 
+     * @param order
+     * @param basicblock
      */
-    public void updateExportedPort() {
-        if (child == null) {
-            return;
+    private void insertOnePort(int order, BasicBlock basicblock) {
+        try {
+            for (IOBlocks b : IOBlocks.values()) {
+                if (basicblock.getClass().equals(b.getReferencedClass())) {
+                    BasicPort port;
+                    port = b.getReferencedPortClass().newInstance();
+                    port.setOrdering(order);
+                    insert(port);
+                }
+            }
+        } catch (InstantiationException e) {
+            Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
+        } catch (IllegalAccessException e) {
+            Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
+        } catch (Exception e)
+        {
+            Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
         }
-        if (getParentDiagram() == null) {
-            setParentDiagram(Xcos.findParent(this));
+    }
+
+    /**
+     * Function that remove one port on the concerned superblock
+     * 
+     * @param order
+     * @param basicport
+     * @param basicblock
+     * @return
+     */
+    private boolean removeOnePort(int order, BasicPort basicport, BasicBlock basicblock) {
+        boolean port_deleted = false;
+
+        for (IOBlocks b : IOBlocks.values()) {
+            if (basicport.getClass().equals(b.getReferencedPortClass())) {
+                if (!basicblock.getClass().equals(b.getReferencedClass())) {
+                    // delete the port
+                    removePort(basicport);
+                    port_deleted = true;
+                }
+            }
         }
 
-        final Map<IOBlocks, List<mxICell>> blocksMap = IOBlocks.getAllBlocks(this);
+        return port_deleted;
+    }
+
+    /**
+     * 
+     * @param basicport
+     */
+    private void removeOnePort(BasicPort basicport) {
+        // delete the port
+        removePort(basicport);
+    }
+
+    /**
+     * Function that returns a hashtable of IOBlocks contained in the superdiagram
+     * depending on their direction.
+     * 
+     * @param blockMap
+     *            a map of blocks
+     * @return the hashtable
+     */
+    private Hashtable<String, List<? extends mxICell>> extractContextBlocks() {
+        // get a map of all the IOBlocks of the superdiagram
+        final Map<IOBlocks, List<BasicBlock>> blocksMap = IOBlocks.getAllBlocks(this);
+
+        // create a map of all the blocks of the superdiagram depending on their type
+        Hashtable<String, List<? extends mxICell>> context_block = new Hashtable<String, List<? extends mxICell>> ();
+
+        if (!context_block.containsKey(XcosDiagram.IN)) {
+            List<BasicBlock> cell_list = blocksMap.get(IOBlocks.ExplicitInBlock);
+            cell_list.addAll(blocksMap.get(IOBlocks.ImplicitInBlock));
+            context_block.put(XcosDiagram.IN, cell_list);
+        }
+        if (!context_block.containsKey(XcosDiagram.OUT)) {
+            List<BasicBlock> cell_list = blocksMap.get(IOBlocks.ExplicitOutBlock);
+            cell_list.addAll(blocksMap.get(IOBlocks.ImplicitOutBlock));
+            context_block.put(XcosDiagram.OUT, cell_list);
+        }
+        if (!context_block.containsKey(XcosDiagram.EIN)) {
+            List<BasicBlock> cell_list = blocksMap.get(IOBlocks.EventInBlock);
+            context_block.put(XcosDiagram.EIN, cell_list);
+        }
+        if (!context_block.containsKey(XcosDiagram.EOUT)) {
+            List<BasicBlock> cell_list = blocksMap.get(IOBlocks.EventOutBlock);
+            context_block.put(XcosDiagram.EOUT, cell_list);
+        }
+
+        return context_block;
+    }
+
+    /**
+     * Function that returns a hashtable of the superblock ports
+     * depending on their direction.
+     * 
+     * @param portsMap
+     *            a map of ports
+     * @return the hashtable
+     */
+    private Hashtable<String, List<? extends mxICell>> extractContextPorts() {
+        // get a map of all the ports of the superblock
         final Map<IOBlocks, List<mxICell>> portsMap = IOBlocks.getAllPorts(this);
-        for (IOBlocks block : IOBlocks.values()) {
-            final int blockCount = blocksMap.get(block).size();
-            int portCount = portsMap.get(block).size();
 
-            // add ports if required
-            while (blockCount > portCount) {
-                try {
-                    BasicPort port;
-                    port = block.getReferencedPortClass().newInstance();
-                    addPort(port);
-                } catch (InstantiationException e) {
-                    Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
-                } catch (IllegalAccessException e) {
-                    Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
+        // create a map of all the ports of the superblock depending on their type
+        Hashtable<String, List<? extends mxICell>> context_port = new Hashtable<String, List<? extends mxICell>> ();
+
+        if (!context_port.containsKey(XcosDiagram.IN)) {
+            List<mxICell> cell_list = portsMap.get(IOBlocks.ExplicitInBlock);
+            cell_list.addAll(portsMap.get(IOBlocks.ImplicitInBlock));
+            context_port.put(XcosDiagram.IN, cell_list);
+        }
+        if (!context_port.containsKey(XcosDiagram.OUT)) {
+            List<mxICell> cell_list = portsMap.get(IOBlocks.ExplicitOutBlock);
+            cell_list.addAll(portsMap.get(IOBlocks.ImplicitOutBlock));
+            context_port.put(XcosDiagram.OUT, cell_list);
+        }
+        if (!context_port.containsKey(XcosDiagram.EIN)) {
+            List<mxICell> cell_list = portsMap.get(IOBlocks.EventInBlock);
+            context_port.put(XcosDiagram.EIN, cell_list);
+        }
+        if (!context_port.containsKey(XcosDiagram.EOUT)) {
+            List<mxICell> cell_list = portsMap.get(IOBlocks.EventOutBlock);
+            context_port.put(XcosDiagram.EOUT, cell_list);
+        }
+
+        return context_port;
+    }
+
+    /**
+     * Function that add a port to a superblock. The function should be called only when
+     * the number of superdiagram blocks is higher than the superblock port number.
+     * 
+     * @param key
+     *         direction of the block ports
+     * @param context_block
+     *         the list of blocks
+     * @param context_port
+     *         the list of ports
+     */
+    private void addPorts(String key, Hashtable<String, List<? extends mxICell>> context_block, Map<String, List<? extends mxICell>> context_port)
+    {
+        // iterate on the superdiagram blocks
+        for (mxICell cell : context_block.get(key)) {
+            if (cell instanceof BasicBlock) {
+                BasicBlock basicblock = (BasicBlock) cell;
+                int order = (int) ((ScilabDouble) basicblock.getIntegerParameters()).getRealPart()[0][0];
+
+                // get the new added block if found
+                List<? extends mxICell> port_list = context_port.get(key);
+                boolean port_found = false;
+                for (mxICell port : port_list) {
+                    if (port instanceof BasicPort) {
+                        BasicPort basicport = (BasicPort) port;
+                        if (order == basicport.getOrdering()) {
+                            port_found = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (port_found == false) {
+                    // add the port on the superblock
+                    insertOnePort(order, basicblock);
+                }
+            }
+        }
+    }
+
+    /**
+     * Function that remove a port to a superblock. The function should be called only when
+     * the number of superdiagram blocks is less than the superblock port number.
+     * 
+     * @param key
+     *         direction of the block ports
+     * @param context_block
+     *         the list of blocks
+     * @param context_port
+     *         the list of ports
+     */
+    private void removePorts(String key, Hashtable<String, List<? extends mxICell>> context_block, Map<String, List<? extends mxICell>> context_port) {
+        // iterate on the superblock ports
+        for (mxICell cell : context_port.get(key)) {
+            if (cell instanceof BasicPort) {
+                BasicPort basicport = (BasicPort) cell;
+                int order = basicport.getOrdering();
+
+                // get the port to remove
+                List<? extends mxICell> block_list = context_block.get(key);
+                boolean block_found = false;
+                for (mxICell block : block_list) {
+                    if (block instanceof BasicBlock) {
+                        BasicBlock basicblock = (BasicBlock) block;
+                        int block_order = (int) ((ScilabDouble) basicblock.getIntegerParameters()).getRealPart()[0][0];
+                        if (order == block_order)
+                        {
+                            block_found = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (block_found == false) {
+                    // delete the port
+                    removeOnePort(basicport);
+                }
+            }
+        }
+    }
+
+    /**
+     * Function that remove dead ports from the superblock. A dead port is a port which has not
+     * a corresponding superdiagram IOBlock
+     * 
+     * @param key
+     *         direction of the block ports
+     * @param context_block
+     *         the list of blocks
+     * @param context_port
+     *         the list of ports
+     */
+    private void removeDeadPorts(String key, Hashtable<String, List<? extends mxICell>> context_block, Map<String, List<? extends mxICell>> context_port) {
+        // first remove dead ports
+        for (mxICell cell : context_port.get(key)) {
+            if (cell instanceof BasicPort) {
+                BasicPort basicport = (BasicPort) cell;
+                int order = basicport.getOrdering();
+
+                // get the port to remove
+                List<? extends mxICell> block_list = context_block.get(key);
+                boolean block_found = false;
+                for (mxICell block : block_list) {
+                    if (block instanceof BasicBlock) {
+                        BasicBlock basicblock = (BasicBlock) block;
+                        int block_order = (int) ((ScilabDouble) basicblock.getIntegerParameters()).getRealPart()[0][0];
+                        if (order == block_order) {
+                            block_found = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (block_found == false) {
+                    // delete the port
+                    removeOnePort(basicport);
+                }
+            }
+        }
+    }
+
+    /**
+     * Function that replace a port of a superblock
+     * if its numbering has changed
+     * 
+     * @param key
+     *          direction of the block ports
+     * @param context_block
+     *          the list of blocks
+     * @param context_port
+     *          the list of ports
+     */
+    private void replacePort(String key, Hashtable<String, List<? extends mxICell>> context_block, Map<String, List<? extends mxICell>> context_port) {
+        // iterate on the superdiagram blocks
+        for (mxICell cell : context_block.get(key)) {
+            if (cell instanceof BasicBlock) {
+                BasicBlock basicblock = (BasicBlock) cell;
+                int order = (int) ((ScilabDouble) basicblock.getIntegerParameters()).getRealPart()[0][0];
+
+                // verify superblock port coherence
+                List<? extends mxICell> port_list = context_port.get(key);
+                BasicPort basicport = null;
+                boolean port_found = false;
+                for (mxICell port : port_list) {
+                    if (port instanceof BasicPort) {
+                        basicport = (BasicPort) port;
+                        if (order == basicport.getOrdering()) {
+                            port_found = true;
+                            break;
+                        }
+                    }
+                }
+
+                if (port_found == true) {
+                    boolean port_deleted = false;
+                    port_deleted = removeOnePort(order, basicport, basicblock);
+
+                    // add the port on the superblock if deleted
+                    if (port_deleted == true) {
+                        insertOnePort(order, basicblock);
+                    }
+                } else {
+                    insertOnePort(order, basicblock);
                 }
-                portCount++;
             }
+        }
+    }
+
+    /**
+     * Function that updates super block ports in parent diagram
+     */
+    public void updateExportedPort() {
+        if (child == null) {
+            return;
+        }
+        if (getParentDiagram() == null) {
+            setParentDiagram(Xcos.findParent(this));
+        }
 
-            // remove ports if required
-            while (portCount > blockCount) {
-                removePort((BasicPort) portsMap.get(block).get(portCount - 1));
-                portCount--;
+        // extracting blocks from the superdiagram
+        Hashtable<String, List<? extends mxICell>> context_block = extractContextBlocks();
+        // extracting ports from the superblock
+        Hashtable<String, List<? extends mxICell>> context_port = extractContextPorts();
+
+        for (String key : context_block.keySet()) {
+            if (context_block.get(key).size() > context_port.get(key).size()) {
+                // adding ports of the superblock
+                addPorts(key, context_block, context_port);
+            } else if (context_block.get(key).size() < context_port.get(key).size()) {
+                // removing ports of the superblock
+                removePorts(key, context_block, context_port);
+            } else {
+                // reordering ports of the superblock
+                removeDeadPorts(key, context_block, context_port);
+                replacePort(key, context_block, context_port);
             }
         }
+
         getParentDiagram().fireEvent(new mxEventObject(XcosEvent.SUPER_BLOCK_UPDATED, XcosConstants.EVENT_BLOCK_UPDATED, this));
     }
 
index e6014f2..f8df45e 100644 (file)
@@ -297,8 +297,8 @@ public abstract class ContextUpdate extends BasicBlock {
          *            the parent
          * @return the port list mapped by port type
          */
-        public static Map<IOBlocks, List<mxICell>> getAllBlocks(SuperBlock parent) {
-            final EnumMap<IOBlocks, List<mxICell>> ret = new EnumMap<IOBlocks, List<mxICell>>(IOBlocks.class);
+        public static Map<IOBlocks, List<BasicBlock>> getAllBlocks(SuperBlock parent) {
+            final EnumMap<IOBlocks, List<BasicBlock>> ret = new EnumMap<IOBlocks, List<BasicBlock>>(IOBlocks.class);
 
             SuperBlockDiagram graph = parent.getChild();
             if (graph == null) {
@@ -308,7 +308,7 @@ public abstract class ContextUpdate extends BasicBlock {
 
             /* Allocation */
             for (IOBlocks b : IOBlocks.values()) {
-                ret.put(b, new ArrayList<mxICell>());
+                ret.put(b, new ArrayList<BasicBlock>());
             }
 
             /* Loop all over the children */
index a7dd64e..b0519e1 100644 (file)
@@ -124,10 +124,10 @@ public class XcosDiagram extends ScilabGraph {
 
     private static final String MODIFIED = "modified";
     private static final String CELLS = "cells";
-    protected static final String IN = "in";
-    protected static final String OUT = "out";
-    protected static final String EIN = "ein";
-    protected static final String EOUT = "eout";
+    public static final String IN = "in";
+    public static final String OUT = "out";
+    public static final String EIN = "ein";
+    public static final String EOUT = "eout";
 
     /**
      * Prefix used to tag text node.
@@ -256,7 +256,7 @@ public class XcosDiagram extends ScilabGraph {
      *            the block list
      * @return the sorted block list (same instance)
      */
-    private List <? extends BasicBlock > iparSort(final List <? extends BasicBlock > blocks) {
+    public List <? extends BasicBlock > iparSort(final List <? extends BasicBlock > blocks) {
         Collections.sort(blocks, new Comparator<BasicBlock>() {
             @Override
             public int compare(BasicBlock o1, BasicBlock o2) {
index ed1482b..763780e 100644 (file)
@@ -356,11 +356,11 @@ public final class DiagramElement extends AbstractElement<XcosDiagram> {
         // Assume that the children are sorted after decode
         // blk.sortChildren();
         final Map<IOBlocks, List<mxICell>> ports = IOBlocks.getAllPorts(parent);
-        final Map<IOBlocks, List<mxICell>> blocks = IOBlocks.getAllBlocks(parent);
+        final Map<IOBlocks, List<BasicBlock>> blocks = IOBlocks.getAllBlocks(parent);
 
         for (final IOBlocks io : IOBlocks.values()) {
             final List<mxICell> port = ports.get(io);
-            final List<mxICell> block = blocks.get(io);
+            final List<BasicBlock> block = blocks.get(io);
 
             final int len = Math.min(port.size(), block.size());
             for (int i = 0; i < len; i++) {
index 934823a..f4fdb17 100644 (file)
@@ -14,6 +14,7 @@ package org.scilab.modules.xcos.utils;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 import java.util.Map;
 
@@ -47,6 +48,25 @@ public final class BlockPositioning {
     }
 
     /**
+     *
+     */
+    public static class PortComparator implements Comparator<BasicPort> {
+        @Override
+        public int compare(BasicPort arg0, BasicPort arg1) {
+            int order_0 = arg0.getOrdering();
+            int order_1 = arg1.getOrdering();
+
+            if (order_0 < order_1) {
+                return -1;
+            } else if (order_0 > order_1) {
+                return 1;
+            } else {
+                return 0;
+            }
+        }
+    }
+
+    /**
      * Dispatch ports on Block's _WEST_ side.
      *
      * @param block
@@ -63,6 +83,11 @@ public final class BlockPositioning {
             gridSize = block.getParentDiagram().getGridSize();
         }
 
+        // BasicBlock.sortsort(List<?> children) takes into account different 
+        // parameters to order the ports list. We only need to order the ports
+        // given their ordering.
+        Collections.sort(ports, new PortComparator());
+
         final mxGeometry blockGeom = block.getGeometry();
         assert blockGeom != null;
         final int portsSize = ports.size();
@@ -75,12 +100,7 @@ public final class BlockPositioning {
             final mxGeometry portGeom = port.getGeometry();
 
             double nonVariantPosition = -portGeom.getWidth();
-            final int order;
-            if (port.getOrdering() <= portsSize) {
-                order = port.getOrdering() - 1;
-            } else {
-                order = i;
-            }
+            final int order = i;
             double alignedPosition = calculateAlignedPosition(gridSize, segLength, order);
 
             portGeom.setX(nonVariantPosition);
@@ -139,6 +159,11 @@ public final class BlockPositioning {
             gridSize = block.getParentDiagram().getGridSize();
         }
 
+        // BasicBlock.sortsort(List<?> children) takes into account different 
+        // parameters to order the ports list. We only need to order the ports
+        // given their ordering.
+        Collections.sort(ports, new PortComparator());
+
         final mxGeometry blockGeom = block.getGeometry();
         assert blockGeom != null;
         final int portsSize = ports.size();
@@ -151,12 +176,7 @@ public final class BlockPositioning {
             final mxGeometry portGeom = port.getGeometry();
 
             double nonVariantPosition = -portGeom.getHeight();
-            final int order;
-            if (port.getOrdering() <= portsSize) {
-                order = port.getOrdering() - 1;
-            } else {
-                order = i;
-            }
+            final int order = i;
             double alignedPosition = calculateAlignedPosition(gridSize, segLength, order);
 
             portGeom.setX(alignedPosition);
@@ -183,6 +203,11 @@ public final class BlockPositioning {
             gridSize = block.getParentDiagram().getGridSize();
         }
 
+        // BasicBlock.sortsort(List<?> children) takes into account different 
+        // parameters to order the ports list. We only need to order the ports
+        // given their ordering.
+        Collections.sort(ports, new PortComparator());
+
         final mxGeometry blockGeom = block.getGeometry();
         assert blockGeom != null;
         final int portsSize = ports.size();
@@ -195,12 +220,7 @@ public final class BlockPositioning {
             final mxGeometry portGeom = port.getGeometry();
 
             double nonVariantPosition = blockGeom.getWidth();
-            final int order;
-            if (port.getOrdering() <= portsSize) {
-                order = port.getOrdering() - 1;
-            } else {
-                order = i;
-            }
+            final int order = i;
             double alignedPosition = calculateAlignedPosition(gridSize, segLength, order);
 
             portGeom.setX(nonVariantPosition);
@@ -227,6 +247,11 @@ public final class BlockPositioning {
             gridSize = block.getParentDiagram().getGridSize();
         }
 
+        // BasicBlock.sortsort(List<?> children) takes into account different 
+        // parameters to order the ports list. We only need to order the ports
+        // given their ordering.
+        Collections.sort(ports, new PortComparator());
+
         final mxGeometry blockGeom = block.getGeometry();
         assert blockGeom != null;
         final int portsSize = ports.size();
@@ -239,12 +264,7 @@ public final class BlockPositioning {
             final mxGeometry portGeom = port.getGeometry();
 
             double nonVariantPosition = blockGeom.getHeight();
-            final int order;
-            if (port.getOrdering() <= portsSize) {
-                order = port.getOrdering() - 1;
-            } else {
-                order = i;
-            }
+            final int order = i;
             double alignedPosition = calculateAlignedPosition(gridSize, segLength, order);
 
             portGeom.setX(alignedPosition);