]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "OptionGroup: fixed Names field & ListItem disabled / selected flags"
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Wed, 5 Jul 2017 08:05:47 +0000 (11:05 +0300)
committerGerrit Code Review <gerrit2@www.simantics.org>
Wed, 5 Jul 2017 08:05:47 +0000 (11:05 +0300)
41 files changed:
bundles/org.simantics.acorn/src/org/simantics/acorn/lru/LRU.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/DelayedWriteGraph.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/PassthroughSerializerBinding.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/impl/TGRemover.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/Layer0Utils.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/util/TGRepresentation.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java
bundles/org.simantics.diagram/src/org/simantics/diagram/adapter/RouteGraphUtils.java
bundles/org.simantics.diagram/src/org/simantics/diagram/handler/Paster.java
bundles/org.simantics.layer0.utils/src/org/simantics/layer0/utils/writer/DelayedGraphWriter.java
bundles/org.simantics.modeling/src/org/simantics/modeling/ModelingUtils.java
bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java
bundles/org.simantics.modeling/src/org/simantics/modeling/adapters/CompositeCopyHandler.java
bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ComponentCopyAdvisor.java
bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/ElementCopyAdvisor.java
bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/NamingCreationInstruction.java
bundles/org.simantics.modeling/src/org/simantics/modeling/utils/OntologicalRequirementEnforceRequest.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRLiteral.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionTransformer.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/StandardExpressionVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/CHRStatement.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/block/StatementVisitor.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAClosure.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAExit.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAObject.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetFunctions.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java
bundles/org.simantics.structural2/src/org/simantics/structural2/utils/StructuralUtils.java
bundles/org.simantics.tests.modelled/src/org/simantics/tests/modelled/utils/ModelledSTSTest.java
bundles/org.simantics.ui/src/org/simantics/ui/workbench/ResourceEditorSupport.java
tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/MemoryLeakTest.java [new file with mode: 0644]

index 690ba426f209afd52035ac875530b1f7e2b3d763..48b7d4b10a9b34c80e9a68c7b536ef3840e48867 100644 (file)
@@ -556,18 +556,28 @@ public class LRU<MapKey,MapValue extends LRUObject<MapKey, MapValue>> {
                 boolean gotMutex = impl.tryAcquireMutex();
 
                 boolean done = false;
-                // TODO: fix this properly pleease
                 int count = 0;
+                long startTime = 0;
                 while (!done) {
 
                     if (gotMutex || borrowMutex) {
                         runWithMutex();
                         done = true;
                     } else {
-                        if (count % 100 == 0)
+                        if (count % 10 == 0) {
+                            // Taking too long, sleep for a while.
                             LOGGER.warn("Retry mutex acquire");
+                            try {
+                                Thread.sleep(10);
+                            } catch (InterruptedException e) {
+                            }
+                        }
                         gotMutex = impl.tryAcquireMutex();
-                        count++;
+                        long currentTime = System.currentTimeMillis();
+                        if ((currentTime - startTime) > 10) {
+                            startTime = currentTime;
+                            count++;
+                        }
                     }
 
                 }
index dec1f5396582ce29522d464a14202c18161ba20b..44e23d017c99864bdc16131cd620723cc1c40cdb 100644 (file)
@@ -12,8 +12,7 @@
 package org.simantics.db.impl.graph;
 
 
-import java.io.DataInput;
-import java.io.DataOutput;
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
@@ -22,10 +21,9 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.nio.file.Files;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
 import java.util.Set;
 import java.util.TreeMap;
 import java.util.UUID;
@@ -33,14 +31,10 @@ import java.util.UUID;
 import org.eclipse.core.runtime.Platform;
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.accessor.Accessor;
-import org.simantics.databoard.accessor.reference.ChildReference;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.error.BindingConstructionException;
-import org.simantics.databoard.binding.impl.BindingPrintContext;
-import org.simantics.databoard.serialization.SerializationException;
 import org.simantics.databoard.serialization.Serializer;
 import org.simantics.databoard.type.Datatype;
-import org.simantics.databoard.util.IdentityPair;
 import org.simantics.databoard.util.binary.RandomAccessBinary;
 import org.simantics.db.Metadata;
 import org.simantics.db.ReadGraph;
@@ -73,7 +67,6 @@ import org.simantics.db.service.XSupport;
 import org.simantics.layer0.Layer0;
 import org.simantics.utils.datastructures.MapList;
 
-import gnu.trove.list.array.TIntArrayList;
 import gnu.trove.map.hash.TIntIntHashMap;
 import gnu.trove.map.hash.TObjectIntHashMap;
 
@@ -82,164 +75,12 @@ import gnu.trove.map.hash.TObjectIntHashMap;
  * immediately but with an explicit commit method. All read operations
  * return results based on the old graph. 
  */
-public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader {
-       
-       private static final boolean DEBUG = false;
-       public static int BUFFER = 65536;
-
-       static class Haxx extends Binding {
-
-               static final Serializer serializer = new Serializer() {
-                       
-                       public byte[] serialize(Object obj) throws SerializationException {
-                               return (byte[])obj;
-                       }
-
-                       @Override
-                       public void serialize(DataOutput out,
-                                       TObjectIntHashMap<Object> identities, Object obj)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public void serialize(DataOutput out, Object obj)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public Object deserialize(DataInput in, List<Object> identities)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public Object deserialize(DataInput in) throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public void deserializeTo(DataInput in, List<Object> identities,
-                                       Object obj) throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public void deserializeTo(DataInput in, Object obj)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public void skip(DataInput in, List<Object> identities)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public void skip(DataInput in) throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public Integer getConstantSize() {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public int getSize(Object obj, TObjectIntHashMap<Object> identities)
-                                       throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public int getSize(Object obj) throws IOException {
-                               throw new Error("Not supported.");
-                       }
-
-                       @Override
-                       public int getMinSize() {
-                               throw new Error("Not supported.");
-                       }
-
-               };
-               
-               @Override
-               public Serializer serializer() {
-                       return serializer;
-               }
-               
-               @Override
-               public void accept(Visitor1 v, Object obj) {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public <T> T accept(Visitor<T> v) {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public boolean isInstance(Object obj) {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
-                               throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public int deepHashValue(Object value,
-                               IdentityHashMap<Object, Object> hashedObjects)
-                               throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public int deepCompare(Object o1, Object o2,
-                               Set<IdentityPair<Object, Object>> compareHistory)
-                               throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-               
-               @Override
-               public void readFrom(Binding srcBinding, Object src, Object dst)
-                               throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-               
-               @Override
-               public Object readFromTry(Binding srcBinding, Object src, Object dst)
-                               throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-               
-               @Override
-               protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {
-                       throw new Error("Not supported.");
-               }
-
-               @Override
-               public int getComponentCount() {
-                       throw new Error("Not supported.");
-               }
+public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, ByteReader, Closeable {
 
-               @Override
-               public Binding getComponentBinding(int index) {
-                       throw new Error("Not supported.");
-               }
+       private static final boolean DEBUG = false;
+       private static final int BUFFER_SIZE = 512*1024;
 
-               @Override
-               public Binding getComponentBinding(ChildReference path) {
-                       throw new Error("Not supported.");
-               }
-               
-       }
-       
-       private static final Haxx haxx = new Haxx();
+       private static final PassthroughSerializerBinding PASSTHROUGH = new PassthroughSerializerBinding();
 
        private final int TERM = 0;
        private final int CLAIM = 1;
@@ -248,30 +89,11 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
     private final int DENY = 5;
     private final int DENY_VALUE = 6;
     private final int COMMIT_AND_CONTINUE = 7;
-       
-    static class ClusterSet {
-       public Resource resource;
-        ClusterSet() {
-            ids = new TIntArrayList();
-            old = false;
-        }
-        ClusterSet(boolean old, Resource r) {
-            ids = new TIntArrayList();
-            this.old = old;
-            this.resource = r;
-        }
-        void add(int id) {
-            ids.add(id);
-        }
-        private TIntArrayList ids;
-        private final boolean old; // true if
-        boolean isNew() {
-            return !old;
-        }
-    }
-    public class State {
+
+    private static class State {
         public File tempFile;
         public FileOutputStream out;
+        public FileInputStream in;
         public ArrayList<Resource> idToResource = new ArrayList<Resource>();
         public TIntIntHashMap externalToId = new TIntIntHashMap(); 
         public ArrayList<Binding> idToBinding = new ArrayList<Binding>();
@@ -285,26 +107,31 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
         public int valueCount = 0;
         public int fileCount = 0;
     }
-    
-    public State writeState;
-    public TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
-       
-    Layer0 b;
-    Session session;
+
+    private State writeState;
+    private TreeMap<String,byte[]> metadata = new TreeMap<String,byte[]>();
+
+    private FileChannel channel;
+    private byte[] bytes = new byte[BUFFER_SIZE];
+    private ByteBuffer bb = ByteBuffer.wrap(bytes);
+    private int byteIndex = 0;
+
+    private Layer0 b;
+    private Session session;
+
     public static Resource convertDelayedResource(Resource r) {
-        if (r instanceof InternalResource) {
-            InternalResource ri = (InternalResource)r;
-            return ri.resource;
-        }
+        if (r instanceof InternalResource)
+            return ((InternalResource) r).resource;
         return r;
     }
+
     private static class InternalResource implements Resource {
 
         int id;
         long clusterId = 0;
         Resource resource = null;
         Resource clusterSet = null;
-        
+
         public InternalResource(int id, long clusterId) {
             this.id = id;
             this.clusterId = clusterId;
@@ -314,7 +141,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
             this.id = id;
             this.clusterSet = clusterSet;
         }
-        
+
         @Override
         public long getResourceId() {
             throw new UnsupportedOperationException();
@@ -324,7 +151,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
         public Resource get() {
             return this;
         }
-        
+
         @Override
         public boolean isPersistent() {
             return false;
@@ -332,11 +159,9 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
 
         @Override
         public int compareTo(Resource o) {
-               if(o instanceof InternalResource) {
-                       return Integer.compare(id, ((InternalResource)o).id);
-               } else {
-                       return -1;
-               }
+            if(o instanceof InternalResource)
+                return Integer.compare(id, ((InternalResource)o).id);
+            return -1;
         }
 
         @Override
@@ -346,7 +171,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
             result = prime * result + id;
             return result;
         }
-        
+
         @Override
         public int getThreadHash() {
             return hashCode();
@@ -365,12 +190,12 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                 return false;
             return true;
         }
-        
 
         @Override
         public boolean equalsResource(Resource other) {
             return equals(other);
         }
+
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(32);
@@ -432,7 +257,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
         session = g.getSession();
                b = Layer0.getInstance(g);
         this.writeState = state;
-    }   
+    }
 
        public DelayedWriteGraph newSync() {
         return new DelayedWriteGraph(this, writeState);
@@ -715,7 +540,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                if (ws.hasClusterSet(null, clusterSet))
                        throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
                writeState.clusterSetsForExistingResources.add(clusterSet);             
-        } else {        
+        } else {
                if(!writeState.clusterSets.add(clusterSet))
                        throw new ClusterSetExistException("Cluster set exist already. Resource=" + clusterSet);
         }
@@ -787,25 +612,25 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                }
        }
 
+       private OutputStream valueWriter = new OutputStream() {
+               @Override
+               public void write(int b) throws IOException {
+                       writeByte(b);
+               }
+       };
+
        @Override
        public void claimValue(Resource resource, Object value, Binding binding)
                        throws ServiceException {
                try {
-                       
+
                writeByte(CLAIM_VALUE_B);
                writeInt(getId(resource));
                Serializer serializer = binding.serializer();
                int size = serializer.getSize(value);
             writeInt(size);
-            serializer.serialize(new OutputStream() {
-                
-                @Override
-                public void write(int b) throws IOException {
-                    writeByte(b);
-                }
-                
-            }, value);
-                       
+            serializer.serialize(valueWriter, value);
+
                } catch(IOException e) {
                Logger.defaultLogError(e);
                        throw new ServiceException(e);
@@ -832,86 +657,76 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
     public void flushCluster(Resource r) throws ServiceException {
         throw new ServiceException("Operation flushCluster(" + r + " not implemented.");
     }
-       
-    private FileChannel channel;
-    byte[] bytes = new byte[BUFFER];
-    byte[] buffer = new byte[BUFFER];
-    ByteBuffer bb = ByteBuffer.wrap(bytes);
-    int byteIndex = 0;
-    
-    private void writeReset(int size) {
 
+    private void writeReset(int size) {
         byteIndex = 0;
         bb.position(0);
         bb.limit(size);
         try {
-
-            if(writeState.tempFile == null) {
-
+            if (writeState.tempFile == null) {
                 File workspace = Platform.getLocation().toFile();
                 File temp = new File(workspace, "tempFiles");
-                temp.mkdirs();
-
                 File base = new File(temp, "delayed");
-                base.mkdirs();
+                Files.createDirectories(base.toPath());
                 writeState.tempFile = new File(base, UUID.randomUUID().toString());
                 writeState.out = new FileOutputStream(writeState.tempFile);
                 channel = writeState.out.getChannel();
-                
             }
 
             for (int got=0;got < size;) {
                 int n = channel.write(bb); 
                 if (n <= 0) {
-                    new Exception().printStackTrace();
+                    Logger.defaultLogError(new Exception("FileChannel.write returned " + n));
                     return;
                 }
                 got += n;
             }
         } catch (IOException e) {
-            e.printStackTrace();
+            Logger.defaultLogError("Failed to write buffer of " + size + " bytes to temporary file " + writeState.tempFile, e);
         }
     }
 
     private void reset() {
         byteIndex = 0;
-        try {
-            bb.clear();
-            for(int got=0; got < BUFFER;) {
-                int n = channel.read(bb); 
-                if (n <= 0)
-                    return;
-                got += n;
+        bb.clear();
+        if (channel != null) {
+            try {
+                for(int got=0; got < BUFFER_SIZE;) {
+                    int n = channel.read(bb); 
+                    if (n <= 0)
+                        return;
+                    got += n;
+                }
+            } catch (IOException e) {
+                Logger.defaultLogError("FileChannel.read failed", e);
             }
-        } catch (IOException e) {
-            e.printStackTrace();
         }
     }
 
     private void writeInt(int i) {
-       if(byteIndex < (BUFFER-4)) {
+       if(byteIndex < (BUFFER_SIZE-4)) {
                bytes[byteIndex++] = (byte)(i&0xff);
                bytes[byteIndex++] = (byte)((i>>>8)&0xff);
                bytes[byteIndex++] = (byte)((i>>>16)&0xff);
                bytes[byteIndex++] = (byte)((i>>>24)&0xff);
-               if (byteIndex == BUFFER)
-                   writeReset(BUFFER);
+               if (byteIndex == BUFFER_SIZE)
+                   writeReset(BUFFER_SIZE);
        } else {
-               int has = BUFFER-byteIndex;
-               if(has == 0) writeReset(BUFFER);
+               int has = BUFFER_SIZE-byteIndex;
+               if(has == 0) writeReset(BUFFER_SIZE);
                bytes[byteIndex++] = (byte)(i&0xff);
-               if(has == 1) writeReset(BUFFER);
+               if(has == 1) writeReset(BUFFER_SIZE);
                bytes[byteIndex++] = (byte)((i>>>8)&0xff);
-               if(has == 2) writeReset(BUFFER);
+               if(has == 2) writeReset(BUFFER_SIZE);
                bytes[byteIndex++] = (byte)((i>>>16)&0xff);
-               if(has == 3) writeReset(BUFFER);
+               if(has == 3) writeReset(BUFFER_SIZE);
                bytes[byteIndex++] = (byte)((i>>>24)&0xff);
-               if(has == 4) writeReset(BUFFER);
+               if(has == 4) writeReset(BUFFER_SIZE);
        }
     }
-    
+
     private int readInt() {
-       if(byteIndex < (BUFFER-4)) {
+       if(byteIndex < (BUFFER_SIZE-4)) {
                int result = (int) 
                        ((bytes[byteIndex++] & 0xff) | 
                        ((bytes[byteIndex++] & 0xff)<<8) | 
@@ -919,7 +734,7 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                        ((bytes[byteIndex++] & 0xff)<<24)); 
                return result;
        } else {
-               int has = BUFFER-byteIndex;
+               int has = BUFFER_SIZE-byteIndex;
                int result = 0;
                if(has == 0) reset();
                        result = (int)(bytes[byteIndex++] & 0xff);
@@ -933,44 +748,40 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                return result;
        }
     }
-    
+
     private byte readByte() {
        byte result = bytes[byteIndex++]; 
-       if(byteIndex == BUFFER) reset();
+       if(byteIndex == BUFFER_SIZE) reset();
        return result;
     }
 
     private void writeByte(int b) {
        bytes[byteIndex++] = (byte)b;
-       if(byteIndex == BUFFER) writeReset(BUFFER);
+       if(byteIndex == BUFFER_SIZE) writeReset(BUFFER_SIZE);
     }
-    
+
     private void writeBytes(byte[] data) {
-               int has = BUFFER-byteIndex;
+               int has = BUFFER_SIZE-byteIndex;
                int amount = data.length;
                if(has > amount) {
                        System.arraycopy(data, 0, bytes, byteIndex, amount);
                        byteIndex += amount;
                } else {
                        System.arraycopy(data, 0, bytes, byteIndex, has);
-                       writeReset(BUFFER);
+                       writeReset(BUFFER_SIZE);
                        ByteBuffer bb2 = ByteBuffer.wrap(data);
                        bb2.position(has);
                        try {
                                channel.write(bb2);
                        } catch (IOException e) {
-                               e.printStackTrace();
+                               Logger.defaultLogError("FileChannel.write failed", e);
                        }
                }
     }
-    
-    public byte[] readBytes(int amount) {
-        return readBytes(buffer, amount);
-    }
-    
+
     public byte[] readBytes(byte[] result, int amount) {
         if(result == null) result = new byte[amount];
-               int has = BUFFER-byteIndex;
+               int has = BUFFER_SIZE-byteIndex;
                if(has > amount) {
                        System.arraycopy(bytes, byteIndex, result, 0, amount);
                        byteIndex += amount;
@@ -982,39 +793,46 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                                try {
                                        got += channel.read(bb2);
                                        if(got == -1) {
-                                               new Exception().printStackTrace();
+                                               // End-of-stream, why log this?
                                                return result;
                                        }
-                                       
                                } catch (IOException e) {
-                                       e.printStackTrace();
+                                       Logger.defaultLogError("FileChannel.read failed", e);
                                }
                        reset();
                }
                return result;
     }
-    
+
     public void commit(final WriteOnlyGraph w, final WriteTraits traits) throws ServiceException {
            writeState.bindingToId = null;
            writeState.externalToId = null;
-               try {
-                       
-                       writeByte(TERM);
-                       if(byteIndex > 0) {
+               writeByte(TERM);
+
+               if (writeState.out != null) {
+                       // Flush current buffer to file only if backing file has already
+                       // been taken into use.
+                       if (byteIndex > 0)
                                writeReset(byteIndex);
+
+                       try (OutputStream out = writeState.out) {
+                               channel.force(false);
+                       } catch (IOException e) {
+                               throw new ServiceException(e);
+                       } finally {
+                               writeState.out = null;
                        }
-                       channel.force(false);
-                       writeState.out.close();
 
-               FileInputStream fs = new FileInputStream(writeState.tempFile);
-               channel = fs.getChannel();
-                       
-               } catch (IOException e) {
-                       throw new ServiceException(e);
+                       try {
+                               writeState.in = new FileInputStream(writeState.tempFile);
+                               channel = writeState.in.getChannel();
+                       } catch (IOException e) {
+                               throw new ServiceException(e);
+                       }
                }
-               
+
                w.getMetadata().putAll(metadata);
-               
+
                TransferableGraphSupport tgs = w.getService(TransferableGraphSupport.class);
 
                // First create all resources defined by clusterId
@@ -1094,13 +912,20 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                }
                
                reset();
-               bb.limit(BUFFER);
+               bb.limit(BUFFER_SIZE);
                
                try {
                        while(true) {
                                byte method = readByte();
-                               switch(method) {                
+                               switch(method) {
                                case TERM: {
+                                       if (DEBUG) {
+                                               System.out.println("Resources:  " + writeState.idToResource.size());
+                                               System.out.println("Statements: " + writeState.statementCount);
+                                               System.out.println("Values:     " + writeState.valueCount);
+                                               System.out.println("Files:      " + writeState.fileCount);
+                                               System.out.println("Clusters:   " + writeState.clusterCount);
+                                       }
                                        return;
                                }
                                case CLAIM: {
@@ -1153,8 +978,6 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                                        Resource resource = getResource(readInt());
                                        int len = readInt();
                                        tgs.setValue(w, resource, null, this, len);
-//                                     byte[] bytes = readBytes(len);
-//                  tgs.setValue(resource, null, bytes);
                                } break;
                                case COMMIT_AND_CONTINUE: {
                                        XSupport xs = w.getService(XSupport.class);
@@ -1168,18 +991,19 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                        else
                                throw new ServiceException(e);
                } finally {
-                       try {
-                               channel.close();
-                               channel = null;
-                       } catch (IOException e) {
-                               throw new ServiceException(e);
+                       channel = null;
+                       if (writeState.in != null) {
+                               try (InputStream in = writeState.in) {
+                               } catch (IOException e) {
+                                       throw new ServiceException(e);
+                               } finally {
+                                       writeState.in = null;
+                                       writeState.tempFile.delete();
+                               }
                        }
                }
-//             System.out.println("Resources:  " + state.resourceCount);
-//             System.out.println("Statements: " + state.statementCount);
-//             System.out.println("Values:     " + state.valueCount);
        }
-       
+
        private Resource getType(Object value) {
                Class<?> clazz = value.getClass();
                Resource dataType = 
@@ -1196,12 +1020,12 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                        : clazz == String[].class ? b.StringArray
                        : clazz == boolean[].class ? b.BooleanArray
                        : clazz == byte[].class ? b.ByteArray
-                       : clazz == long[].class ? b.LongArray                                   
+                       : clazz == long[].class ? b.LongArray
                        : null
                        ;
                return dataType;
        }
-       
+
        public long newCluster() {
                return -1 - (++writeState.clusterCount);
        }
@@ -1209,14 +1033,14 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
        public long getDefaultCluster() {
                return writeState.defaultCluster;
        }
-       
+
        public void setDefaultCluster(long cluster) {
            writeState.defaultCluster = cluster;
        }
-    
+
     @Override
     public void syncRequest(final DelayedWrite request) throws DatabaseException {
-        
+
         try {
 
                final DelayedWriteGraph dwg = new DelayedWriteGraph(this);
@@ -1232,24 +1056,23 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                });
 
         } catch (DatabaseException e) {
-               
+
                throw e;
-               
+
         } catch (Throwable e) {
-               
+
                throw new DatabaseException(e);
-               
+
         } finally {
-               
         }
-        
+
     }
-    
+
     @Override
     public void syncRequest(WriteOnly request) throws DatabaseException {
-       
+
        Resource defaultClusterSet = setClusterSet4NewResource(null);
-       
+
         try {
             WriteSupport ws = session.getService(WriteSupport.class);
             ws.performWriteRequest(this, request);
@@ -1260,46 +1083,46 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
         }  finally {
             setClusterSet4NewResource(defaultClusterSet);
         }
-        
+
     }
 
     @SuppressWarnings("unchecked")
     @Override
     public <T> T getService(Class<T> api) {
-        
+
         if(ClusteringSupport.class == api) {
 
             final ClusteringSupport support = (ClusteringSupport)super.getService(api); 
 
             return (T)new ClusteringSupport() {
-                
+
                 @Override
                 public Resource getResourceByIndexAndCluster(int resourceIndex, long clusterId)
                         throws DatabaseException, ResourceNotFoundException {
                     return support.getResourceByIndexAndCluster(resourceIndex, clusterId);
                 }
-                
+
                 @Override
                 public Resource getResourceByKey(int resourceKey) throws ResourceNotFoundException {
                     return support.getResourceByKey(resourceKey);
                 }
-                
+
                 @Override
                 public int getNumberOfResources(long clusterId)
                                throws DatabaseException {
                        return support.getNumberOfResources(clusterId);
                 }
-                
+
                 @Override
                 public long getCluster(Resource r) {
                     return support.getCluster(r);
                 }
-                
+
                 @Override
                 public long createCluster() {
                     return newCluster();
                 }
-                
+
                 @Override
                 public boolean isClusterSet(Resource r) throws DatabaseException {
                        return support.isClusterSet(r);
@@ -1309,18 +1132,18 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                 public Resource getClusterSetOfCluster(Resource r) throws DatabaseException {
                        return support.getClusterSetOfCluster(r);
                 }
-                
+
                 @Override
                 public Resource getClusterSetOfCluster(long cluster) throws DatabaseException {
                        return support.getClusterSetOfCluster(cluster);
                 }
 
             };
-            
+
         } else if (TransferableGraphSupport.class == api) {
-               
+
                final TransferableGraphSupport parentSupport = session.getService(TransferableGraphSupport.class);
-               
+
                return (T)new TransferableGraphSupport() {
 
                        @Override
@@ -1329,9 +1152,9 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                                writeInt(getId(resource));
                                writeInt(raw.length);
                                writeBytes(raw);
-                               writeInt(getBindingId(haxx));
+                               writeInt(getBindingId(PASSTHROUGH));
                        }
-                       
+
                        @Override
                        public void setValue(WriteOnlyGraph graph, Resource resource, VirtualGraph provider, ByteReader reader, int amount)
                                throws DatabaseException {
@@ -1339,25 +1162,25 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
                     writeInt(getId(resource));
                     writeInt(amount);
                     writeBytes(reader.readBytes(null, amount));
-                    writeInt(getBindingId(haxx));
+                    writeInt(getBindingId(PASSTHROUGH));
                        }
-                       
+
                        @Override
                        public byte[] getValue(ReadGraph graph, Resource resource) {
                                return parentSupport.getValue(graph, resource);
                        }
-                       
+
                        @Override
                        public InputStream getValueStream(ReadGraph graph, Resource resource) {
                                return parentSupport.getValueStream(graph, resource);
                        }
-                       
+
                };
 
         }
-        
+
         return super.getService(api);
-        
+
     }
 
     @Override
@@ -1423,4 +1246,27 @@ public class DelayedWriteGraph extends ReadGraphImpl implements WriteGraph, Byte
         }
        }
 
+    public void close() {
+        if (writeState.out != null) {
+            try (OutputStream out = writeState.out) {
+            } catch (IOException e) {
+                Logger.defaultLogError("Failed to close delayed write graph temporary commit output stream", e);
+            } finally {
+               writeState.out = null;
+            }
+        }
+        if (writeState.in != null) {
+            try (InputStream in = writeState.in) {
+            } catch (IOException e) {
+                Logger.defaultLogError("Failed to close delayed write graph temporary commit input stream", e);
+            } finally {
+                writeState.in = null;
+            }
+        }
+        if (writeState.tempFile != null) {
+            writeState.tempFile.delete();
+            writeState.tempFile = null;
+        }
+    }
+
 }
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/PassthroughSerializerBinding.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/PassthroughSerializerBinding.java
new file mode 100644 (file)
index 0000000..8c95a51
--- /dev/null
@@ -0,0 +1,174 @@
+package org.simantics.db.impl.graph;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Set;
+
+import org.simantics.databoard.accessor.reference.ChildReference;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.impl.BindingPrintContext;
+import org.simantics.databoard.serialization.SerializationException;
+import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.util.IdentityPair;
+
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+/**
+ * Originally within DelayedWriteGraph, put in separate file in 1.30.0.
+ * 
+ * @author Antti Villberg
+ */
+class PassthroughSerializerBinding extends Binding {
+
+       static final Serializer serializer = new Serializer() {
+
+               public byte[] serialize(Object obj) throws SerializationException {
+                       return (byte[])obj;
+               }
+
+               @Override
+               public void serialize(DataOutput out,
+                               TObjectIntHashMap<Object> identities, Object obj)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public void serialize(DataOutput out, Object obj)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public Object deserialize(DataInput in, List<Object> identities)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public Object deserialize(DataInput in) throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public void deserializeTo(DataInput in, List<Object> identities,
+                               Object obj) throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public void deserializeTo(DataInput in, Object obj)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public void skip(DataInput in, List<Object> identities)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public void skip(DataInput in) throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public Integer getConstantSize() {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public int getSize(Object obj, TObjectIntHashMap<Object> identities)
+                               throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public int getSize(Object obj) throws IOException {
+                       throw new Error("Not supported.");
+               }
+
+               @Override
+               public int getMinSize() {
+                       throw new Error("Not supported.");
+               }
+
+       };
+
+       @Override
+       public Serializer serializer() {
+               return serializer;
+       }
+
+       @Override
+       public void accept(Visitor1 v, Object obj) {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public <T> T accept(Visitor<T> v) {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public boolean isInstance(Object obj) {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public void assertInstaceIsValid(Object obj, Set<Object> validInstances)
+                       throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public int deepHashValue(Object value,
+                       IdentityHashMap<Object, Object> hashedObjects)
+                       throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public int deepCompare(Object o1, Object o2,
+                       Set<IdentityPair<Object, Object>> compareHistory)
+                       throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public void readFrom(Binding srcBinding, Object src, Object dst)
+                       throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public Object readFromTry(Binding srcBinding, Object src, Object dst)
+                       throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       protected void toString(Object value, BindingPrintContext ctx) throws org.simantics.databoard.binding.error.BindingException {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public int getComponentCount() {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public Binding getComponentBinding(int index) {
+               throw new Error("Not supported.");
+       }
+
+       @Override
+       public Binding getComponentBinding(ChildReference path) {
+               throw new Error("Not supported.");
+       }
+
+}
\ No newline at end of file
index aae4b581bf5242fa215ac75ddcb52dfdbc4e176b..88594883488f71059dd6ef128b53e9d5176ce85c 100644 (file)
@@ -43,10 +43,9 @@ public class TGRemover extends AbstractRemover {
        
        TransferableGraphConfiguration2 conf = new TransferableGraphConfiguration2(graph, resource);
        conf.values = false;
-       ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf));
        final SerialisationSupport ss = graph.getService(SerialisationSupport.class);
        
-       try {
+       try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(conf))) {
                        source.forResourceStatements(graph, new TransferableGraphSourceProcedure<int[]>() {
                                
                                @Override
@@ -75,8 +74,6 @@ public class TGRemover extends AbstractRemover {
                                
                        });
                        
-                       source.closeStreams();
-                       
                } catch (Exception e) {
                        throw new DatabaseException(e);
                }
index beec63aa1b5a3f928111097b08284f497ba96b43..c04ca3cd1e0b758d1d66a8a8628887dab576f5cc 100644 (file)
@@ -1394,10 +1394,40 @@ public class Layer0Utils {
      * @param graph
      * @param component
      *            for which the identifier is added
+     * @param add
+     *            <code>true</code> to invoke addLiteral, <code>false</code> to
+     *            invoke claimLiteral
      * @throws DatabaseException
      */
-    public static void addL0Identifier(WriteGraph graph, Resource component) throws DatabaseException {
+    public static void claimNewIdentifier(WriteGraph graph, Resource component, boolean add) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
-        graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, GUID.random(), GUID.BINDING);
+        GUID guid = GUID.random();
+        if (add)
+            graph.addLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+        else
+            graph.claimLiteral(component, L0.identifier, L0.identifier_Inverse, L0.GUID, guid, GUID.BINDING);
+    }
+
+    /**
+     * Sets a new random unique identifier for the specified entity if it already
+     * has an identifier. If the entity does not have a previous identifier, nothing
+     * is done.
+     * 
+     * @param graph
+     * @param entity
+     *            for which the identifier is added
+     * @return <code>true</code> if the identifier was renewed, <code>false</code>
+     *         otherwise
+     * @throws DatabaseException
+     * @see {@link #claimNewIdentifier(WriteGraph, Resource, boolean)}
+     */
+    public static boolean renewIdentifier(WriteGraph graph, Resource entity) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        Statement stm = graph.getPossibleStatement(entity, L0.identifier);
+        if (stm != null) {
+            graph.claimValue(stm.getObject(), GUID.random(), GUID.BINDING);
+            return true;
+        }
+        return false;
     }
 }
index 0f9ffa0a73730314f7ba6d56a655f507d28d9b0c..ed7ae5193837190debb03efdc7c6244a1898d7fc 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.db.layer0.util;
 
+import java.io.IOException;
 import java.util.Arrays;
 import java.util.Map;
 
@@ -49,9 +50,11 @@ public class TGRepresentation implements Representation {
                        configuration.exclusionFunction = TGRepresentationUtils.computeExclusionFunction(graph, resources, hints);
                }
                
-               ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(configuration));
-               return TransferableGraphs.create(graph, source);
-               
+               try (ModelTransferableGraphSource source = graph.syncRequest(new ModelTransferableGraphSourceRequest(configuration))) {
+                       return TransferableGraphs.create(graph, source);
+               } catch (IOException e) {
+                       throw new DatabaseException(e);
+               }
        }
        
        @SuppressWarnings("unchecked")
index 80dc3b9bbbbea42e31c1ee3fdc09f613e4753ec1..c286f02c7d4434e69fe31fc0978ef057e16764d8 100644 (file)
@@ -665,6 +665,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                 } catch (Throwable e) {
                     delayedWriteState.except(e);
                     total.finish();
+                    dwg.close();
                     return;
                 } finally {
 //                    newGraph.state.barrier.dec();
index 1b7376f96e4301814ba70ac861635ff058806cce..054db497d2cf7a46f9d8b425cf84fa01eebdd7a0 100644 (file)
@@ -524,7 +524,7 @@ public class RouteGraphUtils {
         }
     }
 
-    private static final ConnectionStyle DEFAULT_CONNECTION_STYLE = new ExampleConnectionStyle();
+    private static final ConnectionStyle DEFAULT_CONNECTION_STYLE = new BasicConnectionStyle(Color.BLACK, Color.BLACK, 3, ExampleConnectionStyle.SOLID, ExampleConnectionStyle.SOLID, 8);
 
     /**
      * @param graph
index 6672599073b1b18e717bd1f79c36f6e3ac0bdb78..75b0473a1bc4991be688799f7a23799a5136457e 100644 (file)
@@ -28,6 +28,7 @@ import org.simantics.db.common.utils.CommonDBUtils;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.common.utils.OrderedSetUtils;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.db.layer0.util.RemoverUtil;
 import org.simantics.db.request.Write;
 import org.simantics.diagram.content.ConnectionUtil;
@@ -863,6 +864,11 @@ public class Paster {
                 graph.claim(copy, L0.ConsistsOf, L0.PartOf, relationCopy);
                 graph.claim(copy, MOD.HasReferenceRelation, MOD.HasReferenceRelation_Inverse, relationCopy);
 
+                // #7348: renew reference relation GUID identifiers properly
+                Layer0Utils.renewIdentifier(graph, relationCopy);
+                for (Resource invRel : graph.getObjects(relationCopy, L0.ConsistsOf))
+                    Layer0Utils.renewIdentifier(graph, invRel);
+
                 return copy;
             }
 
index 576bc0b4b275fbbc5a80258ff1b375210ca85ed9..66ffa77de7def4253c8601babb7d978b4d2184bd 100644 (file)
@@ -12,9 +12,6 @@
 package org.simantics.layer0.utils.writer;
 
 
-import gnu.trove.map.hash.TIntIntHashMap;
-import gnu.trove.map.hash.TIntLongHashMap;
-
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.File;
@@ -31,6 +28,9 @@ import org.simantics.db.Resource;
 import org.simantics.db.WriteOnlyGraph;
 import org.simantics.db.exception.DatabaseException;
 
+import gnu.trove.map.hash.TIntIntHashMap;
+import gnu.trove.map.hash.TIntLongHashMap;
+
 public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
 
        protected File file;
@@ -45,7 +45,6 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                        System.out.println("Temp file: " + file.getAbsolutePath());
                        s = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file), 1024*1024));
 //                     s = new ObjectOutputStream(backup);
-                       
                        file.deleteOnExit();
                } catch (IOException e) {
                        throw new RuntimeException("Opening output stream to temporary file failed", e);
@@ -79,13 +78,13 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                assert(value != null);
                assert(dataType != null);
                try {
-                       ++internalCount;                
+                       ++internalCount;
                        timestamps.add(0);
                        
-                       s.writeByte(1);                 
-                       writeRef(internalCount);                        
+                       s.writeByte(1);
+                       writeRef(internalCount);
                        s.writeUnshared(value);
-                       writeRef(getId(dataType));                                      
+                       writeRef(getId(dataType));
                        
                        s.writeByte(0);
                        writeRef(current);
@@ -110,14 +109,14 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                assert(value != null);
                assert(dataType != null);
         try {
-            ++internalCount;        
+            ++internalCount;
             timestamps.add(0);
             
-            s.writeByte(1);         
-            writeRef(internalCount);            
+            s.writeByte(1);
+            writeRef(internalCount);
             s.writeUnshared(value);
-            writeRef(getId(dataType));                  
-    
+            writeRef(getId(dataType));
+
             current = internalCount;
         } catch (IOException e) {
             throw new RuntimeException("Writing statement failed.", e);
@@ -133,7 +132,7 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                clusterHints.put(current, clusterHint);
                return this;
        }
-           
+
     @Override
     public GraphWriter createInverse(int cluster, Resource r) {
        assert(r != null);
@@ -147,7 +146,7 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
         }
         return this;
     }    
-       
+
     @Override
     public GraphWriter createInverse(Resource r) {
        assert(r != null);
@@ -160,7 +159,7 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
             throw new RuntimeException("Writing statement failed.", e);
         }
         return this;
-    }    
+    }
 
     protected Resource getResource(WriteOnlyGraph wg, Resource[] internals, long[] resourceIds, int id) {
                if(id > 0) {
@@ -185,124 +184,122 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
        
        @Override
        public void commit(IProgressMonitor monitor, WriteOnlyGraph wg) throws DatabaseException {
-               
                try {
-                   if (s != null) {
-                       s.close();
-                       s = null;
-                   }
+                       if (s != null) {
+                               s.close();
+                               s = null;
+                       }
                        externalsInv = null;
-
-                       monitor.beginTask("", 100);
-
-                       int lastPercentageDone = 0;
-                       long fileLength = file.length();
-                       
-//                     System.out.println("size of commit file: " + fileLength);
-
-                       Resource[] internals = new Resource[internalCount];
-                       resourceIds = new long[internalCount];
-                       
-                       
+                       monitor.beginTask("Writing database", 100);
                        FileInputStream fis = new FileInputStream(file);
                        FileChannel fc = fis.getChannel();
-                       ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(fis, 1024*1024));
-            int resourceCounter = 0;
-                       int statementCounter = 0;
-            int valueCounter = 0;
-                       time = 0;
-                       loop: while(true) {
-                               switch(is.read()) {
-                               case -1:
-                                       break loop;
-                               case 0: {
-                                       int s = is.readInt();
-                                       int p = is.readInt();
-                                       int o = is.readInt();
-                                       Resource rs = getResource(wg, internals, resourceIds, s);
-                                       Resource rp = getResource(wg, internals, resourceIds, p);
-                                       Resource ro = getResource(wg, internals, resourceIds, o);
-                                       Resource rpInv = inverses.get(p);
-                                       wg.claim(rs, rp, rpInv, ro);
-                                       statementCounter += 2;
-                               } break;                                        
-                               case 1: {
-                                   int id = is.readInt();
-                                       Object value = is.readUnshared();
-                                       int type = is.readInt();
-                                       
-                                       Resource r = newResource(wg, internals, id);
-                                       wg.claim(r, l0.InstanceOf, null, getResource(wg, internals, resourceIds, type));
-                                       wg.claimValue(r, value);
-                    statementCounter ++;
-                    resourceCounter ++;
-                    valueCounter ++;
-                                       
-                               } break;
-                               case 2: {
-                                   wg.flushCluster();
-                } break; 
-                               case 3: {
-
-                    int s = is.readInt();
-                    int t = is.readInt();
-                                   
-                    Resource type = getResource(wg, internals, resourceIds, t);
-                    wg.claim(newResource(wg, internals, s), l0.InstanceOf, null, type);
-                    statementCounter ++;
-                    resourceCounter ++;
-                                   
-                               } break;
-                               case 4: {
-
-                    int s = is.readInt();
-                    newResource(wg, internals, s);
-                    resourceCounter ++;
-                    
-                               } break;
-                               case 5: { // InverseOf
-
-                    int r1 = is.readInt();
-                    int r2 = is.readInt();
-                    
-                    Resource rr1 = getResource(wg, internals, resourceIds, r1);
-                    Resource rr2 = getResource(wg, internals, resourceIds, r2);
-                    wg.claim(rr1, l0.InverseOf, l0.InverseOf, rr2);
-                    statementCounter += 2;
-                    
-                    inverses.put(r1, rr2);
-                    inverses.put(r2, rr1);
-                    
-                } break;
-                               }
-
-//                if((counter % 200000) == 0) {
-//                    System.out.println("Written " + counter + " statements.");
-//                }
-
-                double percentageDone = 100.0 * (double) fc.position() / (double) fileLength;
-                int newPercentageDone = (int) Math.round(percentageDone);
-                if(newPercentageDone > lastPercentageDone) {
-                    monitor.setTaskName("Writing database (" + newPercentageDone + "%)");
-                    monitor.worked(newPercentageDone - lastPercentageDone);
-                    lastPercentageDone = newPercentageDone;
-                }
+                       try (ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(fis, 1024*1024))) {
+                               commit(monitor, wg, is, fc);
                        }
-                       
-                       System.out.println("clusterIds.size() = " + clusterIds.size());
-                       
-                       System.out.println("Wrote " + resourceCounter + " resources, " + statementCounter + " statements and " + valueCounter + " values.");
-                       
                } catch (IOException e) {
-                       throw new RuntimeException("Commiting delayed graph writings failed.", e);
+                       throw new DatabaseException("Commiting delayed graph writings failed.", e);
                } catch (ClassNotFoundException e) {
-                       throw new RuntimeException("Commiting delayed graph writings failed.", e);
-               } finally {             
+                       throw new DatabaseException("Commiting delayed graph writings failed.", e);
+               } finally {
                        file.delete();
                        monitor.done();
                }
        }
-       
+
+       private void commit(IProgressMonitor monitor, WriteOnlyGraph wg, ObjectInputStream is, FileChannel fc) throws DatabaseException, IOException, ClassNotFoundException {
+               int lastPercentageDone = 0;
+               long fileLength = file.length();
+               //System.out.println("size of commit file: " + fileLength);
+
+               Resource[] internals = new Resource[internalCount];
+               resourceIds = new long[internalCount];
+
+               int resourceCounter = 0;
+               int statementCounter = 0;
+               int valueCounter = 0;
+               time = 0;
+               while(true) {
+                       switch(is.read()) {
+                       case -1:
+                               System.out.println("clusterIds.size() = " + clusterIds.size());
+                               System.out.println("Wrote " + resourceCounter + " resources, " + statementCounter + " statements and " + valueCounter + " values.");
+                               return;
+
+                       case 0: {
+                               int s = is.readInt();
+                               int p = is.readInt();
+                               int o = is.readInt();
+                               Resource rs = getResource(wg, internals, resourceIds, s);
+                               Resource rp = getResource(wg, internals, resourceIds, p);
+                               Resource ro = getResource(wg, internals, resourceIds, o);
+                               Resource rpInv = inverses.get(p);
+                               wg.claim(rs, rp, rpInv, ro);
+                               statementCounter += 2;
+                       } break;                                        
+                       case 1: {
+                               int id = is.readInt();
+                               Object value = is.readUnshared();
+                               int type = is.readInt();
+
+                               Resource r = newResource(wg, internals, id);
+                               wg.claim(r, l0.InstanceOf, null, getResource(wg, internals, resourceIds, type));
+                               wg.claimValue(r, value);
+                               statementCounter ++;
+                               resourceCounter ++;
+                               valueCounter ++;
+
+                       } break;
+                       case 2: {
+                               wg.flushCluster();
+                       } break; 
+                       case 3: {
+
+                               int s = is.readInt();
+                               int t = is.readInt();
+
+                               Resource type = getResource(wg, internals, resourceIds, t);
+                               wg.claim(newResource(wg, internals, s), l0.InstanceOf, null, type);
+                               statementCounter ++;
+                               resourceCounter ++;
+
+                       } break;
+                       case 4: {
+
+                               int s = is.readInt();
+                               newResource(wg, internals, s);
+                               resourceCounter ++;
+
+                       } break;
+                       case 5: { // InverseOf
+
+                               int r1 = is.readInt();
+                               int r2 = is.readInt();
+
+                               Resource rr1 = getResource(wg, internals, resourceIds, r1);
+                               Resource rr2 = getResource(wg, internals, resourceIds, r2);
+                               wg.claim(rr1, l0.InverseOf, l0.InverseOf, rr2);
+                               statementCounter += 2;
+
+                               inverses.put(r1, rr2);
+                               inverses.put(r2, rr1);
+
+                       } break;
+                       }
+
+//                     if((counter % 200000) == 0) {
+//                             System.out.println("Written " + counter + " statements.");
+//                     }
+
+                       double percentageDone = 100.0 * (double) fc.position() / (double) fileLength;
+                       int newPercentageDone = (int) Math.round(percentageDone);
+                       if(newPercentageDone > lastPercentageDone) {
+                               monitor.setTaskName("Writing database (" + newPercentageDone + "%)");
+                               monitor.worked(newPercentageDone - lastPercentageDone);
+                               lastPercentageDone = newPercentageDone;
+                       }
+               }
+       }
+
        private Resource newResource(WriteOnlyGraph wg, Resource[] internals, int s) throws DatabaseException {
                int clusterHint = clusterHints.get(s);
                
@@ -323,42 +320,6 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                resourceIds[s-1] = r.getResourceId();
                return r;
        }
-       
-//    public ValueDescriptor createDescriptor(Object obj) {
-//        
-//        if(obj instanceof String[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (String[])obj);
-//        else if(obj instanceof int[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (int[])obj);
-//        else if(obj instanceof double[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (double[])obj);
-//        else if(obj instanceof float[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (float[])obj);
-//        else if(obj instanceof boolean[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (boolean[])obj);
-//        else if(obj instanceof long[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (long[])obj);
-//        else if(obj instanceof byte[])
-//            return new ValueDescriptor(ValueTrait.StaticValue, (byte[])obj);
-//        
-//        else if(obj instanceof String)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new String[] {(String)obj});
-//        else if(obj instanceof Double)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new double[] {(Double)obj});
-//        else if(obj instanceof Float)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new float[] {(Float)obj});
-//        else if(obj instanceof Integer)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new int[] {(Integer)obj});
-//        else if(obj instanceof Boolean)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new boolean[] {(Boolean)obj});
-//        else if(obj instanceof Byte)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new byte[] {(Byte)obj});
-//        else if(obj instanceof Long)
-//            return new ValueDescriptor(ValueTrait.StaticValue, new long[] {(Long)obj});
-//        
-//        throw new Error("Wrong type!");
-//        
-//    }
 
     @Override
     public GraphWriter create() {
@@ -407,8 +368,7 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
        
        @Override
     public GraphWriter create(int clusterHint, Resource type) {
-               
-               create(type);           
+               create(type);
        clusterHints.put(current, clusterHint);
         return this;
         
@@ -432,7 +392,7 @@ public class DelayedGraphWriter extends AbstractDelayedGraphWriter {
                return this;
        }
 
-       public GraphWriter flush() {       
+       public GraphWriter flush() {
         try {
             s.writeByte(2);
         } catch(IOException e) {
index 753a90292926f6221d002ba187ce51a3bfcd82d7..3054fcaa531c45fd3285719333062fb4d9a14041 100644 (file)
@@ -400,9 +400,7 @@ public class ModelingUtils {
 
                Resource project = SimanticsUI.getProject().get();
 
-               try {
-
-                       StreamingTransferableGraphFileReader importer = new StreamingTransferableGraphFileReader(new File(fileName));
+               try (StreamingTransferableGraphFileReader importer = new StreamingTransferableGraphFileReader(new File(fileName))) {
                        TransferableGraphSource tg = importer.readTG();
 
                        final DefaultPasteImportAdvisor advisor = new DefaultPasteImportAdvisor(project) {
@@ -2260,7 +2258,7 @@ public class ModelingUtils {
                Layer0 L0 = Layer0.getInstance(graph);
                while(!todo.isEmpty()) {
                        Resource resource = todo.remove(todo.size()-1);
-                       Layer0Utils.addL0Identifier(graph, resource);
+                       Layer0Utils.claimNewIdentifier(graph, resource, false);
             if(deep)
                todo.addAll(graph.getObjects(resource, L0.ConsistsOf));
                }
@@ -2291,7 +2289,7 @@ public class ModelingUtils {
                                
                                GUID existing = graph.getPossibleRelatedValue(r, L0.identifier, GUID.BINDING);
                                if(existing == null) {
-                                   Layer0Utils.addL0Identifier(graph, r);
+                                   Layer0Utils.claimNewIdentifier(graph, r, true);
                                        madeChanges = true;
                                }
                                
index 5dde0b081677a9e41dac64ff7ea8c7934d789408..6345a132985c875bdf5b02cf5b2bc73e6d06f9a3 100644 (file)
@@ -9,11 +9,16 @@ import java.awt.geom.Rectangle2D;
 import java.io.ByteArrayOutputStream;
 import java.io.OutputStreamWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Map;
+import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
+import java.util.stream.Collectors;
 
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Transformer;
@@ -24,11 +29,17 @@ import javax.xml.transform.stream.StreamResult;
 import org.apache.batik.dom.GenericDOMImplementation;
 import org.apache.batik.svggen.SVGGeneratorContext;
 import org.apache.batik.svggen.SVGGraphics2D;
+import org.simantics.Simantics;
+import org.simantics.datatypes.literal.GUID;
+import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
+import org.simantics.db.common.request.UnaryRead;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
 import org.simantics.diagram.elements.DiagramNodeUtil;
 import org.simantics.diagram.elements.TextGridNode;
 import org.simantics.diagram.elements.TextNode;
+import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.diagram.DiagramHints;
 import org.simantics.g2d.diagram.IDiagram;
@@ -37,6 +48,7 @@ import org.simantics.g2d.diagram.participant.Selection;
 import org.simantics.g2d.element.IElement;
 import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
 import org.simantics.g2d.utils.CanvasUtils;
+import org.simantics.layer0.Layer0;
 import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.ParentNode;
 import org.simantics.scenegraph.g2d.G2DParentNode;
@@ -57,6 +69,7 @@ import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
 import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
 import org.simantics.scenegraph.g2d.nodes.spatial.RTreeNode;
 import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.scl.runtime.function.Function1;
 import org.simantics.trend.impl.ItemNode;
 import org.simantics.utils.threads.ThreadUtils;
 import org.slf4j.Logger;
@@ -435,7 +448,95 @@ public class SCLScenegraph {
 
        }
 
-       public static String renderSVG(ICanvasContext ctx) {
+       public static String renderSVG3(ICanvasContext ctx) {
+        return renderSVG0(ctx, p0 -> p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2)));
+       }
+
+    /**
+     * @param graph
+     * @param component
+     * @throws DatabaseException
+     */
+    private static Object[] createURIBasedL0Identifier(ReadGraph graph, Resource component) throws DatabaseException {
+        String uri = graph.getPossibleURI(component);
+        int hashCode = uri.hashCode();
+        Random random = new Random(hashCode);
+        long l1 = random.nextLong();
+        long l2 = random.nextLong();
+        return new Object[] { l1, l2 };
+    }
+
+    /**
+     * Default no-op mapper
+     */
+    private static final Function1<Set<?>, Map<?, ?>> mapper = p0 -> p0.stream().collect(Collectors.toMap(p1 -> p1, p2 -> p2));
+    
+    public static String renderSVG(ICanvasContext ctx) {
+        return renderSVG0(ctx, mapper);
+    }
+
+    /**
+     * Renders ICanvasContext into SVG by mapping the SVG id's into URI based
+     * GUID's
+     * 
+     * @param ctx
+     * @return
+     */
+    public static String renderSVGMapIdentifiers(ICanvasContext ctx) {
+        return renderSVG0(ctx, new Function1<Set<?>, Map<?, ?>>() {
+
+            @Override
+            public Map<?, ?> apply(Set<?> p0) {
+                try {
+                    return Simantics.getSession().syncRequest(new UnaryRead<Set<?>, Map<?, ?>>(p0) {
+
+                        @Override
+                        public Map<?, ?> perform(ReadGraph graph) throws DatabaseException {
+                            ModelingResources MOD = ModelingResources.getInstance(graph);
+                            DiagramResource DIA = DiagramResource.getInstance(graph);
+                            Layer0 L0 = Layer0.getInstance(graph);
+                            return parameter.stream().collect(Collectors.toMap(p -> p, p -> {
+                                try {
+                                    if (p instanceof Resource) {
+                                        Resource element = (Resource) p;
+                                        if (graph.isInstanceOf(element, DIA.Element)) {
+                                            Resource component = graph.getPossibleObject(element, MOD.ElementToComponent);
+                                            if (component != null) {
+                                                GUID identifier = graph.getPossibleRelatedValue(component, L0.identifier, GUID.BINDING);
+                                                if (identifier != null) {
+                                                    return Arrays.toString(createURIBasedL0Identifier(graph, component));
+                                                } else {
+                                                    LOGGER.error("Component {} does not have GUID identifier!", component);
+                                                }
+                                            } else if (graph.isInstanceOf(element, DIA.Connection) || graph.isInstanceOf(element, DIA.Terminal)) {
+                                                // Ok, lets create a hashcode for connections and terminals as they do not have identifiers 
+                                                return graph.getURI(element).hashCode();
+                                            } else {
+                                                // Ok, lets create a hashcode or either return empty string in cases where no ID is required
+                                                if (graph.hasStatement(element, L0.HasName))
+                                                    return graph.getURI(element).hashCode();
+                                                return "";
+                                            }
+                                        }
+                                    } else {
+                                        LOGGER.error("Parameter p {} is not resource but it is {}", p, p.getClass());
+                                    }
+                                    return p;
+                                } catch (DatabaseException e) {
+                                    throw new RuntimeDatabaseException(e);
+                                }
+                            }));
+                        }
+                    });
+                } catch (DatabaseException e) {
+                    LOGGER.error("Could not apply mappings", e);
+                    throw new RuntimeDatabaseException(e);
+                }
+            }
+        });
+       }
+       
+       private static String renderSVG0(ICanvasContext ctx, Function1<Set<?>, Map<?, ?>> mappingFunction) {
 
                // Get a DOMImplementation.
                DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
@@ -495,166 +596,14 @@ public class SCLScenegraph {
 
                        result.append("<svg width=\"100%\" height=\"100%\" stroke=\"black\"><g transform=\"translate(").append(trX).append(' ').append(trY).append(")\">");
 
-                       IG2DNodeVisitor visitor = new IG2DNodeVisitor() {
-
-                               int indent = 0;
-
-                               HashMap<SingleElementNode,StringBuilder> senBuilders = new HashMap<>();
-
-                               @Override
-                               public void enter(IG2DNode node) {
-                                       
-                                       StringBuilder parentBuilder = getParentBuilder(node);
-                                       
-                                       indent++;
-                                       if(node instanceof ConnectionNode) {
-                                               
-                                               for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
-                                                       n.setIgnoreSelection(true);
-                                               }
-                                               
-                                               String key = ((ConnectionNode)node).getKey().toString();
-                                               
-                                               parentBuilder.append("\n<g class=\"connection\" id=\"" + key + "\">");
-                                               Element doc = renderSVGNode((IG2DNode)node);
-                                               String svg = printSVGDocument(doc);
-                                               parentBuilder.append(svg);
-
-                                               for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
-                                                       n.setIgnoreSelection(false);
-                                               }
-
-                                               parentBuilder.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
-                                               doc = renderSVGNode((IG2DNode)node);
-                                               svg = printSVGDocument(doc);
-                                               parentBuilder.append(svg);
-                                               parentBuilder.append("\n</g>");
-
-                                               BasicStroke bs = new BasicStroke(5f);
-                                               
-                                               for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
-                                                       n.setDynamicStroke(bs);
-                                               }
-
-                                               parentBuilder.append("\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
-                                               doc = renderSVGNode((IG2DNode)node);
-                                               svg = printSVGDocument(doc);
-                                               parentBuilder.append(svg);
-                                               parentBuilder.append("\n</g>");
-
-                                               parentBuilder.append("\n</g>");
-                                               
-                                       } else if (node instanceof SelectionNode) {
-                                               
-                                               SelectionNode n = (SelectionNode)node;
-                                               SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
-                                               if(parentSEN != null && parentSEN.getKey() != null) {
-                                                       
-                                                       StringBuilder parentBuilder2 = getParentBuilder(parentSEN);
-                                                       
-                                                       String key = parentSEN.getKey().toString();
-                                                       Element doc = renderSVGNode((IG2DNode)node);
-                                                       String svg = printSVGDocument(doc);
-                                                       parentBuilder2.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
-                                                       parentBuilder2.append(svg);
-                                                       parentBuilder2.append("\n</g>");
-                                                       parentBuilder2.append("\n<g class=\"selectionMask\" id=\"" + key + "\">");
-                                                       Rectangle2D rect = n.getRect();
-                                                       parentBuilder2.append("<rect style=\"fill:#fff\" opacity=\"0.001\"");
-                                                       parentBuilder2.append(" x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
-                                                       parentBuilder2.append(" width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
-                                                       parentBuilder2.append("></rect>");
-                                                       parentBuilder2.append("\n</g>");
-                                               }
-                                       } else if (node instanceof SVGNode) {
-                                               SVGNode svg = (SVGNode)node;
-                                               parentBuilder.append(svg.getSVGText());
-                                       } else if (node instanceof G2DParentNode) {
-                                               AffineTransform at = node.getTransform();
-                                               if(node instanceof SingleElementNode) {
-                                                       SingleElementNode sen = (SingleElementNode)node;
-                                                       if(sen.getKey() != null) {
-                                                               String key = sen.getKey().toString();
-                                                               parentBuilder.append("\n<g class=\"definedElement\" id=\"" + key + "\">");
-                                                       }
-                                                       senBuilders.put(sen, new StringBuilder());
-                                               }
-                                               if(!at.isIdentity()) {
-                                                       if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
-                                                               String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
-                                                               parentBuilder.append("\n<g transform=\"" + m + "\">");
-                                                       } else {
-                                                               double[] ds = new double[6];
-                                                               at.getMatrix(ds);
-                                                               String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
-                                                               parentBuilder.append("\n<g transform=\"" + m + "\">");
-                                                       }
-                                               }
-                                       }
-
-                                       //enters.put(node, b.length());
-
-                               }
-                               
-                               private StringBuilder getParentBuilder(IG2DNode node) {
-                                       
-                                       INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
-                                       if(parentSEN instanceof G2DSceneGraph) return result;
-
-                                       StringBuilder parentBuilder = senBuilders.get(parentSEN);
-                                       if(parentBuilder == null) return result;
-                                       
-                                       return parentBuilder;
-                                       
-                               }
-
-                               @Override
-                               public void leave(IG2DNode node) {
-
-                                       if(node instanceof ConnectionNode || node instanceof SVGNode) {
-                                               // We are done
-                                       } else if (node instanceof G2DParentNode) {
-                                               
-                                               StringBuilder parentBuilder = getParentBuilder(node);
-                                               
-                                               if(node instanceof SingleElementNode) {
-                                                       SingleElementNode sen = (SingleElementNode)node;
-//                                                     if(sen.getKey() != null) {
-                                                               StringBuilder b = senBuilders.get(sen);
-                                                               String content = b.toString();
-                                                               if(content.isEmpty()) {
-                                                                       if(sen.getKey() != null) {
-                                                                               
-                                                                               for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
-                                                                                       n.setIgnore(true);
-                                                                               }
-
-                                                                               Element doc = renderSVGNode((IG2DNode)node);
-                                                                               String svg = printSVGDocument(doc);
-                                                                               parentBuilder.append(svg);
-                                                                       }
-                                                               } else {
-                                                                       parentBuilder.append(content);
-                                                               }
-//                                                     }
-                                               }
-
-                                               
-                                               AffineTransform at = node.getTransform();
-                                               if(!at.isIdentity()) {
-                                                       parentBuilder.append("</g>");
-                                               }
-                                               if(node instanceof SingleElementNode) {
-                                                       SingleElementNode sen = (SingleElementNode)node;
-                                                       if(sen.getKey() != null) {
-                                                               parentBuilder.append("</g>");
-                                                       }
-                                               }
-                                       }
-                                       indent --;
-                               }
+                       KeyVisitor keyVisitor = new KeyVisitor();
+                       sg.accept(keyVisitor);
+                       
+                       Set<Object> keys = keyVisitor.getKeys();
+                       
+                       Map<?, ?> mappings = mappingFunction.apply(keys);
 
-                       };
+                       IG2DNodeVisitor visitor = new PrintingVisitor(result, mappings);
                        sg.accept(visitor);
 
                } catch (Throwable t) {
@@ -665,8 +614,208 @@ public class SCLScenegraph {
                //System.err.println(" == FINAL RESULT == ");
                //System.err.println(b);
                return result.toString();
+       }
+       
+       
+       
+       private static class KeyVisitor implements IG2DNodeVisitor {
+
+        private Set<Object> keys = new HashSet<>();
 
+        @Override
+        public void enter(IG2DNode node) {
+            if (node instanceof SingleElementNode) {
+                Object key = ((SingleElementNode) node).getKey();
+                if (key != null) {
+                    keys.add(key);
+                }
+            }
+        }
+
+        @Override
+        public void leave(IG2DNode node) {
+            // Nothing to do
+        }
+
+        public Set<Object> getKeys() {
+            return keys;
+        }
        }
 
+       private static class PrintingVisitor implements IG2DNodeVisitor {
+
+        int indent = 0;
+
+        HashMap<SingleElementNode,StringBuilder> senBuilders = new HashMap<>();
+
+        private StringBuilder result;
+
+        private Map<?, ?> mappings;
+
+        public PrintingVisitor(StringBuilder result, Map<?, ?> mappings) {
+            this.result = result;
+            this.mappings = mappings;
+        }
+
+        private String getKey(SingleElementNode node) {
+            String key;
+            if (mappings.containsKey(node.getKey()))
+                key = mappings.get(node.getKey()).toString();
+            else
+                key = node.getKey().toString();
+            return key;
+        }
+
+        @Override
+        public void enter(IG2DNode node) {
+            
+            StringBuilder parentBuilder = getParentBuilder(node);
+            
+            indent++;
+            if(node instanceof ConnectionNode) {
+                
+                for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+                    n.setIgnoreSelection(true);
+                }
+
+                String key = getKey((ConnectionNode) node);
+                parentBuilder.append("\n<g class=\"connection\" id=\"" + key + "\">");
+                Element doc = renderSVGNode((IG2DNode)node);
+                String svg = printSVGDocument(doc);
+                parentBuilder.append(svg);
+
+                for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+                    n.setIgnoreSelection(false);
+                }
+
+                parentBuilder.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+                doc = renderSVGNode((IG2DNode)node);
+                svg = printSVGDocument(doc);
+                parentBuilder.append(svg);
+                parentBuilder.append("\n</g>");
+
+                BasicStroke bs = new BasicStroke(5f);
+                
+                for(RouteGraphNode n : NodeUtil.collectNodes(node, RouteGraphNode.class)) {
+                    n.setDynamicStroke(bs);
+                }
+
+                parentBuilder.append("\n<g class=\"selectionMask\" opacity=\"0.001\" id=\"" + key + "\">");
+                doc = renderSVGNode((IG2DNode)node);
+                svg = printSVGDocument(doc);
+                parentBuilder.append(svg);
+                parentBuilder.append("\n</g>");
+
+                parentBuilder.append("\n</g>");
+                
+            } else if (node instanceof SelectionNode) {
+                
+                SelectionNode n = (SelectionNode)node;
+                SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+                if(parentSEN != null && parentSEN.getKey() != null) {
+                    
+                    StringBuilder parentBuilder2 = getParentBuilder(parentSEN);
+                    
+                    String key = getKey(parentSEN);
+                    Element doc = renderSVGNode((IG2DNode)node);
+                    String svg = printSVGDocument(doc);
+                    parentBuilder2.append("\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+                    parentBuilder2.append(svg);
+                    parentBuilder2.append("\n</g>");
+                    parentBuilder2.append("\n<g class=\"selectionMask\" id=\"" + key + "\">");
+                    Rectangle2D rect = n.getRect();
+                    parentBuilder2.append("<rect style=\"fill:#fff\" opacity=\"0.001\"");
+                    parentBuilder2.append(" x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
+                    parentBuilder2.append(" width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
+                    parentBuilder2.append("></rect>");
+                    parentBuilder2.append("\n</g>");
+                }
+            } else if (node instanceof SVGNode) {
+                SVGNode svg = (SVGNode)node;
+                parentBuilder.append(svg.getSVGText());
+            } else if (node instanceof G2DParentNode) {
+                AffineTransform at = node.getTransform();
+                if(node instanceof SingleElementNode) {
+                    SingleElementNode sen = (SingleElementNode)node;
+                    if(sen.getKey() != null) {
+                        String key = getKey(sen);
+                        parentBuilder.append("\n<g class=\"definedElement\" id=\"" + key + "\">");
+                    }
+                    senBuilders.put(sen, new StringBuilder());
+                }
+                if(!at.isIdentity()) {
+                    if(at.getScaleX() == 1.0 && at.getScaleY() == 1.0 && at.getShearX() == 0.0 && at.getShearY() == 0.0) {
+                        String m = "translate(" + at.getTranslateX() + " " + at.getTranslateY() + ")";
+                        parentBuilder.append("\n<g transform=\"" + m + "\">");
+                    } else {
+                        double[] ds = new double[6];
+                        at.getMatrix(ds);
+                        String m = "matrix(" + ds[0] + " " + ds[1] + " " + ds[2] + " " + ds[3] + " " + ds[4] + " " + ds[5] + ")";
+                        parentBuilder.append("\n<g transform=\"" + m + "\">");
+                    }
+                }
+            }
+
+            //enters.put(node, b.length());
+
+        }
+        
+        private StringBuilder getParentBuilder(IG2DNode node) {
+            
+            INode parentSEN = NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+            if(parentSEN instanceof G2DSceneGraph) return result;
+
+            StringBuilder parentBuilder = senBuilders.get(parentSEN);
+            if(parentBuilder == null) return result;
+            
+            return parentBuilder;
+            
+        }
 
+        @Override
+        public void leave(IG2DNode node) {
+
+            if(node instanceof ConnectionNode || node instanceof SVGNode) {
+                // We are done
+            } else if (node instanceof G2DParentNode) {
+                
+                StringBuilder parentBuilder = getParentBuilder(node);
+                
+                if(node instanceof SingleElementNode) {
+                    SingleElementNode sen = (SingleElementNode)node;
+//                  if(sen.getKey() != null) {
+                        StringBuilder b = senBuilders.get(sen);
+                        String content = b.toString();
+                        if(content.isEmpty()) {
+                            if(sen.getKey() != null) {
+                                
+                                for(SelectionNode n : NodeUtil.collectNodes(node, SelectionNode.class)) {
+                                    n.setIgnore(true);
+                                }
+
+                                Element doc = renderSVGNode((IG2DNode)node);
+                                String svg = printSVGDocument(doc);
+                                parentBuilder.append(svg);
+                            }
+                        } else {
+                            parentBuilder.append(content);
+                        }
+//                  }
+                }
+
+                
+                AffineTransform at = node.getTransform();
+                if(!at.isIdentity()) {
+                    parentBuilder.append("</g>");
+                }
+                if(node instanceof SingleElementNode) {
+                    SingleElementNode sen = (SingleElementNode)node;
+                    if(sen.getKey() != null) {
+                        parentBuilder.append("</g>");
+                    }
+                }
+            }
+            indent --;
+        }
+       }
 }
\ No newline at end of file
index ae65e87f88476bf6b2059e8899d5a63266816fee..6167334fdd79815ad98a60cb1db1762d611a116f 100644 (file)
@@ -22,6 +22,7 @@ import org.simantics.db.Resource;
 import org.simantics.db.common.request.ObjectsWithType;
 import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.function.DbConsumer;
 import org.simantics.db.layer0.adapter.SubgraphExtent.ExtentStatus;
 import org.simantics.db.layer0.adapter.impl.DefaultCopyHandler;
 import org.simantics.db.layer0.util.TransferableGraphConfiguration2;
@@ -64,39 +65,63 @@ public class CompositeCopyHandler extends DefaultCopyHandler {
         if(indexRoot == null) throw new DatabaseException("Composite is not part of any index root");
         String indexRootUri = graph.getURI(indexRoot);
 
+        DbConsumer<Resource> identifierExcluder = r -> {
+            if (r != null)
+                exclusions.addAll(graph.getObjects(r, L0.identifier));
+        };
+
         for(Resource resource : resources) {
             // Process all connection joins.
             // This is the only way to access all of them.
             for (Resource diagram : graph.getObjects(resource, MOD.CompositeToDiagram)) {
-                for (Resource flag : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Flag))) {
-                    for (Resource join : graph.getObjects(flag, DIA.FlagIsJoinedBy)) {
-                        // Joins with external references are omitted
-                        for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
-                            if (!resourceSet.contains(comp))
-                                exclusions.add(join);
-                        }
-                        // This code excludes joins with flags to external
-                        // diagrams that are not connected (have no
-                        // configuration for the flag)
-                        for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
-                            Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
-                            if (diagram2 != null) {
-                                Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
+                identifierExcluder.accept(diagram);
+
+                for (Resource element : graph.getObjects(diagram, L0.ConsistsOf)) {
+                    identifierExcluder.accept(element);
+
+                    Set<Resource> types = graph.getTypes(element);
+
+                    // Check all diagram flag elements for necessary exclusions.
+                    if (types.contains(DIA.Flag)) {
+                        for (Resource join : graph.getObjects(element, DIA.FlagIsJoinedBy)) {
+                            // Joins with external references are omitted
+                            for (Resource comp : graph.getObjects(join, SR.JoinsComposite)) {
                                 if (!resourceSet.contains(comp))
-                                    exclusions.add(join); 
+                                    exclusions.add(join);
+                            }
+                            // This code excludes joins with flags to external
+                            // diagrams that are not connected (have no
+                            // configuration for the flag)
+                            for (Resource flag2 : graph.getObjects(join, DIA.JoinsFlag)) {
+                                Resource diagram2 = graph.getPossibleObject(flag2, L0.PartOf);
+                                if (diagram2 != null) {
+                                    Resource comp = graph.getPossibleObject(diagram2, MOD.DiagramToComposite);
+                                    if (!resourceSet.contains(comp))
+                                        exclusions.add(join); 
+                                }
+                            }
+                        }
+                    }
+
+                    // Check all diagram monitor elements.
+                    // Any components referenced that are external to the exported diagrams must be excluded from the export.
+                    // This will leave the monitors without a monitored component but export and import will work anyway.
+                    if (types.contains(DIA.Monitor)) {
+                        for (Resource monitoredComponent : graph.getObjects(element, DIA.HasMonitorComponent)) {
+                            Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
+                            if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
+                                exclusions.add(monitoredComponent);
                             }
                         }
                     }
-                }
 
-                // Check all diagram monitor elements.
-                // Any components referenced that are external to the exported diagrams must be excluded from the export.
-                // This will leave the monitors without a monitored component but export and import will work anyway.
-                for (Resource ref : graph.syncRequest(new ObjectsWithType(diagram, L0.ConsistsOf, DIA.Monitor))) {
-                    for (Resource monitoredComponent : graph.getObjects(ref, DIA.HasMonitorComponent)) {
-                        Resource monitoredComponentComposite = graph.getPossibleObject(monitoredComponent, L0.PartOf);
-                        if (monitoredComponentComposite != null && !resourceSet.contains(monitoredComponentComposite)) {
-                            exclusions.add(monitoredComponent);
+                    // Check all diagram reference elements for necessary exclusions.
+                    if (types.contains(MOD.ReferenceElement)) {
+                        for (Resource rel : graph.getObjects(element, L0.ConsistsOf)) {
+                            identifierExcluder.accept(rel);
+                            for (Resource invRel : graph.getObjects(rel, L0.ConsistsOf)) {
+                                identifierExcluder.accept(invRel);
+                            }
                         }
                     }
                 }
@@ -119,13 +144,11 @@ public class CompositeCopyHandler extends DefaultCopyHandler {
             // Include resource as root
             CompositeInfo info = CompositeInfo.fromResource(graph, resource);
             roots.add(new RootSpec(resource, info.getTGName(), true, typeId(graph, L0, indexRootUri, resource)));
-               Resource id = graph.getPossibleObject(resource, L0.identifier);
-               if(id != null) exclusions.add(id);
+            identifierExcluder.accept(resource);
             // Include components as roots
-            for(Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
-               DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
-               id = graph.getPossibleObject(child, L0.identifier);
-               if(id != null) exclusions.add(id);
+            for (Resource child : graph.sync(new ObjectsWithType(resource, L0.ConsistsOf, SR.Component))) {
+                DiagramComponentInfo cinfo = DiagramComponentInfo.fromResource(graph, info, child);
+                identifierExcluder.accept(child);
                 roots.add(new RootSpec(child, cinfo.getTGName(info), true, typeId(graph, L0, indexRootUri, child)));
             }
         }
index 96aa3f134b7dff7e0aef854b24546f216618622f..6b4e59d176860bdeb53387818a00a8d1d696e6db 100644 (file)
@@ -17,7 +17,6 @@ import java.util.Map;
 
 import org.simantics.Simantics;
 import org.simantics.databoard.Bindings;
-import org.simantics.datatypes.literal.GUID;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.exception.DatabaseException;
@@ -74,7 +73,7 @@ public class ComponentCopyAdvisor extends GraphCopyAdvisor {
         if (graph.hasStatement(sourceContainer, L0.ConsistsOf, source))
             graph.claim(targetContainer, L0.ConsistsOf, copy);
 
-        Layer0Utils.addL0Identifier(graph, copy);
+        Layer0Utils.claimNewIdentifier(graph, copy, false);
         if (context.get(SynchronizationHints.NO_RENAME) == null)
             renameComponent(context, graph, source, copy, sourceContainer, targetContainer);
         return copy;
index 994aa1ab13feb132f6a9ce5ebaa5270c01bf6582..d666d63d5f24b9ba33b47a0fef6d363831dcecc3 100644 (file)
@@ -23,6 +23,7 @@ import org.simantics.db.common.utils.OrderedSetUtils;
 import org.simantics.db.exception.CancelTransactionException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.request.PossibleModel;
+import org.simantics.db.layer0.util.Layer0Utils;
 import org.simantics.diagram.stubs.DiagramResource;
 import org.simantics.diagram.stubs.G2DResource;
 import org.simantics.diagram.synchronization.ISynchronizationContext;
@@ -89,6 +90,8 @@ public class ElementCopyAdvisor extends GraphCopyAdvisor {
         if (graph.hasStatement(sourceContainer, L0.ConsistsOf, source))
             graph.claim(targetContainer, L0.ConsistsOf, copy);
 
+        Layer0Utils.claimNewIdentifier(graph, copy, false);
+
         return copy;
     }
 
index 3330587b934f5e9c233b997e6b96745aff8e9168..0796e6879622b15d05a12e50bfe1271d4061774a 100644 (file)
@@ -14,7 +14,6 @@ package org.simantics.modeling.mapping;
 import gnu.trove.map.hash.TIntIntHashMap;
 import gnu.trove.set.hash.TIntHashSet;
 
-import org.simantics.datatypes.literal.GUID;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.utils.CommonDBUtils;
@@ -55,7 +54,7 @@ public class NamingCreationInstruction extends CreationInstruction {
             Resource result = GraphUtils.create(g,
                     b.HasName, proposition
             );
-            Layer0Utils.addL0Identifier(g, result);
+            Layer0Utils.claimNewIdentifier(g, result, true);
             return result;
         } catch (NamingException e1) {
             throw new DatabaseException(e1);
index 905305bc3087f657ec6e70739eafdcf8eb4867cb..dd547ffe382bf7bc1dd47c8f31bd3df2c62f6d4e 100644 (file)
@@ -2,7 +2,6 @@ package org.simantics.modeling.utils;
 
 import java.util.Collection;
 
-import org.simantics.datatypes.literal.GUID;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.CommentMetadata;
@@ -113,7 +112,7 @@ public class OntologicalRequirementEnforceRequest extends WriteRequest {
                for (Resource r : ids) {
                        if (!graph.hasStatement(r, L0.identifier)) {
                                CommonDBUtils.selectClusterSet(graph, r);
-                               Layer0Utils.addL0Identifier(graph, r);
+                               Layer0Utils.claimNewIdentifier(graph, r, true);
                        }
                }
 
index 14bcbcaf65e84e645e99948b02c80a508033ef83..9089ebb817209e1735ebcaf3dcfd7e39d65585b9 100644 (file)
@@ -373,4 +373,11 @@ public class SCLConstant extends DelegateConstant implements Named {
         if(inlineArity < Integer.MAX_VALUE)
             inlinableDefinition = (SSAFunction)definition.copy();
     }
+
+    public void cleanup() {
+        if(definition != null)
+            definition.cleanup();
+        if(inlinableDefinition != null)
+            inlinableDefinition.cleanup();
+    }
 }
index 7b4a5bc26b1c7afb59addb97fa91d93985d7cc39..f44609e6c1b13552b9311025f2872c740a10978c 100644 (file)
@@ -47,6 +47,10 @@ public class CHRLiteral extends Symbol {
     }
 
     public void resolve(TranslationContext context) {
+        if(parameters != null) {
+            for(int i=0;i<parameters.length;++i)
+                parameters[i] = parameters[i].resolve(context);
+        }
         if(relation instanceof UnresolvedCHRRelation) {
             UnresolvedCHRRelation unresolved = (UnresolvedCHRRelation)relation;
             CHRConstraint constraint = context.resolveCHRConstraint(unresolved.name);
@@ -59,6 +63,10 @@ public class CHRLiteral extends Symbol {
                 if(sclRelation != null)
                     relation = new ExternalCHRRelation(sclRelation);
                 else {
+                    if(unresolved.name.contains(".")) {
+                        context.getErrorLog().log(unresolved.location, "Couldn't resolve relation " + unresolved.name + ".");
+                        return;
+                    }   
                     if(parameters == null) {
                         context.getErrorLog().log(location, "Relation must be declared if record syntax is used.");
                         return;
@@ -98,10 +106,6 @@ public class CHRLiteral extends Symbol {
             }
             fields = null;
         }
-        else {
-            for(int i=0;i<parameters.length;++i)
-                parameters[i] = parameters[i].resolve(context);
-        }
     }
 
     public void collectRefs(TObjectIntHashMap<Object> allRefs, TIntHashSet refs) {
index ac61eb4866844c1822abf0c7323f958df6b9cbaa..1bd0d22c4ec4b7f4a075f0375da97a53075714c0 100644 (file)
@@ -9,6 +9,7 @@ import org.simantics.scl.compiler.elaboration.equation.Equation;
 import org.simantics.scl.compiler.elaboration.equation.EquationVisitor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.ExpressionAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
@@ -517,4 +518,12 @@ EquationVisitor {
         equation.guard =  equation.guard.accept(this);
     }
 
+    @Override
+    public void visit(CHRStatement statement) {
+        for(int i=0;i<statement.body.length;++i)
+            statement.body[i] = statement.body[i].accept(this);
+        for(int i=0;i<statement.head.length;++i)
+            statement.head[i] = statement.head[i].accept(this);
+    }
+
 }
index be9be3109c75fe29a08fe119f88529a8788519aa..b7ce06d92fc4ea01e3f9660ba8465514b26afda1 100644 (file)
@@ -13,6 +13,7 @@ import org.simantics.scl.compiler.elaboration.expressions.accessor.FieldAccessor
 import org.simantics.scl.compiler.elaboration.expressions.accessor.IdAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.accessor.StringAccessor;
 import org.simantics.scl.compiler.elaboration.expressions.block.BindStatement;
+import org.simantics.scl.compiler.elaboration.expressions.block.CHRStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.GuardStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.IncludeStatement;
 import org.simantics.scl.compiler.elaboration.expressions.block.LetStatement;
@@ -22,6 +23,7 @@ import org.simantics.scl.compiler.elaboration.expressions.block.StatementVisitor
 import org.simantics.scl.compiler.elaboration.expressions.list.ListAssignment;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGenerator;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListGuard;
+import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifier;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListQualifierVisitor;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListSeq;
 import org.simantics.scl.compiler.elaboration.expressions.list.ListThen;
@@ -443,4 +445,12 @@ EquationVisitor, StatementVisitor {
     public void visit(IncludeStatement statement) {
         statement.value.accept(this);
     }
+    
+    @Override
+    public void visit(CHRStatement statement) {
+        for(ListQualifier q : statement.body)
+            q.accept(this);
+        for(ListQualifier q : statement.head)
+            q.accept(this);
+    }
 }
index a0efc8862b4b96e003730f3fbf06b37ff8edae59..d58f9c360e79c072eeb2723b8216466913a4c8b5 100644 (file)
@@ -44,7 +44,7 @@ public class CHRStatement extends Statement {
 
     @Override
     public void accept(StatementVisitor visitor) {
-        throw new UnsupportedOperationException();
+        visitor.visit(this);
     }
     
     @Override
index 2d90774feff1345c144be9392015537ad86417e8..a81cea78bfc512a5cc75b1509fd1ccbe204d2556 100644 (file)
@@ -6,4 +6,5 @@ public interface StatementVisitor {
     void visit(LetStatement statement);
     void visit(RuleStatement statement);
     void visit(IncludeStatement statement);
+    void visit(CHRStatement statement);
 }
index ba9d62d27ce730bffc2b99772321406736125e07..60e156a7f0a683dbac408cf2d9b8ba8d61bfa035 100644 (file)
@@ -598,5 +598,12 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
             statement.forValRefs(visitor);
         exit.forValRefs(visitor);
     }
+
+    public void cleanup() {
+        for(SSAStatement statement = firstStatement;
+                statement != null; statement = statement.next)
+            statement.cleanup();
+        exit.cleanup();
+    }
     
 }
index 57748b284b436c727109433613296de9e6910148..3dd77d926b519c495436cb22324b9826386d513e 100644 (file)
@@ -104,5 +104,7 @@ public abstract class SSAClosure implements Printable, BoundVarBinder {
     }
 
     public abstract void forValRefs(ValRefVisitor visitor);
+
+    public abstract void cleanup();
     
 }
index c183699f9cb5512eb95fa943bfa41d73a1c8b318..ae9ad5725a436256b382fbd12853544286c06312 100644 (file)
@@ -71,4 +71,6 @@ public abstract class SSAExit implements Printable {
     }
 
     public abstract void forValRefs(ValRefVisitor visitor);
+
+    public abstract void cleanup();
 }
\ No newline at end of file
index b9e8bfbb398e0803977e305533259eb0eb6d4982..209c92a64af4016687339f559e6639369093a7bb 100644 (file)
@@ -154,7 +154,7 @@ public final class SSAFunction extends SSAClosure {
         
         // Add valid variables and continuations
         context.validContinuations.add(returnCont);        
-        for(SSABlock block = firstBlock; block != null; block = block.next) {            
+        for(SSABlock block = firstBlock; block != null; block = block.next) {
             context.validContinuations.add(block);  
             for(BoundVar parameter : block.parameters)
                 context.validBoundVariables.add(parameter);
@@ -461,4 +461,9 @@ public final class SSAFunction extends SSAClosure {
             block.forValRefs(visitor);
     }
 
+    @Override
+    public void cleanup() {
+        for(SSABlock block = firstBlock; block != null; block = block.next)
+            block.cleanup();
+    }
 }
index e0dbf214f3a8a9a32c2adcec8c2feb98ab7ae225..c9c8b35fb19c16a85714c027772d102c50e92c88 100644 (file)
@@ -219,4 +219,11 @@ public class SSAModule {
         for(SCLConstant function : functions.values())
             function.saveInlinableDefinition();
     }
+
+    public void cleanup() {
+        for(SSAClosure closure : closuresToGenerate)
+            closure.cleanup();
+        for(SCLConstant constant : functions.values())
+            constant.cleanup();
+    }
 }
index 56877e304c96097885db1587d904bc48ff45ed82..a5ce6f95b9447ea02bebd418318b0463a739690d 100644 (file)
@@ -144,4 +144,10 @@ public class SSAObject extends SSAClosure implements ClosureBinder {
             closure.forValRefs(visitor);
     }
 
+    @Override
+    public void cleanup() {
+        for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
+            closure.cleanup();
+    }
+
 }
index 31742fbecd945ffb7783e7f87e71edd9fdc239c1..e957723d35f43ee5fe8b85515a46f4a2e569a78b 100644 (file)
@@ -123,4 +123,6 @@ public abstract class SSAStatement implements Printable {
     }
 
     public abstract void forValRefs(ValRefVisitor visitor);
+
+    public abstract void cleanup();
 }
index 296ec6d1f461545c72222ff8ad49cde1310ef267..4eca7d1aeb35fa851124281175643a0f489025e7 100644 (file)
@@ -223,4 +223,9 @@ public class If extends SSAExit implements ValRefBinder {
     public void forValRefs(ValRefVisitor visitor) {
         visitor.visit(condition);
     }
+
+    @Override
+    public void cleanup() {
+        condition.remove();
+    }
 }
index 6ffbe88619e1e05cf331950e50a3b3c5d1d5b1cb..eb1a3dea972dc61f05914b4c18e13015b37adf63 100644 (file)
@@ -146,4 +146,10 @@ public class Jump extends SSAExit implements ValRefBinder {
         for(ValRef parameter : parameters)
             visitor.visit(parameter);
     }
+
+    @Override
+    public void cleanup() {
+        for(ValRef parameter : parameters)
+            parameter.remove();
+    }
 }
index 386199d838d3cfd0e60cb1faea0375bb45791e21..b3584ae7e53692c5196bcf0f9f575723296f5117 100644 (file)
@@ -279,4 +279,9 @@ public class Switch extends SSAExit implements ValRefBinder {
     public void forValRefs(ValRefVisitor visitor) {
         visitor.visit(scrutinee);
     }
+
+    @Override
+    public void cleanup() {
+        scrutinee.remove();
+    }
 }
index b0391b96581cbe0df97d498589a862a23fe8b775..593b81c63f2914c40355e47b7932336f3e0ced29 100644 (file)
@@ -93,4 +93,8 @@ public class Throw extends SSAExit {
     @Override
     public void forValRefs(ValRefVisitor visitor) {
     }
+
+    @Override
+    public void cleanup() {
+    }
 }
index 400cb6e4e373f78c480e8fc37c1da3dc203a47f2..d9d79737f5222ab39e475a6385377eef49f8f0ce 100644 (file)
@@ -488,4 +488,11 @@ public class LetApply extends LetStatement implements ValRefBinder {
         for(ValRef parameter : parameters)
             visitor.visit(parameter);
     }
+
+    @Override
+    public void cleanup() {
+        function.remove();
+        for(ValRef parameter : parameters)
+            parameter.remove();
+    }
 }
index 9f6fe9f01d8511bf86e6f49f740a9795e6f16531..dc6a8580d713cc8c579ef1cbdfb45aad24dd34ea 100644 (file)
@@ -275,4 +275,10 @@ public class LetFunctions extends SSAStatement implements ClosureBinder {
         for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
             closure.forValRefs(visitor);    
     }
+
+    @Override
+    public void cleanup() {
+        for(SSAClosure closure = firstClosure; closure != null; closure = closure.getNext())
+            closure.cleanup();
+    }
 }
index a1724428303502e3de48030bf7545e853735ce3f..67f43838d837ff897d8a0f8c9a3d1e97df13ecee 100644 (file)
@@ -430,6 +430,7 @@ public class ExpressionEvaluator {
             throw new SCLExpressionCompilationException(errorLog.getErrors());
         }
         Map<String, byte[]> classes = moduleBuilder.getClasses();
+        ssaModule.cleanup();
         
         // Load generated code and execute
         try {
index 9b9dc6cb67ec862501598cc4e10252e7d2c3469f..9a77d100fca3ded3b6924aee9915d05119f52ecb 100644 (file)
@@ -7,7 +7,6 @@ import java.util.List;
 import java.util.Set;
 
 import org.simantics.databoard.Bindings;
-import org.simantics.datatypes.literal.GUID;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.RequestProcessor;
 import org.simantics.db.Resource;
@@ -142,8 +141,7 @@ public class StructuralUtils {
         g.claim(component, L0.HasName, Layer0Utils.literal(g, name));
         g.claim(component, L0.HasLabel, Layer0Utils.literal(g, ""));
         g.claim(parent, L0.ConsistsOf, component);
-        // Add identifier
-        Layer0Utils.addL0Identifier(g, component);
+        Layer0Utils.claimNewIdentifier(g, component, true);
         // Add comment to change set.
         CommentMetadata cm = g.getMetadata(CommentMetadata.class);
         g.addMetadata(cm.add("Created component " + component));
index 94ff2b6b6a4082a78dc5f006b0038d0b22999637..e1eb08baf0321c200af4d79b06034ceb5b4469b3 100644 (file)
@@ -102,22 +102,22 @@ public class ModelledSTSTest {
         ModuleRepository repo = new ModuleRepository(SCLOsgi.SOURCE_REPOSITORY);
         CommandSession session = null;
         try {
-            repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
-                
-                @Override
-                public ModuleCompilationOptions getOptions(String moduleName) {
-                    // TODO: default to false
-                    boolean coverage = true;
-                    // TODO: add moduleName filters back
-    //                for (Pattern p : getModuleNameFilterPatterns()) {
-    //                    if (p.matcher(moduleName.toLowerCase()).find()) {
-    //                        coverage = true;
-    //                        break;
-    //                    }
-    //                }
-                    return new ModuleCompilationOptions(coverage);
-                }
-            });
+//            repo.setAdvisor(new ModuleCompilationOptionsAdvisor() {
+//                
+//                @Override
+//                public ModuleCompilationOptions getOptions(String moduleName) {
+//                    // TODO: default to false
+//                    boolean coverage = true;
+//                    // TODO: add moduleName filters back
+//    //                for (Pattern p : getModuleNameFilterPatterns()) {
+//    //                    if (p.matcher(moduleName.toLowerCase()).find()) {
+//    //                        coverage = true;
+//    //                        break;
+//    //                    }
+//    //                }
+//                    return new ModuleCompilationOptions(coverage);
+//                }
+//            });
             
             SCLReportingHandler handler = (SCLReportingHandler) SCLContext.getCurrent().get(SCLReportingHandler.REPORTING_HANDLER);
             session = new CommandSession(repo, handler);
index 4075e1e11efaec0a6b3161db1bf9cf2b3f67bdba..80e0393cf42e6da121ed96f0e016d5cbf4b836b7 100644 (file)
@@ -311,7 +311,9 @@ public class ResourceEditorSupport implements IAdaptable, ChangeListener {
     }
 
     private static void scheduleEditorClose(IEditorPart editorPart) {
-        SWTUtils.asyncExec(editorPart.getSite().getShell(), () -> {
+        if (editorPart == null)
+            return;
+        SWTUtils.asyncExec(editorPart.getSite().getWorkbenchWindow().getShell(), () -> {
             // Don't have to check isDisposed since closeEditor
             // will ignore already closed editor parts.
             WorkbenchUtils.closeEditor(editorPart, false);
diff --git a/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/MemoryLeakTest.java b/tests/org.simantics.scl.compiler.tests/src/org/simantics/scl/compiler/tests/MemoryLeakTest.java
new file mode 100644 (file)
index 0000000..7ff61a8
--- /dev/null
@@ -0,0 +1,74 @@
+package org.simantics.scl.compiler.tests;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.simantics.scl.compiler.environment.specification.EnvironmentSpecification;
+import org.simantics.scl.compiler.errors.CompilationErrorFormatter;
+import org.simantics.scl.compiler.module.repository.ImportFailure;
+import org.simantics.scl.compiler.module.repository.ImportFailureException;
+import org.simantics.scl.compiler.module.repository.ModuleRepository;
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.top.ExpressionEvaluator;
+import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+
+public class MemoryLeakTest {
+    ModuleRepository moduleRepository;
+
+    EnvironmentSpecification environmentSpecification;
+
+    @Before
+    public void initialize() throws Exception {
+        moduleRepository = InitialRepository.getInitialRepository();
+
+        // Environment for compiling expressions
+        environmentSpecification = new EnvironmentSpecification();
+        environmentSpecification.importModule("Builtin", "");
+        environmentSpecification.importModule("Prelude", "");
+    }
+
+    private void testExpression0(String expressionText,
+            Object expectedValue,
+            Type expectedType) throws Exception {
+        
+        RuntimeEnvironment runtimeEnvironment;
+        try {
+            runtimeEnvironment = moduleRepository.createRuntimeEnvironment(environmentSpecification,
+                    getClass().getClassLoader());
+        } catch(ImportFailureException e) {
+            for(ImportFailure failure : e.failures)
+                System.err.println("Failed to import " + failure.moduleName);
+            throw e;
+        }
+
+        // Compiling and running expression
+        try {
+            Object result = new ExpressionEvaluator(runtimeEnvironment, expressionText)
+                    .expectedType(expectedType)
+                    .interpretIfPossible(false)
+                    .eval();
+            if(expectedValue != null)
+                Assert.assertEquals(expectedValue, result);
+        } catch(SCLExpressionCompilationException e) {
+            System.out.println(CompilationErrorFormatter.toString(expressionText, e.getErrors()));
+            throw e;
+        }
+    }
+
+    @Test
+    public void testIt() throws Exception {
+        for(int i=0;i<1000000;++i) {
+            testExpression0("fst (\"a\", \"b\")", "a", Types.STRING);
+            if(i % 10000 == 0 && i > 0) {
+                System.gc();
+                System.runFinalization();
+                System.gc();
+                Thread.sleep(100L);
+                double used = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory());
+                System.out.println(i + " " + used*1e-6 + " Mb, " + (used / i) + " b / expression");
+            }
+        }
+    }
+}