Xcos save: generate uniques but predictables UIDs 49/17549/3
Clément DAVID [Tue, 8 Dec 2015 09:14:03 +0000 (10:14 +0100)]
This commit allow reproductible edit / save cycles without dummy
modification. This allow the use of a VCS to track modification.

Change-Id: I5edb08038e3b08cb7e996e14a9d65d4195d4166e

14 files changed:
scilab/modules/xcos/src/java/org/scilab/modules/xcos/graph/XcosDiagram.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/XcosFileType.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/sax/BlockHandler.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/sax/CustomHandler.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/sax/XcosSAXHandler.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/BlockModelElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/InputPortElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/LinkElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/scicos/OutputPortElement.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/BlockWriter.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/CustomWriter.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/LinkWriter.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/PortWriter.java
scilab/modules/xcos/src/java/org/scilab/modules/xcos/io/writer/XcosWriter.java

index 5511d70..746689d 100644 (file)
@@ -1791,6 +1791,17 @@ public class XcosDiagram extends ScilabGraph {
         info(XcosMessages.EMPTY_INFO);
     }
 
+    @Override
+    public void setSavedFile(File savedFile) {
+        super.setSavedFile(savedFile);
+
+        if (savedFile != null) {
+            JavaController controller = new JavaController();
+            controller.setObjectProperty(getUID(), getKind(), ObjectProperties.PATH, savedFile.getAbsolutePath());
+        }
+    }
+
+
     /**
      * Set the title of the diagram
      *
index 156376e..4ae5370 100644 (file)
@@ -153,8 +153,8 @@ public enum XcosFileType {
     private static final Logger LOG = Logger.getLogger(XcosFileType.class
                                       .getName());
 
-    private String extension;
-    private String description;
+    private final String extension;
+    private final String description;
 
     /**
      * Default constructor
@@ -253,7 +253,7 @@ public enum XcosFileType {
 
         int index = 0;
         for (FileFilter fileFilter : filters) {
-            if (fileFilter.getDescription() == filter.getDescription()) {
+            if (fileFilter.getDescription().equals(filter.getDescription())) {
                 break;
             }
 
@@ -312,9 +312,7 @@ public enum XcosFileType {
             try {
                 new XcosPackage(theFile).checkHeader();
                 retValue = ZCOS;
-            } catch (IOException e) {
-            } catch (ParserConfigurationException e) {
-            } catch (TransformerException e) {
+            } catch (IOException | ParserConfigurationException | TransformerException e) {
             }
         }
 
@@ -339,7 +337,7 @@ public enum XcosFileType {
      *
      * @param file
      *            the file to save to
-     * @param into
+     * @param from
      *            the diagram instance to save
      * @throws Exception
      *             in case of problem
index 477ccdb..dc7d575 100644 (file)
@@ -73,7 +73,6 @@ class BlockHandler implements ScilabHandler {
                 block = new BigSom(uid);
                 break;
             case ConstBlock:
-                // FIXME: why not needed anymore
                 block = new BasicBlock(uid);
                 break;
             case EventInBlock:
@@ -89,7 +88,6 @@ class BlockHandler implements ScilabHandler {
                 block = new ExplicitOutBlock(uid);
                 break;
             case GainBlock:
-                // FIXME: why not needed anymore
                 block = new BasicBlock(uid);
                 break;
             case GroundBlock:
@@ -102,7 +100,6 @@ class BlockHandler implements ScilabHandler {
                 block = new ImplicitOutBlock(uid);
                 break;
             case PrintBlock:
-                // FIXME: why not needed anymore
                 block = new BasicBlock(uid);
                 break;
             case Product:
index ab620ad..d3fe9b5 100644 (file)
@@ -83,10 +83,7 @@ class CustomHandler implements ScilabHandler {
                 /*
                  * Decode some graph properties
                  */
-                v = atts.getValue("savedFile");
-                if (v != null) {
-                    saxHandler.controller.setObjectProperty(uid, Kind.DIAGRAM, ObjectProperties.PATH, v);
-                }
+                // the legacy savedFile attribute is removed to avoid any diff between two saved files with the same content
                 v = atts.getValue("debugLevel");
                 if (v != null) {
                     saxHandler.controller.setObjectProperty(uid, Kind.DIAGRAM, ObjectProperties.DEBUG_LEVEL, Integer.valueOf(v));
@@ -159,6 +156,7 @@ class CustomHandler implements ScilabHandler {
                 }
                 saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.COLOR, colors);
 
+                // TODO: implement a GUI to setup the title property (currently file name is used)
                 v = atts.getValue("title");
                 if (v != null) {
                     saxHandler.controller.setObjectProperty(uid, kind, ObjectProperties.TITLE, v);
index 634be7b..aedf7ed 100644 (file)
@@ -48,10 +48,10 @@ public class XcosSAXHandler extends DefaultHandler {
      * Utilities classes and methods
      */
     protected static class UnresolvedReference {
-        private ScicosObjectOwner owner;
-        private ObjectProperties property;
-        private ObjectProperties associatedProperty;
-        private int associatedPropertyIndex;
+        final private ScicosObjectOwner owner;
+        final private ObjectProperties property;
+        final private ObjectProperties associatedProperty;
+        final private int associatedPropertyIndex;
 
         public UnresolvedReference(ScicosObjectOwner owner, ObjectProperties property, ObjectProperties associatedProperty, int associatedPropertyIndex) {
             this.owner = owner;
@@ -100,7 +100,7 @@ public class XcosSAXHandler extends DefaultHandler {
 
     /** Contains the decoded parent' node (as an in-depth view of decoded elements) */
     Stack<Object> parents = new Stack<>();
-    /** Mapping of UUID JGraphX strings to an MVC decoded object */
+    /** Mapping of UID JGraphX strings to an MVC decoded object */
     Stack<HashMap<String, Long>> allChildren = new Stack<>();
     /** List of unresolved references that will be resolved at {@link HandledElement#XcosDiagram} or {@link HandledElement#SuperBlockDiagram} ending */
     HashMap<String, ArrayList<UnresolvedReference>> unresolvedReferences = new HashMap<>();
@@ -177,6 +177,8 @@ public class XcosSAXHandler extends DefaultHandler {
      *   <LI>{@link ObjectProperties#PARENT_BLOCK}
      *   <LI>{@link ObjectProperties#PARENT_DIAGRAM}
      *   <LI>{@link ObjectProperties#CHILDREN}
+     * </UL>
+     * @param cell to insert
      */
     protected void insertChild(final XcosCell cell) {
         long parentUID;
@@ -215,13 +217,13 @@ public class XcosSAXHandler extends DefaultHandler {
 
     @Override
     public void error(SAXParseException e) throws SAXException {
-        System.err.println("XcosSAXHandler warning: " + e.getSystemId() + " at line " + e.getLineNumber() + " column " + e.getColumnNumber());
+        System.err.println("XcosSAXHandler error: " + e.getSystemId() + " at line " + e.getLineNumber() + " column " + e.getColumnNumber());
         System.err.println(e.getMessage());
     }
 
     @Override
     public void fatalError(SAXParseException e) throws SAXException {
-        System.err.println("XcosSAXHandler warning: " + e.getSystemId() + " at line " + e.getLineNumber() + " column " + e.getColumnNumber());
+        System.err.println("XcosSAXHandler fatalError: " + e.getSystemId() + " at line " + e.getLineNumber() + " column " + e.getColumnNumber());
         System.err.println(e.getMessage());
     }
 }
index 244aa48..195734f 100644 (file)
 
 package org.scilab.modules.xcos.io.scicos;
 
+import java.rmi.server.UID;
 import static java.util.Arrays.asList;
 
 import java.util.List;
 
-import org.flexdock.util.UUID;
 import org.scilab.modules.types.ScilabBoolean;
 import org.scilab.modules.types.ScilabDouble;
 import org.scilab.modules.types.ScilabList;
@@ -157,7 +157,7 @@ final class BlockModelElement extends BlockPartsElement {
             int nbControlPort = dataNbControlPort.getHeight();
             for (int i = 0; i < nbControlPort; i++) {
                 final BasicPort port = new ControlPort(controller.createObject(Kind.PORT));
-                port.setId(UUID.randomUUID().toString());
+                port.setId(new UID().toString());
 
                 // do not use BasicPort#addPort() to avoid the view update
                 into.insert(port, baseIndex + i);
@@ -170,7 +170,7 @@ final class BlockModelElement extends BlockPartsElement {
             int nbCommandPort = dataNbCommandPort.getHeight();
             for (int i = 0; i < nbCommandPort; i++) {
                 final BasicPort port = new CommandPort(controller.createObject(Kind.PORT));
-                port.setId(UUID.randomUUID().toString());
+                port.setId(new UID().toString());
 
                 // do not use BasicPort#addPort() to avoid the view update
                 into.insert(port, baseIndex + i);
index a11d87f..09ccfaa 100644 (file)
@@ -12,9 +12,9 @@
 
 package org.scilab.modules.xcos.io.scicos;
 
+import java.rmi.server.UID;
 import java.util.List;
 
-import org.flexdock.util.UUID;
 import org.scilab.modules.graph.utils.StyleMap;
 import org.scilab.modules.types.ScilabDouble;
 import org.scilab.modules.types.ScilabMList;
@@ -102,7 +102,7 @@ public final class InputPortElement extends AbstractElement<InputPort> {
         data = (ScilabMList) element;
 
         port = allocatePort();
-        port.setId(UUID.randomUUID().toString());
+        port.setId(new UID().toString());
 
         port = beforeDecode(element, port);
 
index c712450..48d3677 100644 (file)
@@ -18,7 +18,6 @@ import java.lang.reflect.Constructor;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
-import java.util.UUID;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -39,6 +38,7 @@ import org.scilab.modules.xcos.port.BasicPort;
 
 import com.mxgraph.model.mxGeometry;
 import com.mxgraph.util.mxPoint;
+import java.rmi.server.UID;
 
 /**
  * Perform a link transformation between Scicos and Xcos.
@@ -137,7 +137,7 @@ public final class LinkElement extends AbstractElement<BasicLink> {
             LOG.severe(e.toString());
         }
 
-        link.setId(UUID.randomUUID().toString());
+        link.setId(new UID().toString());
         return link;
     }
 
index dedfdf0..e0fa6b8 100644 (file)
@@ -12,9 +12,9 @@
 
 package org.scilab.modules.xcos.io.scicos;
 
+import java.rmi.server.UID;
 import java.util.List;
 
-import org.flexdock.util.UUID;
 import org.scilab.modules.graph.utils.StyleMap;
 import org.scilab.modules.types.ScilabDouble;
 import org.scilab.modules.types.ScilabMList;
@@ -104,7 +104,7 @@ public final class OutputPortElement extends AbstractElement<OutputPort> {
         data = (ScilabMList) element;
 
         port = allocatePort();
-        port.setId(UUID.randomUUID().toString());
+        port.setId(new UID().toString());
 
         port = beforeDecode(element, port);
 
index 2fdf4c4..78a2692 100644 (file)
@@ -11,8 +11,8 @@
  */
 package org.scilab.modules.xcos.io.writer;
 
+import java.rmi.server.UID;
 import java.util.EnumSet;
-import java.util.UUID;
 
 import javax.xml.stream.XMLStreamException;
 
@@ -48,10 +48,10 @@ public class BlockWriter extends ScilabWriter {
         String[] v = new String[1];
 
         shared.controller.getObjectProperty(uid, kind, ObjectProperties.UID, v);
-        if (v[0].isEmpty()) {
-            v[0] = UUID.randomUUID().toString();
-            shared.controller.setObjectProperty(uid, kind, ObjectProperties.UID, v[0]);
+        while (v[0].isEmpty() || shared.uniqueUIDs.contains(v[0])) {
+            v[0] = new UID().toString();
         }
+        shared.controller.setObjectProperty(uid, kind, ObjectProperties.UID, v[0]);
         shared.stream.writeAttribute("id", v[0]);
         shared.stream.writeAttribute("parent", shared.layers.peek());
         shared.layers.push(v[0]);
index 1a24404..e8d430a 100644 (file)
@@ -11,7 +11,7 @@
  */
 package org.scilab.modules.xcos.io.writer;
 
-import java.util.UUID;
+import java.rmi.server.UID;
 
 import javax.xml.stream.XMLStreamException;
 
@@ -57,9 +57,6 @@ public class CustomWriter extends ScilabWriter {
                 /*
                  * Write diagram content
                  */
-
-                shared.controller.getObjectProperty(uid, kind, ObjectProperties.PATH, str);
-                shared.stream.writeAttribute("savedFile", str[0]);
                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.DEBUG_LEVEL, integer);
                 shared.stream.writeAttribute("debugLevel", Integer.toString(integer[0]));
 
@@ -86,7 +83,9 @@ public class CustomWriter extends ScilabWriter {
 
                 // write the graphical part and children
                 shared.controller.getObjectProperty(uid, kind, ObjectProperties.CHILDREN, children);
-                writeDiagramAndSuperDiagramContent(uid, kind, children);
+                String zeroUID = new UID((short) 0).toString();
+                shared.uniqueUIDs.add(zeroUID);
+                writeDiagramAndSuperDiagramContent(uid, kind, children, zeroUID);
 
                 shared.stream.writeEndElement();
                 shared.stream.writeEndDocument();
@@ -99,7 +98,7 @@ public class CustomWriter extends ScilabWriter {
                 if (children.size() > 0) {
                     shared.stream.writeStartElement(HandledElement.SuperBlockDiagram.name());
                     shared.stream.writeAttribute("as", "child");
-                    writeDiagramAndSuperDiagramContent(uid, kind, children);
+                    writeDiagramAndSuperDiagramContent(uid, kind, children, shared.layers.peek());
                     shared.stream.writeEndElement(); // SuperBlockDiagram
                 }
                 break;
@@ -111,7 +110,7 @@ public class CustomWriter extends ScilabWriter {
         }
     }
 
-    private void writeDiagramAndSuperDiagramContent(long uid, Kind kind, VectorOfScicosID children) throws XMLStreamException {
+    private void writeDiagramAndSuperDiagramContent(long uid, Kind kind, VectorOfScicosID children, String parentUID) throws XMLStreamException {
         VectorOfInt colors = new VectorOfInt();
         shared.controller.getObjectProperty(uid, kind, ObjectProperties.COLOR, colors);
         shared.stream.writeAttribute("background", Integer.toString(colors.get(0)));
@@ -126,19 +125,32 @@ public class CustomWriter extends ScilabWriter {
          */
         shared.rawDataWriter.write(uid, kind);
 
-        UUID root = UUID.randomUUID();
-        UUID layer = UUID.randomUUID();
-        shared.layers.push(layer.toString());
+        /*
+         * Generate uniques but predictables UIDs
+         */
+        String[] parent = parentUID.split(":");
+        long uidCounter = 1;
+        String rootUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
+        for (; shared.uniqueUIDs.contains(rootUID); uidCounter++) {
+            rootUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
+        }
+        shared.uniqueUIDs.add(rootUID);
+        String layerUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
+        for (; shared.uniqueUIDs.contains(layerUID); uidCounter++) {
+            layerUID = parent[0] + ":" + Long.toString(Long.parseLong(parent[1], 16) + uidCounter, 16) + ":" + parent[2];
+        }
+        shared.uniqueUIDs.add(layerUID);
+        shared.layers.push(layerUID);
 
         // children header
         shared.stream.writeStartElement("mxGraphModel");
         shared.stream.writeAttribute("as", "model");
         shared.stream.writeStartElement("root");
         shared.stream.writeEmptyElement("mxCell");
-        shared.stream.writeAttribute("id", root.toString());
+        shared.stream.writeAttribute("id", rootUID);
         shared.stream.writeEmptyElement("mxCell");
-        shared.stream.writeAttribute("id", shared.layers.peek());
-        shared.stream.writeAttribute("parent", root.toString());
+        shared.stream.writeAttribute("id", layerUID);
+        shared.stream.writeAttribute("parent", rootUID);
 
         // loop on all children, encode the blocks and ports then the links
         VectorOfInt kinds = new VectorOfInt();
@@ -156,7 +168,7 @@ public class CustomWriter extends ScilabWriter {
         shared.stream.writeEndElement(); // mxGraphModel
         shared.stream.writeEmptyElement("mxCell");
         shared.stream.writeAttribute("as", "defaultParent");
-        shared.stream.writeAttribute("id", layer.toString());
-        shared.stream.writeAttribute("parent", root.toString());
+        shared.stream.writeAttribute("id", layerUID);
+        shared.stream.writeAttribute("parent", rootUID);
     }
 }
index 0289892..c488740 100644 (file)
@@ -11,6 +11,7 @@
  */
 package org.scilab.modules.xcos.io.writer;
 
+import java.rmi.server.UID;
 import javax.xml.stream.XMLStreamException;
 
 import org.scilab.modules.xcos.Kind;
@@ -72,7 +73,12 @@ public class LinkWriter extends ScilabWriter {
         if (!src[0].isEmpty() && !dst[0].isEmpty()) {
             shared.stream.writeStartElement(localName);
 
+            while (id[0].isEmpty() || shared.uniqueUIDs.contains(id[0])) {
+                id[0] = new UID().toString();
+            }
+            shared.controller.setObjectProperty(uid, kind, ObjectProperties.UID, id[0]);
             shared.stream.writeAttribute("id", id[0]);
+
             shared.stream.writeAttribute("parent", shared.layers.peek());
 
             shared.stream.writeAttribute("source", src[0]);
index ef52a99..d37c049 100644 (file)
@@ -11,6 +11,7 @@
  */
 package org.scilab.modules.xcos.io.writer;
 
+import java.rmi.server.UID;
 import javax.xml.stream.XMLStreamException;
 
 import org.scilab.modules.xcos.Kind;
@@ -75,7 +76,12 @@ public class PortWriter extends ScilabWriter {
         shared.stream.writeEmptyElement(localName);
 
         shared.controller.getObjectProperty(uid, kind, ObjectProperties.UID, str);
+        while (str[0].isEmpty() || shared.uniqueUIDs.contains(str[0])) {
+            str[0] = new UID().toString();
+        }
+        shared.controller.setObjectProperty(uid, kind, ObjectProperties.UID, str[0]);
         shared.stream.writeAttribute("id", str[0]);
+
         shared.stream.writeAttribute("parent", shared.layers.peek());
         shared.stream.writeAttribute("ordering", Integer.toString(++ordering));
 
index 7550614..65e6edf 100644 (file)
@@ -11,6 +11,7 @@
  */
 package org.scilab.modules.xcos.io.writer;
 
+import java.util.HashSet;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
@@ -36,6 +37,7 @@ public class XcosWriter {
     protected final RawDataWriter rawDataWriter;
     protected final XMLStreamWriter stream;
     protected final Stack<String> layers;
+    protected final HashSet<String> uniqueUIDs;
 
     public XcosWriter(ScilabList dictionary, XMLStreamWriter writer) {
         this.controller = new JavaController();
@@ -44,6 +46,7 @@ public class XcosWriter {
         this.stream = writer;
 
         this.layers = new Stack<>();
+        this.uniqueUIDs = new HashSet<>();
     }
 
     public void write(long uid, Kind kind) throws XMLStreamException {