Xcos decoder: fix de-serialization issue 50/14050/2
Clément DAVID [Tue, 18 Mar 2014 08:45:57 +0000 (09:45 +0100)]
mxCodec.getElementById() is unable to retrieve id due to the wrong
document root. Override this behavior using DOM Level 3,
Document.getElementById() and user-defined ID to avoid using XPATH
expression.

Change-Id: I1f7e10d1d442e998bc2e7cc15b049809d5086c38

scilab/modules/xcos/src/java/org/scilab/modules/xcos/block/SuperBlock.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/XcosFileType.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/codec/BasicLinkCodec.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/codec/XcosCodec.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/codec/XcosObjectCodec.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/spec/ContentEntry.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/utils/FileUtils.java

index 3d3088c..a24730a 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
+ * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
@@ -18,6 +19,9 @@ import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
 
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.scilab.modules.commons.xml.ScilabDocumentBuilderFactory;
 import org.scilab.modules.graph.ScilabGraph;
 import org.scilab.modules.gui.contextmenu.ContextMenu;
 import org.scilab.modules.gui.menu.Menu;
@@ -45,6 +49,7 @@ import org.scilab.modules.xcos.utils.FileUtils;
 import org.scilab.modules.xcos.utils.XcosConstants;
 import org.scilab.modules.xcos.utils.XcosEvent;
 import org.scilab.modules.xcos.utils.XcosMessages;
+import org.w3c.dom.Document;
 import org.w3c.dom.Node;
 
 import com.mxgraph.model.mxICell;
@@ -348,7 +353,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * Function that insert one port on the concerned superblock
      * and gives it the right order.
-     * 
+     *
      * @param order
      * @param basicblock
      */
@@ -366,15 +371,14 @@ public final class SuperBlock extends BasicBlock {
             Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
         } catch (IllegalAccessException e) {
             Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
-        } catch (Exception e)
-        {
+        } catch (Exception e) {
             Logger.getLogger(SuperBlock.class.getName()).severe(e.toString());
         }
     }
 
     /**
      * Function that remove one port on the concerned superblock
-     * 
+     *
      * @param order
      * @param basicport
      * @param basicblock
@@ -397,7 +401,7 @@ public final class SuperBlock extends BasicBlock {
     }
 
     /**
-     * 
+     *
      * @param basicport
      */
     private void removeOnePort(BasicPort basicport) {
@@ -408,7 +412,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * Function that returns a hashtable of IOBlocks contained in the superdiagram
      * depending on their direction.
-     * 
+     *
      * @param blockMap
      *            a map of blocks
      * @return the hashtable
@@ -445,7 +449,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * Function that returns a hashtable of the superblock ports
      * depending on their direction.
-     * 
+     *
      * @param portsMap
      *            a map of ports
      * @return the hashtable
@@ -482,7 +486,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * 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
@@ -490,8 +494,7 @@ public final class SuperBlock extends BasicBlock {
      * @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)
-    {
+    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) {
@@ -522,7 +525,7 @@ public final class SuperBlock extends 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
@@ -544,8 +547,7 @@ public final class SuperBlock extends BasicBlock {
                     if (block instanceof BasicBlock) {
                         BasicBlock basicblock = (BasicBlock) block;
                         int block_order = (int) ((ScilabDouble) basicblock.getIntegerParameters()).getRealPart()[0][0];
-                        if (order == block_order)
-                        {
+                        if (order == block_order) {
                             block_found = true;
                             break;
                         }
@@ -563,7 +565,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * 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
@@ -603,7 +605,7 @@ public final class SuperBlock extends BasicBlock {
     /**
      * Function that replace a port of a superblock
      * if its numbering has changed
-     * 
+     *
      * @param key
      *          direction of the block ports
      * @param context_block
@@ -759,9 +761,11 @@ public final class SuperBlock extends BasicBlock {
      *            the output stream
      * @throws IOException
      *             on error
+     * @throws ParserConfigurationException on error
      */
-    private void writeObject(java.io.ObjectOutputStream out) throws IOException {
-        out.writeObject(new XcosCodec().encode(this));
+    private void writeObject(java.io.ObjectOutputStream out) throws IOException, ParserConfigurationException {
+        final XcosCodec codec = new XcosCodec();
+        out.writeObject(codec.encode(this));
     }
 
     /**
@@ -773,9 +777,14 @@ public final class SuperBlock extends BasicBlock {
      *             on error
      * @throws ClassNotFoundException
      *             on error
+     * @throws ParserConfigurationException on error
      */
-    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
-        new XcosCodec().decode((Node) in.readObject(), this);
+    private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException, ParserConfigurationException {
+        final Node input = (Node) in.readObject();
+        final XcosCodec codec = new XcosCodec(input.getOwnerDocument());
+
+        codec.setElementIdAttributes();
+        codec.decode(input, this);
 
         /*
          * Specific post serialization things
index 5006b81..4810726 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2009 - DIGITEO - Clement DAVID
- * Copyright (C) 2011-2012 - Scilab Enterprises - Clement DAVID
+ * Copyright (C) 2011-2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
@@ -96,13 +96,14 @@ public enum XcosFileType {
             try {
                 src = new StreamSource(new File(file).toURI().toURL()
                                        .toString());
-                final DOMResult result = new DOMResult();
+                final DOMResult result = new DOMResult(codec.getDocument());
 
                 LOG.entering("Transformer", "transform");
                 aTransformer.transform(src, result);
                 LOG.exiting("Transformer", "transform");
 
                 LOG.entering("XcosCodec", "decode");
+                codec.setElementIdAttributes();
                 codec.decode(result.getNode().getFirstChild(), into);
                 LOG.exiting("XcosCodec", "decode");
             } catch (MalformedURLException e) {
index 0556536..499ba1d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2011 - Scilab Enterprises - Clement DAVID
+ * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
index f7fd4d0..8257511 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
+ * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
 
 package org.scilab.modules.xcos.io.codec;
 
+import java.util.logging.Logger;
+
 import org.scilab.modules.graph.io.ScilabObjectCodec;
 import org.scilab.modules.types.ScilabList;
 import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
 
 import com.mxgraph.io.mxCodec;
 import com.mxgraph.io.mxCodecRegistry;
+import com.mxgraph.io.mxObjectCodec;
 
 /**
  * Root codec for Xcos diagram instance.
@@ -82,14 +89,55 @@ public class XcosCodec extends mxCodec {
         super();
     }
 
+    public XcosCodec(Document document) {
+        super(document);
+    }
+
+
+    /**
+     * Set the setIdAttribute for all node in the {@link Document}.
+     */
+    public void setElementIdAttributes () {
+        setElementIdAttributes(getDocument());
+    }
+
     /**
-     * Construct a new codec associated with the document.
+     * Set the setIdAttribute for all node in the {@link Node}.
      *
-     * @param document
-     *            the document containing all the data.
+     * After this call the user can easily getElementById() on the DOM tree.
+     *
+     * @param n the root node to start with
      */
-    public XcosCodec(Document document) {
-        super(document);
+    public static void setElementIdAttributes (final Node root) {
+        for (Node next = root.getNextSibling(); next != null; next = next.getNextSibling()) {
+            if (next.getNodeType() == Node.ELEMENT_NODE) {
+                final Element elem = (Element) next;
+
+                if (elem.hasAttribute("id")) {
+                    elem.setIdAttribute("id", true);
+                }
+            }
+        }
+
+        NodeList children = root.getChildNodes();
+        for (int i = 0; i < children.getLength(); i++) {
+            final Node child = children.item(i);
+            if (child.getNodeType() == Node.ELEMENT_NODE) {
+                setElementIdAttributes(child);
+            }
+        }
+    }
+
+    /**
+     * As each node has an xml:id, use getElementById() instead of an xpath expression (through JGraphX).
+     *
+     * {@inheritDoc}
+     */
+    @Override
+    public Object lookup(String id) {
+        final Element element = getDocument().getElementById(id);
+        final mxObjectCodec decoder = mxCodecRegistry.getCodec(element.getNodeName());
+        return decoder.decode(this, element);
     }
 
     public static Object enableBinarySerialization(ScilabList dictionary) {
index fb790ea..89c3a83 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2009 - DIGITEO - Bruno JOFRET
+ * Copyright (C) 2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
index 0d95ad4..8432339 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
- * Copyright (C) 2012 - Scilab Enterprises - Clement DAVID
+ * Copyright (C) 2012-2014 - Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
@@ -72,13 +72,14 @@ public class ContentEntry implements Entry {
             final Transformer aTransformer = tranFactory.newTransformer();
 
             final StreamSource src = new StreamSource(stream);
-            final DOMResult result = new DOMResult();
+            final DOMResult result = new DOMResult(codec.getDocument());
 
             LOG.entering("Transformer", "transform");
             aTransformer.transform(src, result);
             LOG.exiting("Transformer", "transform");
 
             LOG.entering("XcosCodec", "decode");
+            codec.setElementIdAttributes();
             if (dictionary == null) {
                 codec.decode(result.getNode().getFirstChild(), content);
             } else {
index a82fdb3..1be3a51 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
  * Copyright (C) 2010 - DIGITEO - Clement DAVID
- * Copyright (C) Scilab Enterprises - 2011 - Clement DAVID
+ * Copyright (C) 2011-2014 Scilab Enterprises - Clement DAVID
  *
  * This file must be used under the terms of the CeCILL.
  * This source file is licensed as described in the file COPYING, which
@@ -201,29 +201,6 @@ public final class FileUtils {
     }
 
     /**
-     * Load an Xcos file.
-     *
-     * @param xcosFile
-     *            xcos file
-     * @return opened document
-     */
-    public static Document loadXcosDocument(String xcosFile) {
-        DocumentBuilderFactory docBuilderFactory = ScilabDocumentBuilderFactory.newInstance();
-        DocumentBuilder docBuilder;
-
-        try {
-            docBuilder = docBuilderFactory.newDocumentBuilder();
-            return docBuilder.parse(xcosFile);
-        } catch (ParserConfigurationException e) {
-            return null;
-        } catch (SAXException e) {
-            return null;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
      * Export an HTML label String to a valid C identifier String.
      *
      * @param label