]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Multiple readers and variable optimization
authorAntti Villberg <antti.villberg@semantum.fi>
Thu, 17 May 2018 04:37:51 +0000 (07:37 +0300)
committerAntti Villberg <antti.villberg@semantum.fi>
Thu, 26 Jul 2018 20:58:32 +0000 (23:58 +0300)
gitlab #5
gitlab #6
(refs #6961)

Change-Id: Iabc5ff369cb42e8a3813519b6e5d981f538ebdff

71 files changed:
bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphSupport.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedPredicates.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/AssertedStatements.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java [moved from bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/NamespaceIndex.java with 59% similarity]
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/CodeGen.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/DirectPredicates.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/IntSet.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Predicates.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCache.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCacheBase.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryCollectorImpl.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/RelationInfoQuery.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/SuperRelations.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Types.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/URIToResource.java
bundles/org.simantics.db.layer0/adapters.xml
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ReflectionExternalValue.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/SCLExternalValue.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/request/PropertyInfoRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionAnalysisRequest.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionCompilationRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/CompileValueRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/ExpressionAnalysis.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/VariableMapImpl.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/CollectionSupportImpl.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java [new file with mode: 0644]
bundles/org.simantics.db/src/org/simantics/db/ConverterExternalValue.java [new file with mode: 0644]
bundles/org.simantics.db/src/org/simantics/db/ExternalValue.java [new file with mode: 0644]
bundles/org.simantics.db/src/org/simantics/db/ObjectResourceIdMap.java [new file with mode: 0644]
bundles/org.simantics.debug.ui/src/org/simantics/debug/ui/VariableDebugger.java
bundles/org.simantics.document.base.ontology/graph/Components.pgraph
bundles/org.simantics.document.base.ontology/graph/Functions.pgraph
bundles/org.simantics.document.base.ontology/graph/Properties.pgraph
bundles/org.simantics.document.server/adapters.xml
bundles/org.simantics.document.server/scl/Document/All.scl
bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentProperties.java [new file with mode: 0644]
bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentServerUtils.java
bundles/org.simantics.document.server/src/org/simantics/document/server/Functions.java
bundles/org.simantics.document.server/src/org/simantics/document/server/SCLExternalValue.java [new file with mode: 0644]
bundles/org.simantics.document.server/src/org/simantics/document/server/request/NodeRequest.java
bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLHandlerValueRequest.java
bundles/org.simantics.document.server/src/org/simantics/document/server/request/ServerSCLValueRequest.java
bundles/org.simantics.document.swt.core/src/org/simantics/document/swt/core/widget/ComboWidget.java
bundles/org.simantics.graph.db/src/org/simantics/graph/db/TransferableGraphs.java
bundles/org.simantics.layer0/graph/Layer0SCL.pgraph
bundles/org.simantics.layer0/graph/Layer0Values.pgraph
bundles/org.simantics.modeling/adapters.xml
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContent.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContentRequest.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyVariable.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariable.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableBuilder.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContent.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContentRequest.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/scl/AnalyseSCLValueRequest.java [new file with mode: 0644]
bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/Synchronizer.java
bundles/org.simantics.structural2/scl/Simantics/Structural.scl
bundles/org.simantics.structural2/src/org/simantics/structural2/ConnectionImpl.java [new file with mode: 0644]
bundles/org.simantics.structural2/src/org/simantics/structural2/Functions.java
bundles/org.simantics.structural2/src/org/simantics/structural2/queries/ConnectionPointMapOfResource.java
bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AbstractAnalyseStructuralValueRequest.java [new file with mode: 0644]
bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AnalyseStructuralValueRequest.java [new file with mode: 0644]
bundles/org.simantics.structural2/src/org/simantics/structural2/utils/StructuralUtils.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/Connection.java
bundles/org.simantics.structural2/src/org/simantics/structural2/variables/StandardProceduralChildVariable.java
features/org.simantics.desktop.product.feature/feature.xml

index 02877596b00d4423fac8387a31bdc73cdde76e87..c8bd03257f5783f0300ff08f1714069406bc48b1 100644 (file)
@@ -1,13 +1,12 @@
 package org.simantics.db.common.request;
 
+import org.simantics.db.ExternalValue;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.utils.Functions;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.RuntimeDatabaseException;
 import org.simantics.layer0.Layer0;
-import org.simantics.scl.reflection.ReflectionUtils;
-import org.simantics.scl.reflection.ValueNotFoundException;
 import org.simantics.scl.runtime.function.FunctionImpl3;
 
 /**
@@ -20,7 +19,7 @@ public class AdaptValue extends ResourceRead<Object> {
         super(resource);
     }
 
-    private static final FunctionImpl3<ReadGraph,Resource,Object,Object> functionApplication = new FunctionImpl3<ReadGraph,Resource,Object,Object>() {
+    public static final FunctionImpl3 functionApplication = new FunctionImpl3<ReadGraph,Resource,Object,Object>() {
 
                @Override
                public Object apply(ReadGraph graph, Resource resource, Object context) {
@@ -36,12 +35,11 @@ public class AdaptValue extends ResourceRead<Object> {
     @Override
     public Object perform(ReadGraph graph) throws DatabaseException {
         String uri = graph.getURI(resource);        
-        try {
-                       if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication;
-            return ReflectionUtils.getValue(uri).getValue();
-        } catch (ValueNotFoundException e) {
-            throw new DatabaseException("Couldn't adapt the value " + uri, e);
-        }
+        if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication;
+                       
+        ExternalValue ev = graph.adapt(resource, ExternalValue.class);
+        return ev.getValue(graph, resource);
+
     }
 
 }
index 25438ef1ef3f0d57878c32c3c03def4111c8ca0c..e3e7d50ecbc04998d62a650a9695ce939b6667ac 100644 (file)
@@ -45,6 +45,7 @@ import org.simantics.databoard.util.binary.BinaryFile;
 import org.simantics.databoard.util.binary.RandomAccessBinary;
 import org.simantics.db.AsyncReadGraph;
 import org.simantics.db.DevelopmentKeys;
+import org.simantics.db.ExternalValue;
 import org.simantics.db.ExternalValueSupport;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.RelationContext;
@@ -6453,7 +6454,8 @@ public class ReadGraphImpl implements ReadGraph {
             for(Resource converter : graph.getObjects(resource, L0.ConvertsToValueWith)) {
                 try {
                        if(L0.Functions_functionApplication.equals(converter)) {
-                               return (Function3<ReadGraph,Resource,Object,T>)graph.syncRequest(new AdaptValue(resource));
+                               return AdaptValue.functionApplication;
+                               //return (Function3<ReadGraph,Resource,Object,T>)graph.syncRequest(new AdaptValue(resource));
                        } else {
                                return graph.getValue2(converter, resource);
                        }
@@ -6511,9 +6513,11 @@ public class ReadGraphImpl implements ReadGraph {
                }
        } else if(types.contains(L0.ExternalValue)) {
                try {
-                       return (T)ReflectionUtils.getValue(getURI(r)).getValue();
-               } catch(ValueNotFoundException e) {
-                       throw new DatabaseException(e);
+                       ExternalValue ev = adapt(r, ExternalValue.class);
+                       return ev.getValue(this, r);
+                       //return (T)ReflectionUtils.getValue(getURI(r)).getValue();
+//             } catch(ValueNotFoundException e) {
+//                     throw new DatabaseException(e);
                } catch(ClassCastException e) {
                        throw new DatabaseException(e);
                }
index d8fda07b7704c49b96f07c4788d8d5470caf4b46..3f7e6f4e63ba7d07b8442fd50903a18fb4927d8f 100644 (file)
@@ -72,7 +72,7 @@ public interface ReadGraphSupport {
     void forPossibleSuperrelation(ReadGraphImpl graph, Resource subject, AsyncProcedure<Resource> procedure);
     void forSuperrelations(ReadGraphImpl graph, Resource subject, AsyncProcedure<Set<Resource>> procedure);
     byte[] getValue(ReadGraphImpl graph, Resource subject) throws DatabaseException;
-    byte[] forValue(ReadGraphImpl graph, Resource subject, AsyncProcedure<byte[]> procedure);
+    void forValue(ReadGraphImpl graph, Resource subject, AsyncProcedure<byte[]> procedure);
     void forPossibleValue(ReadGraphImpl graph, Resource subject, AsyncProcedure<byte[]> procedure);
     void forInverse(ReadGraphImpl graph, Resource relation, AsyncProcedure<Resource> procedure);
     void forResource(ReadGraphImpl graph, String id, AsyncProcedure<Resource> procedure);
index 8013c1a47d2c0684e0a5a2cf1a3084ab079fcde6..410db7118e31f59888e07d9672127a97d01b275b 100644 (file)
@@ -160,40 +160,16 @@ final public class AssertedPredicates extends CollectionUnaryQuery<IntProcedure>
         
     }
 
-       final static InternalProcedure<RelationInfo> ip = new InternalProcedure<RelationInfo>() {
-
-               @Override
-               public void execute(ReadGraphImpl graph, RelationInfo result) {
-               }
-
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
-
-       };
-
-       final static InternalProcedure<IntSet> ip2 = new InternalProcedure<IntSet>() {
-
-               @Override
-               public void execute(ReadGraphImpl graph, IntSet result) {
-               }
-
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
-
-       };
-
        synchronized private void addOrSetHiding(ReadGraphImpl graph, int add, CacheEntry parent) throws DatabaseException {
 
        assert(isPending());
        
         IntArray value = (IntArray)getResult(); 
-               RelationInfo ri = QueryCacheBase.resultRelationInfoQuery(graph, add, parent, null, ip);
+               RelationInfo ri = QueryCacheBase.resultRelationInfoQuery(graph, add, parent, null);
                if(ri.isFunctional) {
                        // Replace existing functional predicate if found
                        try {
-                               IntSet supers = QueryCache.resultSuperRelations(graph, add, parent, null, ip2); 
+                               IntSet supers = QueryCache.resultSuperRelations(graph, add, parent, null); 
                        if(value.data == null) {
                            if(value.sizeOrData != IntArray.NO_DATA) {
                                if(supers.contains(value.sizeOrData)) {
index a9ce7c6f8c7334926e2c132b05a21bd941e9592d..90daa9a845fe4fad3e9979eed02ab169fc14cc25 100644 (file)
@@ -145,7 +145,7 @@ final public class AssertedStatements extends CollectionBinaryQuery<TripleIntPro
 
     public static void computeForEach(ReadGraphImpl graph, final int type, final int predicate, final AssertedStatements entry, final TripleIntProcedure procedure) throws DatabaseException {
 
-       RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, predicate, entry, null, QueryCache.emptyRelationInfoProcedure);
+       RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, predicate, entry, null);
        
         final AtomicInteger found = new AtomicInteger(0);
 
@@ -364,9 +364,6 @@ final public class AssertedStatements extends CollectionBinaryQuery<TripleIntPro
 
     private boolean addOrSet(int s, int p, int o) {
        
-       if(!isPending())
-               System.err.println("asd");
-        
        assert(isPending());
         
         IntArray value = (IntArray)getResult();
@@ -401,9 +398,6 @@ final public class AssertedStatements extends CollectionBinaryQuery<TripleIntPro
     
     static void finish(ReadGraphImpl graph, AssertedStatements entry) {
         
-       if(!entry.isPending())
-               System.err.println("asd");
-       
        assert(entry.isPending());
        if(entry != null) {
                synchronized(entry) {
similarity index 59%
rename from bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/NamespaceIndex.java
rename to bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/ChildMap.java
index 884f3f6d4e7ad37c0a124486a50f26173cefda37..9f24ba64023a62b439c8c5bdc84345b826fae4ed 100644 (file)
@@ -13,33 +13,37 @@ package org.simantics.db.impl.query;
 
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.serialization.Serializer;
-import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.db.ObjectResourceIdMap;
 import org.simantics.db.common.WriteBindings;
 import org.simantics.db.common.exception.DebugException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.procedure.InternalProcedure;
+import org.simantics.db.service.CollectionSupport;
 
-import gnu.trove.map.hash.TObjectIntHashMap;
-
-final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectIntHashMap<String>>> {
+final public class ChildMap extends UnaryQuery<InternalProcedure<ObjectResourceIdMap<String>>> {
        
-    NamespaceIndex(final String id) {
-        super(id);
+    ChildMap(final int r) {
+        super(r);
     }
     
        @Override
        final public void removeEntry(QueryProcessor provider) {
                provider.cache.remove(this);
        }
-       
-       final static private void index(ReadGraphImpl graph, int root, NamespaceIndex entry, final InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
+       
+    @Override
+       public Object compute(ReadGraphImpl graph, final InternalProcedure<ObjectResourceIdMap<String>> procedure) throws DatabaseException {
+               computeForEach(graph, id, this, procedure);
+               return getResult();
+    }
+
+       public static void computeForEach(ReadGraphImpl graph, final int root, final ChildMap entry, final InternalProcedure<ObjectResourceIdMap<String>> procedure) throws DatabaseException {
                
                if(root == 0) {
                        if(entry != null)
                                entry.add2(graph, null);
             procedure.execute(graph, null);
-//            System.err.println("NamespaceIndex[" + id + "]->null");
             return;
                }
 
@@ -48,7 +52,7 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
                final int consistsOf = processor.getConsistsOf();
                final int hasName = processor.getHasName();
         
-        final TObjectIntHashMap<String> result = new TObjectIntHashMap<String>();
+               ObjectResourceIdMap<String> result = graph.getService(CollectionSupport.class).createObjectResourceMap(String.class);
         
         QueryCache.runnerObjects(graph, root, consistsOf, entry, null, new SyncIntProcedure() {
                
@@ -67,8 +71,6 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
 
                @Override
                public void execute(ReadGraphImpl graph, final int obj) throws DatabaseException {
-                       
-                       //System.out.println(id + " => " + obj);
 
                        inc();
                        
@@ -91,12 +93,7 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
                                                Binding b = WriteBindings.STRING;
                                            Serializer serializer = b.serializer();
                                            final String part = (String)serializer.deserialize(value);
-       
-                                           synchronized(result) {
-                                               Object previous = result.put(URIStringUtils.escape(part), obj);
-                                               // TODO: this is not the most elegant solution
-                                               if(previous != null) previous = "";
-                                           }
+                                           result.putId(part, obj);
                                            
                                                } catch (Throwable e) {
                                            if(DebugException.DEBUG) new DebugException(e).printStackTrace();
@@ -137,67 +134,12 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
         
     }
 
-       
-    @Override
-       public Object compute(ReadGraphImpl graph, final InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
-               computeForEach(graph, id, this, procedure);
-               return getResult();
-    }
-
-       public static void computeForEach(ReadGraphImpl graph, final String id, final NamespaceIndex entry, final InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
-       
-       QueryProcessor processor = graph.processor;
-       
-//     System.err.println("NamespaceIndex " + id);
-       
-        if("http://".equals(id) || "http:/".equals(id)) {
-            index(graph, processor.getRootLibrary(), entry, procedure);
-        } else {
-            final String[] parts = URIStringUtils.splitURI(id);
-            if(parts != null) {
-                QueryCache.runnerNamespaceIndex(graph, parts[0], entry, null, new InternalProcedure<TObjectIntHashMap<String>>() {
-    
-                    @Override
-                    public void execute(ReadGraphImpl graph, TObjectIntHashMap<String> index) throws DatabaseException {
-    
-                        if(index != null) {
-                            index(graph, index.get(parts[1]), entry, procedure);
-                        } else {
-                            if(entry != null) entry.add2(graph, null);
-                            procedure.execute(graph, null);
-//                            System.err.println("NamespaceIndex[" + id + "]->null");
-                        }
-                        
-                    }
-    
-                    @Override
-                    public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                        if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                        if(entry != null) entry.except(t);
-                        procedure.exception(graph, t);
-                    }
-    
-                });
-            } else {
-                if(entry != null) entry.add2(graph, null);
-                procedure.execute(graph, null);
-//                System.err.println("NamespaceIndex[" + id + "]->null");
-            }
-
-        }
-        
-    }
-
     @Override
     public String toString() {
-       return "NamespaceIndex[" + id + "]";
+       return "ChildMap[" + id + "]";
     }
 
-    private void add2(ReadGraphImpl graph, TObjectIntHashMap<String> result) {
-       
-       if(!isPending()) {
-               new Exception(""+hashCode()).printStackTrace();
-       }
+    private void add2(ReadGraphImpl graph, ObjectResourceIdMap<String> result) {
        
        assert(isPending());
 
@@ -211,13 +153,13 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
     }
     
     @Override
-    public Object performFromCache(ReadGraphImpl graph, InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
+    public Object performFromCache(ReadGraphImpl graph, InternalProcedure<ObjectResourceIdMap<String>> procedure) throws DatabaseException {
         
         assert(isReady());
         
        if(handleException(graph, procedure)) return (Throwable)statusOrException;
         
-       TObjectIntHashMap<String> result = (TObjectIntHashMap<String>)getResult();
+       ObjectResourceIdMap<String> result = (ObjectResourceIdMap<String>)getResult();
        
         procedure.execute(graph, result);
         
@@ -228,10 +170,10 @@ final public class NamespaceIndex extends StringQuery<InternalProcedure<TObjectI
     @Override
     public void recompute(ReadGraphImpl graph) throws DatabaseException {
         
-        compute(graph, new InternalProcedure<TObjectIntHashMap<String>>() {
+        compute(graph, new InternalProcedure<ObjectResourceIdMap<String>>() {
 
             @Override
-            public void execute(ReadGraphImpl graph, TObjectIntHashMap<String> result) {
+            public void execute(ReadGraphImpl graph, ObjectResourceIdMap<String> result) {
             }
                        
                        @Override
index 857d93487235a0c43f83fd2a2de47c05aa9bb0b0..ed60398478b8a70933b1f28ef8e201147b975394 100644 (file)
@@ -7,6 +7,7 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLDecoder;
 
+import org.simantics.db.ObjectResourceIdMap;
 import org.simantics.utils.FileUtils;
 
 public class CodeGen {
@@ -23,6 +24,7 @@ public class CodeGen {
        String[] signatureR2TIP = { "int r1, int r2", "r1,r2", "keyR2", "long", "TripleIntProcedure", "entry.id" };
        String[] signatureID1 = { "String id", "id", "keyID", "String", "InternalProcedure<Integer>", "entry.id" };
        String[] signatureID2 = { "String id", "id", "keyID", "String", "InternalProcedure<TObjectIntHashMap<String>>", "entry.id" };
+       String[] signatureChildMap = { "int r", "r", "keyR", "long", "InternalProcedure<ObjectResourceIdMap<String>>", "entry.id" };
        String[] signatureRead = { "Read<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
        String[] signatureAsyncRead = { "AsyncRead<?> r", "r", "id", "long", "AsyncProcedure", "entry.request" };
        String[] signatureMultiRead = { "MultiRead<?> r", "r", "id", "long", "AsyncMultiProcedure", "entry.request" };
@@ -45,13 +47,13 @@ public class CodeGen {
        public void generateRunner(StringBuilder content, String clazz, String[] signature, boolean shortcut) {
                
                line(content, "public static void runner" + clazz + "(ReadGraphImpl graph, " + signature[0] + ", CacheEntry parent, ListenerBase listener, " + signature[4] + " procedure) throws DatabaseException {");
+               line(content, "    QueryCache cache  = graph.processor.cache;");
                if(shortcut) {
-                       line(content, "    if(parent == null && listener == null) {");
+                       line(content, "    if(parent == null && listener == null && !cache.shouldCache(graph.processor, " + signature[1] + ")) {");
                        line(content, "        " + clazz + ".computeForEach(graph, " + signature[1] + ", null, procedure);");
                        line(content, "        return;");
                        line(content, "    }");
                }
-               line(content, "    QueryCache cache  = graph.processor.cache;");
                line(content, "    if(procedure == null) procedure = emptyProcedure" + clazz + ";");
                line(content, "    " + clazz + " entry = (" + clazz + ")cache.getOrCreate" + clazz + "(" + signature[1] + ");");
                line(content, "    ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);");
@@ -92,6 +94,7 @@ public class CodeGen {
                line(content, "            existing.clearResult(querySupport);");
                line(content, "            existing.setPending();");
                line(content, "            " + lower + "Map.put(" + signature[2] + "(" + signature[1] + "), existing);");
+               line(content, "            size++;");
                line(content, "            return existing;");
                line(content, "        }");
                line(content, "        if(existing.requiresComputation()) {");
@@ -121,6 +124,8 @@ public class CodeGen {
                     StringBuilder content = new StringBuilder();
                     content.append("package org.simantics.db.impl.query;\n");
                     content.append("\n");
+                    
+                    content.append("import org.simantics.db.ObjectResourceIdMap;\n");
                     content.append("import org.simantics.db.RelationInfo;\n");
                     content.append("import org.simantics.db.exception.DatabaseException;\n");
                     content.append("import org.simantics.db.impl.graph.ReadGraphImpl;\n");
@@ -157,7 +162,8 @@ public class CodeGen {
                     generateQuery(content, "ReadEntry", signatureRead, true);
                     generateQuery(content, "AsyncReadEntry", signatureAsyncRead, true);
                     generateQuery(content, "Types", signatureR1IntSet, true);
-                    generateQuery(content, "NamespaceIndex", signatureID2, true);
+                    //generateQuery(content, "NamespaceIndex", signatureID2, true);
+                    generateQuery(content, "ChildMap", signatureChildMap, true);
 
                     generateQuery(content, "AssertedStatements", signatureR2TIP, false);
                     generateQuery(content, "AssertedPredicates", signatureR1IP, false);
index 2d15b6b804031e8934640a526794fe349daf7c9e..feb0533efb4c06f626d4e45b158ca288076c192c 100644 (file)
@@ -42,7 +42,7 @@ final public class DirectPredicates extends CollectionUnaryQuery<InternalProcedu
 
                graph.processor.querySupport.ensureLoaded(graph, id);
                
-               final IntSet list = new IntSet();
+               final IntSet list = new IntSet(graph.processor.querySupport);
 
                graph.processor.querySupport.getPredicates(graph, id, new IntProcedure() {
 
index fdea8d2132e49c78ace27d26015ff8b5800084cd..813677d53265d36079395fd471f160e69237680b 100644 (file)
@@ -43,12 +43,12 @@ final public class IntSet implements ResourceSet {
     
     private static final Object[] EMPTY_ARRAY = new Object[0];
 
-    public IntSet() {
-        support = null;
-        data = null;
-        sizeOrData = NO_DATA;
+    public static IntSet EMPTY = new IntSet();
+    
+    private IntSet() {
+       support = null;
     }
-
+    
     public IntSet(QuerySupport support) {
         this.support = support.getSupport();
         data = null;
index d95f3160a6774a53dc566a1b1d15054224b1a93d..62fb3bdb8c73c3449b091501d7d275264ab6a889 100644 (file)
@@ -81,7 +81,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
                        @Override
                        public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
                                if(result == null) {
-                                       result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null, NOPT);
+                                       result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
                                } else {
                                        if (first) {
                                                IntArray ia = result;
@@ -91,7 +91,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
                                                }
                                                first = false;
                                        }
-                                       IntArray ia = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null, NOPT);
+                                       IntArray ia = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
                                        if(ia.data != null) {
                                                for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
                                        }
@@ -151,7 +151,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
 
                        IntSet candidateIs = null;
                        try {
-                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, entry, null, NOP);
+                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, entry, null);
                        } catch (DatabaseException e) {
                                if(entry != null) entry.except(e);
                                procedure.exception(graph, e);
@@ -173,7 +173,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
 
                                                IntSet nextIs = null;
                                                try {
-                                                       nextIs = QueryCache.resultSuperTypes(graph, nextS, entry, null, NOP);
+                                                       nextIs = QueryCache.resultSuperTypes(graph, nextS, entry, null);
                                                } catch (DatabaseException e) {
                                                        if(entry != null) entry.except(e);
                                                        procedure.exception(graph, e);
@@ -312,7 +312,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
                } else {
 
                        // Note! The dependency is intentionally cut!
-            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null, QueryCache.emptyProcedureDirectPredicates);
+            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
 
                                boolean found = false;
@@ -544,7 +544,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
                } else {
 
                        // Note! The dependency is intentionally cut!
-            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null, QueryCache.emptyProcedureDirectPredicates);
+            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
 
                                @Override
@@ -656,7 +656,7 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
 
        public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure) throws DatabaseException {
 
-               RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null, ip);
+               RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
                graph.ensureLoaded(r1, r2);       
                if(ri.isFunctional) {
                        computeFunctionalIndex(graph, r1, r2, entry, ri, procedure);
@@ -666,18 +666,6 @@ final public class Objects extends CollectionBinaryQuery<IntProcedure> {
 
        }
 
-       final static InternalProcedure<RelationInfo> ip = new InternalProcedure<RelationInfo>() {
-
-               @Override
-               public void execute(ReadGraphImpl graph, RelationInfo result) {
-               }
-
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
-
-       };
-
        @Override
        public String toString() {
                return "Objects[" + r1() + " - " + r2() + "]";
index 3841e1d14640777706ce30421c00d2bcce2d43ea..e5cb6dfa146e10f6cf5b6b909554e56abe532cc0 100644 (file)
@@ -85,45 +85,39 @@ final public class Predicates extends UnaryQuery<InternalProcedure<IntSet>> {
 
        public static void computeForEach(ReadGraphImpl graph, final int r, final Predicates entry, final InternalProcedure<IntSet> procedure) throws DatabaseException {
        
-       
-       IntSet direct = QueryCache.resultDirectPredicates(graph, r, entry, null, procedure);
-               IntSet result = new IntSet();
-               direct.forEach(new TIntProcedure() {
-                       @Override
-                       public boolean execute(int value) {
-                               result.add(value);
-                               return true;
-                       }
-               });
+       IntSet direct = QueryCache.resultDirectPredicates(graph, r, entry, null);
                
+               IntSet result = new IntSet(graph.processor.querySupport);
        forAssertions(graph, r, entry, result);
        
-//             DirectPredicates.queryEach(graph, r, processor, entry, null, new IntProcedure() {
-//
-//                     @Override
-//                     public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
-//                             result.add(pred);
-//                     }
-//
-//                     @Override
-//                     public void finished(ReadGraphImpl graph) throws DatabaseException {
-//                             
-//
-//                     }
-//
-//                     @Override
-//                     public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-//                             procedure.exception(graph, t);
-//                     }
-//
-//             });
-               
-               if(entry != null) {
-                       entry.setResult(result);
-                       entry.setReady();
-               }
+       if(result.isEmpty()) {
+               
+               if(entry != null) {
+                       entry.setResult(direct);
+                       entry.setReady();
+               }
+               
+               procedure.execute(graph, direct);
+               
+       } else {
+               
+               direct.forEach(new TIntProcedure() {
+                       @Override
+                       public boolean execute(int value) {
+                               result.add(value);
+                               return true;
+                       }
+               });
+
+               if(entry != null) {
+                       entry.setResult(result);
+                       entry.setReady();
+               }
+               
+               procedure.execute(graph, result);
+               
+       }
                
-               procedure.execute(graph, result);
         
     }
     
index dbd0068c3f66100404eda02d5fbba9d70fdc8308..49e02dece32049884f7a3907e85f960f2bf27f64 100644 (file)
@@ -1,5 +1,6 @@
 package org.simantics.db.impl.query;
 
+import org.simantics.db.ObjectResourceIdMap;
 import org.simantics.db.RelationInfo;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.graph.ReadGraphImpl;
@@ -30,6 +31,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 objectsMap.put(keyR2(r1,r2), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -48,11 +50,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerObjects(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r1,r2)) {
             Objects.computeForEach(graph, r1,r2, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureObjects;
         Objects entry = (Objects)cache.getOrCreateObjects(r1,r2);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -72,6 +74,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 statementsMap.put(keyR2(r1,r2), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -90,11 +93,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, TripleIntProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r1,r2)) {
             Statements.computeForEach(graph, r1,r2, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureStatements;
         Statements entry = (Statements)cache.getOrCreateStatements(r1,r2);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -114,6 +117,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 directObjectsMap.put(keyR2(r1,r2), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -132,11 +136,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerDirectObjects(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r1,r2)) {
             DirectObjects.computeForEach(graph, r1,r2, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureDirectObjects;
         DirectObjects entry = (DirectObjects)cache.getOrCreateDirectObjects(r1,r2);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -156,6 +160,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 relationInfoQueryMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -174,11 +179,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<RelationInfo> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             RelationInfoQuery.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureRelationInfoQuery;
         RelationInfoQuery entry = (RelationInfoQuery)cache.getOrCreateRelationInfoQuery(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -198,6 +203,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 uRIToResourceMap.put(keyID(id), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -216,11 +222,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener, InternalProcedure<Integer> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, id)) {
             URIToResource.computeForEach(graph, id, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureURIToResource;
         URIToResource entry = (URIToResource)cache.getOrCreateURIToResource(id);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -240,6 +246,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 valueQueryMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -258,11 +265,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<byte[]> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             ValueQuery.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureValueQuery;
         ValueQuery entry = (ValueQuery)cache.getOrCreateValueQuery(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -282,6 +289,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 orderedSetMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -300,11 +308,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerOrderedSet(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             OrderedSet.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureOrderedSet;
         OrderedSet entry = (OrderedSet)cache.getOrCreateOrderedSet(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -324,6 +332,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 principalTypesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -342,11 +351,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerPrincipalTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, IntProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             PrincipalTypes.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedurePrincipalTypes;
         PrincipalTypes entry = (PrincipalTypes)cache.getOrCreatePrincipalTypes(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -366,6 +375,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 directPredicatesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -384,11 +394,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             DirectPredicates.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureDirectPredicates;
         DirectPredicates entry = (DirectPredicates)cache.getOrCreateDirectPredicates(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -408,6 +418,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 predicatesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -426,11 +437,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             Predicates.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedurePredicates;
         Predicates entry = (Predicates)cache.getOrCreatePredicates(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -450,6 +461,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 readEntryMap.put(id(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -468,11 +480,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerReadEntry(ReadGraphImpl graph, Read<?> r, CacheEntry parent, ListenerBase listener, AsyncProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             ReadEntry.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureReadEntry;
         ReadEntry entry = (ReadEntry)cache.getOrCreateReadEntry(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -492,6 +504,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 asyncReadEntryMap.put(id(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -510,11 +523,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerAsyncReadEntry(ReadGraphImpl graph, AsyncRead<?> r, CacheEntry parent, ListenerBase listener, AsyncProcedure procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             AsyncReadEntry.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureAsyncReadEntry;
         AsyncReadEntry entry = (AsyncReadEntry)cache.getOrCreateAsyncReadEntry(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -534,6 +547,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 typesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -552,11 +566,11 @@ public class QueryCache extends QueryCacheBase {
     }
     
     public static void runnerTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
             Types.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
         if(procedure == null) procedure = emptyProcedureTypes;
         Types entry = (Types)cache.getOrCreateTypes(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
@@ -567,15 +581,16 @@ public class QueryCache extends QueryCacheBase {
         }
     }
     
-    NamespaceIndex getOrCreateNamespaceIndex(String id) throws DatabaseException {
-        NamespaceIndex existing = null;
-        synchronized(namespaceIndexMap) {
-            existing = (NamespaceIndex)namespaceIndexMap.get(id);
+    ChildMap getOrCreateChildMap(int r) throws DatabaseException {
+        ChildMap existing = null;
+        synchronized(childMapMap) {
+            existing = (ChildMap)childMapMap.get(r);
             if(existing == null) {
-                existing = new NamespaceIndex(id);
+                existing = new ChildMap(r);
                 existing.clearResult(querySupport);
                 existing.setPending();
-                namespaceIndexMap.put(keyID(id), existing);
+                childMapMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -587,24 +602,24 @@ public class QueryCache extends QueryCacheBase {
         return existing;
     }
     
-    void remove(NamespaceIndex entry) {
-        synchronized(namespaceIndexMap) {
-            namespaceIndexMap.remove(entry.id);
+    void remove(ChildMap entry) {
+        synchronized(childMapMap) {
+            childMapMap.remove(entry.id);
         }
     }
     
-    public static void runnerNamespaceIndex(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener, InternalProcedure<TObjectIntHashMap<String>> procedure) throws DatabaseException {
-        if(parent == null && listener == null) {
-            NamespaceIndex.computeForEach(graph, id, null, procedure);
+    public static void runnerChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<ObjectResourceIdMap<String>> procedure) throws DatabaseException {
+        QueryCache cache  = graph.processor.cache;
+        if(parent == null && listener == null && !cache.shouldCache(graph.processor, r)) {
+            ChildMap.computeForEach(graph, r, null, procedure);
             return;
         }
-        QueryCache cache  = graph.processor.cache;
-        if(procedure == null) procedure = emptyProcedureNamespaceIndex;
-        NamespaceIndex entry = (NamespaceIndex)cache.getOrCreateNamespaceIndex(id);
+        if(procedure == null) procedure = emptyProcedureChildMap;
+        ChildMap entry = (ChildMap)cache.getOrCreateChildMap(r);
         ListenerEntry listenerEntry = cache.registerDependencies(graph, entry, parent, listener, procedure, false);
         if(entry.isReady()) entry.performFromCache(graph, procedure);
         else {
-            NamespaceIndex.computeForEach(graph, id, entry, procedure);
+            ChildMap.computeForEach(graph, r, entry, procedure);
             if(listenerEntry != null) cache.primeListenerEntry(listenerEntry, entry.getResult());
         }
     }
@@ -618,6 +633,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 assertedStatementsMap.put(keyR2(r1,r2), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -656,6 +672,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 assertedPredicatesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -694,6 +711,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 directSuperRelationsMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -732,6 +750,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 superTypesMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -770,6 +789,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 typeHierarchyMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -808,6 +828,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 superRelationsMap.put(keyR(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -846,6 +867,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 multiReadEntryMap.put(id(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -884,6 +906,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 asyncMultiReadEntryMap.put(id(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
@@ -922,6 +945,7 @@ public class QueryCache extends QueryCacheBase {
                 existing.clearResult(querySupport);
                 existing.setPending();
                 externalReadEntryMap.put(id(r), existing);
+                size++;
                 return existing;
             }
             if(existing.requiresComputation()) {
index e2737f891385911bdb321139dcd7b93a45ff518c..f75cd9dcd80b790727383a5d078f84f9c374c994 100644 (file)
@@ -5,6 +5,7 @@ import java.util.Collection;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.ObjectResourceIdMap;
 import org.simantics.db.RelationInfo;
 import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
@@ -38,7 +39,8 @@ public class QueryCacheBase {
        public boolean                                         collecting            = false;
 
        final protected THashMap<String, URIToResource>                      uRIToResourceMap;
-       final protected THashMap<String, NamespaceIndex>                     namespaceIndexMap;
+       //final protected THashMap<String, NamespaceIndex>                     namespaceIndexMap;
+       final protected UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>> childMapMap;
        final protected DoubleKeyQueryHashMap<IntProcedure>                     objectsMap;
        final protected DoubleKeyQueryHashMap<TripleIntProcedure>               assertedStatementsMap;
        final protected DoubleKeyQueryHashMap<IntProcedure>                     directObjectsMap;
@@ -79,7 +81,8 @@ public class QueryCacheBase {
                valueQueryMap = new UnaryQueryHashMap();
                principalTypesMap = new UnaryQueryHashMap();
                uRIToResourceMap = new THashMap<String, URIToResource>();
-               namespaceIndexMap = new THashMap<String, NamespaceIndex>();
+               //namespaceIndexMap = new THashMap<String, NamespaceIndex>();
+               childMapMap = new UnaryQueryHashMap<InternalProcedure<ObjectResourceIdMap<String>>>();
                relationInfoQueryMap = new UnaryQueryHashMap();
                typeHierarchyMap = new UnaryQueryHashMap();
                superTypesMap = new UnaryQueryHashMap();
@@ -373,12 +376,15 @@ public class QueryCacheBase {
                
        }
        
-       synchronized public ListenerEntry registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
+       public ListenerEntry registerDependencies(ReadGraphImpl graph, CacheEntry child, CacheEntry parent, ListenerBase listener, Object procedure, boolean inferred) {
 
                if (parent != null && !inferred) {
                        try {
-                               if(!child.isImmutable(graph))
-                                       child.addParent(parent);
+                               if(!child.isImmutable(graph)) {
+                                       synchronized(child) {
+                                               child.addParent(parent);
+                                       }
+                               }
                        } catch (DatabaseException e) {
                                Logger.defaultLogError(e);
                        }
@@ -393,7 +399,7 @@ public class QueryCacheBase {
 
        }
        
-       public ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
+       public synchronized ListenerEntry registerListener(final CacheEntry entry, final ListenerBase base, final Object procedure) {
 
                assert (entry != null);
 
@@ -510,7 +516,8 @@ public class QueryCacheBase {
                realSize += directSuperRelationsMap.size();
                realSize += principalTypesMap.size();
                realSize += uRIToResourceMap.size();
-               realSize += namespaceIndexMap.size();
+               //realSize += namespaceIndexMap.size();
+               realSize += childMapMap.size();
                
                realSize += relationInfoQueryMap.size();
                realSize += superTypesMap.size();
@@ -547,9 +554,11 @@ public class QueryCacheBase {
                for(CacheEntryBase e : uRIToResourceMap.values())
                        if(e.getLevel() <= level)
                                result.add(e);
-               for(CacheEntryBase e : namespaceIndexMap.values())
-                       if(e.getLevel() <= level)
-                               result.add(e);
+//             for(CacheEntryBase e : namespaceIndexMap.values())
+//                     if(e.getLevel() <= level)
+//                             result.add(e);
+
+               childMapMap.values(level, result);
                
                relationInfoQueryMap.values(level, result);
                superTypesMap.values(level, result);
@@ -585,7 +594,8 @@ public class QueryCacheBase {
                entries.addAll(directSuperRelationsMap.values());
                entries.addAll(principalTypesMap.values());
                entries.addAll(uRIToResourceMap.values());
-               entries.addAll(namespaceIndexMap.values());
+               //entries.addAll(namespaceIndexMap.values());
+               entries.addAll(childMapMap.values());
                entries.addAll(relationInfoQueryMap.values());
                entries.addAll(superTypesMap.values());
                entries.addAll(superRelationsMap.values());
@@ -643,7 +653,9 @@ public class QueryCacheBase {
 //                                             System.err.println("ready:");
 //                                             base.ready.printStackTrace();
 //                                     }
-                                       System.err.println("asd");
+                                       new Exception("Timeout waiting for request to complete: " + entry.getOriginalRequest().toString()).printStackTrace();
+                                       throw new DatabaseException("Timeout waiting for request to complete.");
+                                       //System.err.println("asd");
                                        //base.getQuery().recompute(null, null, entry);
                                }
                        } catch (InterruptedException e) {
@@ -796,6 +808,19 @@ public class QueryCacheBase {
                
        }; 
 
+    protected static InternalProcedure<ObjectResourceIdMap<String>> emptyChildMapProcedure = new InternalProcedure<ObjectResourceIdMap<String>>() {
+
+               @Override
+               public void execute(ReadGraphImpl graph, ObjectResourceIdMap<String> i) {
+               }
+
+               @Override
+               public void exception(ReadGraphImpl graph, Throwable throwable) {
+               }
+               
+       }; 
+
+       
        
        protected static IntProcedure emptyIntProcedure = new IntProcedure() {
                
@@ -878,6 +903,7 @@ public class QueryCacheBase {
     
     protected static InternalProcedure<Integer> emptyProcedureURIToResource = emptyIntegerProcedure;
     protected static InternalProcedure<TObjectIntHashMap<String>> emptyProcedureNamespaceIndex = emptyNamespaceProcedure;
+    protected static InternalProcedure<ObjectResourceIdMap<String>> emptyProcedureChildMap = emptyChildMapProcedure;
     protected static InternalProcedure<RelationInfo> emptyProcedureRelationInfoQuery = emptyRelationInfoProcedure;
 
     protected static AsyncProcedure emptyProcedureReadEntry = emptyAsyncProcedure;
@@ -956,11 +982,12 @@ public class QueryCacheBase {
     static class IntSetWrapper implements IntProcedure {
        
        private IntProcedure procedure;
-       private IntSet result = new IntSet();
+       final private IntSet result;
        private Throwable throwable = null;
        
-       IntSetWrapper(IntProcedure procedure) {
+       IntSetWrapper(ReadGraphImpl graph, IntProcedure procedure) {
                this.procedure = procedure;
+               result = new IntSet(graph.processor.querySupport);
        }
 
                @Override
@@ -1037,53 +1064,77 @@ public class QueryCacheBase {
         return wrap.get();
     }
 
-    public static byte[] resultValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<byte[]> procedure) throws DatabaseException {
-       InternalProcedureWrapper<byte[]> wrap = new InternalProcedureWrapper<>(procedure);
+    public static byte[] resultValueQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<byte[]> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerValueQuery(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static RelationInfo resultRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<RelationInfo> procedure) throws DatabaseException {
-       InternalProcedureWrapper<RelationInfo> wrap = new InternalProcedureWrapper<>(procedure);
+    public static RelationInfo resultRelationInfoQuery(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<RelationInfo> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerRelationInfoQuery(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static IntSet resultSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(procedure);
+    public static IntSet resultSuperRelations(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerSuperRelations(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static IntSet resultSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(procedure);
+    public static IntSet resultSuperTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerSuperTypes(graph, r, parent, listener, wrap);
         return wrap.get();
     }
     
-    public static IntSet resultTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(procedure);
+    public static IntSet resultTypes(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerTypes(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static IntSet resultPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(procedure);
+    public static IntSet resultPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerPredicates(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static IntSet resultDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener, InternalProcedure<IntSet> procedure) throws DatabaseException {
-       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(procedure);
+    public static IntSet resultDirectPredicates(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<IntSet> wrap = new InternalProcedureWrapper<>(null);
         QueryCache.runnerDirectPredicates(graph, r, parent, listener, wrap);
         return wrap.get();
     }
 
-    public static IntArray resultAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener, TripleIntProcedure procedure) throws DatabaseException {
-       TripleIntProcedureWrapper wrap = new TripleIntProcedureWrapper(procedure);
+    public static IntArray resultAssertedStatements(ReadGraphImpl graph, int r1, int r2, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       TripleIntProcedureWrapper wrap = new TripleIntProcedureWrapper(null);
         QueryCache.runnerAssertedStatements(graph, r1, r2, parent, listener, wrap);
         return wrap.get();
     }
 
+    public static Integer resultURIToResource(ReadGraphImpl graph, String id, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<Integer> wrap = new InternalProcedureWrapper<Integer>(null);
+        QueryCache.runnerURIToResource(graph, id, parent, listener, wrap);
+        return wrap.get();
+    }
+
+    public static ObjectResourceIdMap<String> resultChildMap(ReadGraphImpl graph, int r, CacheEntry parent, ListenerBase listener) throws DatabaseException {
+       InternalProcedureWrapper<ObjectResourceIdMap<String>> wrap = new InternalProcedureWrapper<ObjectResourceIdMap<String>>(null);
+        QueryCache.runnerChildMap(graph, r, parent, listener, wrap);
+        return wrap.get();
+    }
+
+    static boolean shouldCache(QueryProcessor processor, int r) {
+       return processor.isImmutable(r);
+    }
+    
+    static boolean shouldCache(QueryProcessor processor, int r, int r2) {
+       return processor.isImmutable(r);
+    }
+
+    static boolean shouldCache(QueryProcessor processor, Object o) {
+       return false;
+    }
+    
 }
 
index 965f1e39f41fb1dc4d99000d533c03dde6c21da3..8ea760b75c4a8774a2454f6b2393aed8a388975d 100644 (file)
@@ -29,10 +29,11 @@ class QueryCollectorImpl implements QueryProcessor.QueryCollector {
         */
        boolean propagate = true;
        
-       
        private static final int COLLECT_N = 1000;
        
+       private long allowance = 100;
        private long spent = 0;
+       private long collectionCounter = 0;
        
        QueryCollectorImpl(QueryProcessor queryProcessor, QueryCollectorSupport support) {
                this.queryProcessor = queryProcessor;
@@ -41,14 +42,28 @@ class QueryCollectorImpl implements QueryProcessor.QueryCollector {
        
        @Override
        public void collect(int youngTarget, int allowedTimeInMs) {
-
+               
                long start = System.nanoTime();
 
                // Refresh current size
                int size = support.calculateCurrentSize();
+               
+//             if(collectionCounter > allowance) {
+//                     collectionCounter = 0;
+//                     allowance = (allowance * 1100) / 1000;
+//             }
+               
                int bound = queryProcessor.boundQueries;
                int young = size - bound;
                int youngPct = size > 0 ? 100*young / size : 0;
+
+               // System.err.println("Collect size = " + size + " bound=" + bound + " allowance=" + allowance);
+               
+               // Allowance maintains a reasonable set of queries 
+               if(size < allowance) return;
+               
+               // No need to collect anything if the amount of free queries is small compared to the amount of bound queries
+               if(youngPct < youngTarget) return;
                
                // Initialize support for new run
                // If support returns 0 we are starting from 0
@@ -182,6 +197,7 @@ class QueryCollectorImpl implements QueryProcessor.QueryCollector {
                                support.remove();
                                propagate = true;
                                moreAll++;
+                               collectionCounter++;
                                doneAll = false;
                                return true;
                        }
index a6c987a9d0e10e0b2beda36f7a571a8633527063..a54484a6566e623ae9fd4c1ea6b3dac63060572e 100644 (file)
@@ -16,6 +16,7 @@ import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -279,10 +280,29 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        public boolean resume(ReadGraphImpl graph) {
                return executors[0].runSynchronized();
        }
+       
+       //private WeakReference<GarbageTracker> garbageTracker;
+       
+       private class GarbageTracker    {
+               
+               @Override
+               protected void finalize() throws Throwable {
+                       
+//                     System.err.println("GarbageTracker");
+//                     
+//                     garbageTracker = new WeakReference<GarbageTracker>(new GarbageTracker());
+                       
+                       super.finalize();
+                       
+               }
+               
+       }
 
        public QueryProcessor(final int threads, QuerySupport core, Set<Thread> threadSet)
                        throws DatabaseException {
 
+               //garbageTracker = new WeakReference<GarbageTracker>(new GarbageTracker());
+               
                THREADS = threads;
                THREAD_MASK = threads - 1;
 
@@ -2324,11 +2344,8 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        
        @Override
        final public IntSet getPredicates(final ReadGraphImpl impl, final Resource subject) throws Throwable {
-               
-               return QueryCacheBase.resultPredicates(impl, querySupport.getId(subject), impl.parent, null, null); 
-
+               return QueryCacheBase.resultPredicates(impl, querySupport.getId(subject), impl.parent, null); 
        }
-       
 
        @Override
        final public void forEachStatement(final ReadGraphImpl impl, final Resource subject,
@@ -3424,7 +3441,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 
                assert(subject != null);
                
-               return QueryCacheBase.resultTypes(impl, querySupport.getId(subject), impl.parent, null, null);
+               return QueryCacheBase.resultTypes(impl, querySupport.getId(subject), impl.parent, null);
 
        }
 
@@ -3647,17 +3664,18 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
        }
 
        final public byte[] getValue(final ReadGraphImpl impl, final int subject) throws DatabaseException {
-               return QueryCache.resultValueQuery(impl, subject, impl.parent, null, null); 
+               return QueryCache.resultValueQuery(impl, subject, impl.parent, null); 
        }
 
        @Override
-       final public byte[] forValue(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<byte[]> procedure) {
+       final public void forValue(final ReadGraphImpl impl, final Resource subject, final AsyncProcedure<byte[]> procedure) {
 
                assert(subject != null);
+               assert(procedure != null);
 
                int sId = querySupport.getId(subject);
 
-               if(procedure != null) {
+//             if(procedure != null) {
                
                        final ListenerBase listener = getListenerBase(procedure);
 
@@ -3699,23 +3717,18 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
 //                     else impl.state.barrier.inc(null, null);
 
                        try {
-                               return QueryCacheBase.resultValueQuery(impl, sId, impl.parent, listener, ip);
+                               QueryCache.runnerValueQuery(impl, sId, impl.parent, listener, ip);
                        } catch (DatabaseException e) {
-                               Logger.defaultLogError(e);
-                       } 
-                       
-
-               } else {
+                               throw new IllegalStateException("Internal error");
+                       }
 
-                       try {
-                               return QueryCacheBase.resultValueQuery(impl, sId, impl.parent, null, null);
-                       } catch (DatabaseException e) {
-                               Logger.defaultLogError(e);
-                       } 
-                       
-               }
-               
-               throw new IllegalStateException("Internal error");
+//             } else {
+//
+//                     return QueryCacheBase.runnerValueQuery(impl, sId, impl.parent, null, null);
+//                     
+//             }
+//             
+//             throw new IllegalStateException("Internal error");
 
        }
 
@@ -3973,7 +3986,7 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                final ListenerBase listener = getListenerBase(procedure);
 
                try {
-                       IntSet result = QueryCache.resultDirectPredicates(impl, querySupport.getId(subject), impl.parent, listener,QueryCache.emptyProcedureDirectPredicates);
+                       IntSet result = QueryCache.resultDirectPredicates(impl, querySupport.getId(subject), impl.parent, listener);
                        procedure.execute(impl, !result.isEmpty());
                } catch (DatabaseException e) {
                        procedure.exception(impl, e);
index 667d2f1256917551ecff8bc0f68ff6501528cccb..d55768aaa1a04cea220b146882cdf614e0353fd9 100644 (file)
@@ -78,8 +78,8 @@ final public class RelationInfoQuery extends UnaryQuery<InternalProcedure<Relati
            final int superRelationOf = provider.getSuperrelationOf();
         assert(superRelationOf != 0);
         
-        IntSet direct = QueryCache.resultDirectPredicates(graph, r, entry, null, QueryCache.emptyProcedureDirectPredicates);
-        IntSet types = QueryCache.resultTypes(graph, r, entry, null, QueryCache.emptyProcedureTypes);
+        IntSet direct = QueryCache.resultDirectPredicates(graph, r, entry, null);
+        IntSet types = QueryCache.resultTypes(graph, r, entry, null);
         
        computeAssertions(graph, r, !direct.contains(superRelationOf), types.contains(graph.processor.getFunctionalRelation()), entry, procedure);
         
index 121653b0faa799ec3b4cadc153dfd481ef5a513d..e1a106aaac540cc019262d03f1688194bbd23fd2 100644 (file)
@@ -97,7 +97,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
             @Override
             public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
                 if(result == null) {
-                       result = QueryCache.resultAssertedStatements(graph, type, r2, entry, null, NOPT);
+                       result = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
                 } else {
                        if (first) {
                                IntArray ia = result;
@@ -107,7 +107,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                                }
                                first = false;
                        }
-                       IntArray ia = QueryCache.resultAssertedStatements(graph, type, r2, entry, null, NOPT);
+                       IntArray ia = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
                        if(ia.data != null) {
                                for(int i = 0;i < ia.sizeOrData ; i+=3) addStatement(ia.data[i],ia.data[i+1],ia.data[i+2]);
                        }
@@ -170,7 +170,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                
                        IntSet candidateIs = null;
                        try {
-                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, entry, null, NOP);
+                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, entry, null);
                        } catch (DatabaseException e) {
                                if(entry != null) entry.except(e);
                                procedure.exception(graph, e);
@@ -202,7 +202,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                                
                                        IntSet nextIs = null;
                                        try {
-                                               nextIs = QueryCache.resultSuperTypes(graph, nextS, entry, null, NOP);
+                                               nextIs = QueryCache.resultSuperTypes(graph, nextS, entry, null);
                                        } catch (DatabaseException e) {
                                                if(entry != null) entry.except(e);
                                                procedure.exception(graph, e);
@@ -322,7 +322,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
             final AtomicBoolean found = new AtomicBoolean(false);
             
             // Note! The dependency is intentionally cut!
-            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null, QueryCache.emptyProcedureDirectPredicates);
+            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
                 
                 @Override
@@ -554,7 +554,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
         } else {
 
             // Note! The dependency is intentionally cut!
-            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null, QueryCache.emptyProcedureDirectPredicates);
+            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
                 
                 @Override
@@ -599,7 +599,7 @@ final public class Statements extends CollectionBinaryQuery<TripleIntProcedure>
 
                         try {
                             
-                            IntSet result = QueryCache.resultSuperRelations(graph, pred2, entry, null, null);
+                            IntSet result = QueryCache.resultSuperRelations(graph, pred2, entry, null);
                             if(result.contains(r2)) {
 
                                 inc();
index 479bd71cd4d7bb6d48303c3c38688690678f379e..0f076fb34ddb13823ea08389e78def15df14ee30 100644 (file)
@@ -37,7 +37,6 @@ final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>>
        }
        
        static int histoCounter = 0;
-       static IntSet EMPTY_SET = new IntSet();
     static int counter = 0;
     
     class Koss {
@@ -121,8 +120,8 @@ final public class SuperRelations extends UnaryQuery<InternalProcedure<IntSet>>
 
            if(size == 0) {
 
-               addOrSet(graph, EMPTY_SET, processor);
-               proc.execute(graph, EMPTY_SET);
+               addOrSet(graph, IntSet.EMPTY, processor);
+               proc.execute(graph, IntSet.EMPTY);
 
            } else if (size == 1) {
 
index 96afa8c4f586bd8fb83135e4eca2c4803542c3f8..155bc209bf27d2edc1a4d771f14d74047d1eeebd 100644 (file)
@@ -38,10 +38,6 @@ final public class Types extends UnaryQuery<InternalProcedure<IntSet>> {
 
        public static void computeForEach(final ReadGraphImpl graph, int id, Types entry, final InternalProcedure<IntSet> procedure) throws DatabaseException {
 
-               if(entry != null)
-                       if(entry.isReady())
-                               System.err.println("asd");
-               
                assert(procedure != null);
 
                QueryProcessor processor = graph.processor;
@@ -56,7 +52,10 @@ final public class Types extends UnaryQuery<InternalProcedure<IntSet>> {
                                @Override
                                public void execute(ReadGraphImpl graph, IntSet types) throws DatabaseException {
 
-                                       if(entry != null) entry.addOrSet(graph, types, processor);
+                                       if(entry != null) {
+                                               entry.addOrSet(graph, types, processor);
+                                               entry.finish();
+                                       }
                                        procedure.execute(graph, types);
 
                                }
@@ -67,6 +66,8 @@ final public class Types extends UnaryQuery<InternalProcedure<IntSet>> {
                                }
 
                        });
+                       
+                       return;
 
                }
                
@@ -103,9 +104,7 @@ final public class Types extends UnaryQuery<InternalProcedure<IntSet>> {
             @Override
             public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
                 
-               synchronized(result) {
-                       result.add(i);
-               }
+               result.add(i);
                 
                 inc();
 
index 5a44fc2eb608a273139501ac827a264265f1f5d3..78ae0d12d0ba0a147ca79b7ac65f894952e2bf47 100644 (file)
 package org.simantics.db.impl.query;
 
 import org.simantics.databoard.util.URIStringUtils;
+import org.simantics.db.ObjectResourceIdMap;
 import org.simantics.db.common.exception.DebugException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.procedure.InternalProcedure;
-import org.simantics.db.procedure.ListenerBase;
-
-import gnu.trove.map.hash.TObjectIntHashMap;
 
 public class URIToResource extends StringQuery<InternalProcedure<Integer>> {
 
@@ -30,38 +28,6 @@ public class URIToResource extends StringQuery<InternalProcedure<Integer>> {
     final public void removeEntry(QueryProcessor provider) {
        provider.cache.remove(this);
     }
-
-    private static void lookup(ReadGraphImpl graph, final URIToResource entry, final InternalProcedure<Integer> procedure, final String namespace, final String name) throws DatabaseException {
-        
-       QueryCache.runnerNamespaceIndex(graph, namespace, entry, null, new InternalProcedure<TObjectIntHashMap<String>>() {
-
-            @Override
-            public void execute(ReadGraphImpl graph, TObjectIntHashMap<String> index) throws DatabaseException {
-
-                if(index != null) {
-                    int result = index.get(name);
-                    if(result != 0) {
-                        if(entry != null) entry.addOrSet(graph, graph.processor, result);
-                        procedure.execute(graph, result);
-                        return;
-                    }
-                }
-                
-                Integer zero = 0;
-                if(entry != null) entry.addOrSet(graph, graph.processor, zero);
-                procedure.execute(graph, zero);
-
-            }
-
-            @Override
-            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                if(entry != null) entry.except(t);
-                procedure.exception(graph, t);
-            }
-
-        });
-
-    }
     
     @Override
     public Object compute(ReadGraphImpl graph, final InternalProcedure<Integer> procedure) throws DatabaseException {
@@ -81,9 +47,24 @@ public class URIToResource extends StringQuery<InternalProcedure<Integer>> {
             
             final String[] parts = URIStringUtils.splitURI(id);
             if (parts != null) {
-                lookup(graph, entry, procedure, parts[0], parts[1]);
+
+               Integer parentId = QueryCache.resultURIToResource(graph, parts[0], entry, null);
+               ObjectResourceIdMap<String> map = QueryCache.resultChildMap(graph, parentId, entry, null);
+               if(map == null) {
+                       procedure.execute(graph, 0);
+                       if(entry != null) entry.addOrSet(graph, graph.processor, 0);
+               } else {
+                       int result = map.getId(URIStringUtils.unescape(parts[1]));
+                       if(entry != null) entry.addOrSet(graph, graph.processor, result);
+                       procedure.execute(graph, result);
+               }
+               
             } else {
-                lookup(graph, entry, procedure, "http://", id.replaceFirst("http://", ""));
+               
+               DatabaseException e = new DatabaseException("No URI for " + id);
+               if(entry != null) entry.except(e);
+               procedure.exception(graph, e);
+                
             }
 
         }
index 9e85e9a1bc15ab584f3522933b012ae60c468be2..fe60665610c859fe05b17935511ed8abb312790d 100644 (file)
                        class="org.simantics.db.layer0.adapter.impl.ModelImportAdvisorFactory">
                </resource>
        </target>
+
+       <target interface="org.simantics.db.ExternalValue">
+               <type uri="http://www.simantics.org/Layer0-0.0/ExternalValue"
+                       class="org.simantics.db.layer0.adapter.ReflectionExternalValue">
+               </type>
+               <type uri="http://www.simantics.org/Layer0-0.0/Function"
+                       class="org.simantics.db.layer0.adapter.ReflectionExternalValue">
+               </type>
+       </target>
        
+       <target interface="org.simantics.db.ExternalValue">
+               <resource uri="http://www.simantics.org/Layer0-0.0/Functions/computeExpression"
+                       class="org.simantics.db.layer0.adapter.SCLExternalValue">
+               </resource>
+       </target>
+
 </adapters>
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ReflectionExternalValue.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ReflectionExternalValue.java
new file mode 100644 (file)
index 0000000..6bc6afb
--- /dev/null
@@ -0,0 +1,25 @@
+package org.simantics.db.layer0.adapter;
+
+import org.simantics.db.ExternalValue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.scl.reflection.ReflectionUtils;
+import org.simantics.scl.reflection.ValueNotFoundException;
+
+public class ReflectionExternalValue implements ExternalValue {
+
+       @Override
+       public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException {
+               
+               try {
+                       return (T)ReflectionUtils.getValue(graph.getURI(resource)).getValue();
+               } catch(ValueNotFoundException e) {
+                       throw new DatabaseException(e);
+               } catch(ClassCastException e) {
+                       throw new DatabaseException(e);
+               }
+               
+       }
+
+}
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/SCLExternalValue.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/SCLExternalValue.java
new file mode 100644 (file)
index 0000000..12e950c
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.db.layer0.adapter;
+
+import org.simantics.db.ConverterExternalValue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.scl.CompileValueRequest;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.reflection.ReflectionUtils;
+import org.simantics.scl.reflection.ValueNotFoundException;
+import org.simantics.scl.runtime.function.Function1;
+
+public class SCLExternalValue implements ConverterExternalValue {
+
+       @Override
+       public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException {
+               try {
+                       return (T)ReflectionUtils.getValue(Layer0.URIs.Functions_computeExpression).getValue();
+               } catch (ValueNotFoundException e) {
+                       throw new DatabaseException(e);
+               }
+       }
+
+       @Override
+       public Function1 getFunction(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+               return CompileValueRequest.compile(graph, s, o, p);
+       }
+
+}
index 3b819cbabf5ab609188c21417ee8a19f8cf75e3a..ca81e163044b943d8fa034abd759edc0d5c684ca 100644 (file)
@@ -1,7 +1,5 @@
 package org.simantics.db.layer0.request;
 
-import gnu.trove.map.hash.THashMap;
-
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Map;
@@ -11,7 +9,6 @@ import org.simantics.databoard.Bindings;
 import org.simantics.databoard.accessor.reference.ChildReference;
 import org.simantics.databoard.accessor.reference.IndexReference;
 import org.simantics.databoard.accessor.reference.NameReference;
-import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.type.Datatype;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
@@ -24,6 +21,8 @@ import org.simantics.layer0.Layer0;
 import org.simantics.operation.Layer0X;
 import org.simantics.utils.datastructures.Pair;
 
+import gnu.trove.map.hash.THashMap;
+
 final public class PropertyInfoRequest extends ResourceRead<PropertyInfo> {
 
        public PropertyInfoRequest(Resource resource) {
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionAnalysisRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/AbstractExpressionAnalysisRequest.java
new file mode 100644 (file)
index 0000000..2cb0501
--- /dev/null
@@ -0,0 +1,240 @@
+package org.simantics.db.layer0.scl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.request.Read;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.ESimpleLet;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.expressions.Variable;
+import org.simantics.scl.compiler.environment.AbstractLocalEnvironment;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.LocalEnvironment;
+import org.simantics.scl.compiler.errors.CompilationError;
+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.TCon;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.compiler.types.Types;
+import org.simantics.scl.compiler.types.exceptions.MatchException;
+import org.simantics.scl.compiler.types.kinds.Kinds;
+import org.simantics.scl.compiler.types.util.MultiFunction;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.utils.datastructures.Pair;
+
+import gnu.trove.map.hash.THashMap;
+
+/**
+ * <p>This is a base implementation for compiling expressions stored into 
+ * graph. It provides a skeleton and a set of methods that must be
+ * implemented to get a concrete compilation request.
+ * 
+ * <p>The request returns an SCL function with type {@code EvaluationContext -> Result}
+ * where {@code EvaluationContext} is the type given by {@link #getContextVariableType()}
+ * and {@code Result} is the type of the expression that can be optionally restricted
+ * by {@link #getExpectedType(ReadGraph, AbstractExpressionCompilationContext)}.
+ * 
+ * <p>Compilation calls {@link #getCompilationContext(ReadGraph)} to read all information
+ * that is needed about the context of the resource during compilation. The result must
+ * extend the type {@link AbstractExpressionCompilationContext} including at least information about 
+ * {@link RuntimeEnvironment}.
+ * 
+ * <p>Compilation calls {@link #getVariableAccessExpression(ReadGraph, AbstractExpressionCompilationContext, Variable, String)}
+ * to get access to local environment. The method may return null if the variable is not defined.
+ * 
+ * @author Hannu Niemist&ouml;
+ *
+ * @param <Context>
+ */
+public abstract class AbstractExpressionAnalysisRequest<CompilationContext extends AbstractExpressionCompilationContext,EvaluationContext>
+implements Read<ExpressionAnalysis<EvaluationContext>> {
+
+    protected static final Type RESOURCE = Types.con("Simantics/DB", "Resource");
+    protected static final Type VARIABLE = Types.con("Simantics/Variables", "Variable");
+    protected static Name PROPERTY_VALUE = Name.create("Simantics/Variables", "propertyValue");
+    protected static Name VARIABLE_PARENT = Name.create("Simantics/Variables", "variableParent");
+    protected static Name FROM_DOUBLE = Name.create("Prelude", "fromDouble");
+    protected static Name TO_DOUBLE = Name.create("Prelude", "toDouble");
+    protected static Name FROM_DYNAMIC = Name.create("Prelude", "fromDynamic");
+
+    private static final Type DEFAULT_EXPECTED_EFFECT = Types.union(new Type[] {Types.PROC, Types.READ_GRAPH});
+
+    /**
+     * Returns the expression that will be compiled in textual form.
+     */
+    protected abstract String getExpressionText(ReadGraph graph) throws DatabaseException;
+    /**
+     * Returns the context that is used for the compilation of the expression. The context
+     * contains information about available constants and variables.
+     */
+    protected abstract CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException;
+    /**
+     * This should return the SCL type corresponding to generic type parameter {@code EvaluationContext}.
+     */
+    protected abstract Type getContextVariableType();
+    /**
+     * Returns <code>null</code>, if variable {@code name} is not defined.
+     */
+    protected abstract Expression getVariableAccessExpression(ReadGraph graph,
+            CompilationContext context, Variable contextVariable, String name) throws DatabaseException;
+
+    protected Type getExpectedType(ReadGraph graph, CompilationContext context) throws DatabaseException {
+        return Types.metaVar(Kinds.STAR);
+    }
+
+    protected Type getExpectedEffect(ReadGraph graph, CompilationContext context) throws DatabaseException {
+        return DEFAULT_EXPECTED_EFFECT;
+    }
+    
+    private ExpressionEvaluator prepareEvaluator(final ReadGraph graph, final CompilationContext context, Type expectedType) throws DatabaseException {
+        final Variable contextVariable = new Variable("context", getContextVariableType());
+        LocalEnvironment localEnvironment = new AbstractLocalEnvironment() {
+            THashMap<String,Pair<Variable,Expression>> precalculatedVariables = new THashMap<String,Pair<Variable,Expression>>(); 
+            @Override
+            public Expression resolve(Environment environment, String localName) {
+                Pair<Variable,Expression> precalculatedVariable = precalculatedVariables.get(localName);
+                if(precalculatedVariable == null) {
+                    try {
+                        Expression value = getVariableAccessExpression(graph, context, contextVariable, localName);
+                        if(value == null)
+                            return null;
+                        Variable variable = new Variable(localName);
+                        precalculatedVariable = Pair.make(variable, value);
+                        precalculatedVariables.put(localName, precalculatedVariable);
+                    } catch (DatabaseException e) {
+                        throw new RuntimeDatabaseException(e);
+                    }
+                }
+                return new EVariable(precalculatedVariable.first);
+            }
+            @Override
+            public Expression preDecorateExpression(Expression expression) {
+                for(Pair<Variable,Expression> precalculatedVariable : precalculatedVariables.values())
+                    expression = new ESimpleLet(precalculatedVariable.first, precalculatedVariable.second, expression);
+                return expression;
+            }
+            @Override
+            protected Variable[] getContextVariables() {
+                return new Variable[] { contextVariable };
+            }
+        };
+
+        String expressionText = getExpressionText(graph);
+        return new ExpressionEvaluator(context.runtimeEnvironment, expressionText)
+            .localEnvironment(localEnvironment)
+            .expectedType(expectedType)
+            .parseAsBlock(parseAsBlock());
+    }
+    
+    protected boolean parseAsBlock() {
+        return false;
+    }
+    
+    private Function1<EvaluationContext, Object> eval(ExpressionEvaluator evaluator, ReadGraph graph) throws DatabaseException {
+        Object oldGraph = SCLContext.getCurrent().put("graph", graph);
+        try {
+            return (Function1<EvaluationContext,Object>)evaluator.eval();
+        } catch(RuntimeDatabaseException e) {
+            e.printStackTrace();
+            if(e.getCause() instanceof DatabaseException)
+                throw (DatabaseException)e.getCause();
+            else
+                throw e;
+        } catch (SCLExpressionCompilationException e) {
+            StringBuilder b = new StringBuilder();
+            b.append("Couldn't compile '");
+            b.append(evaluator.getExpressionText());
+            b.append("':\n");
+            StringBuilder b2 = new StringBuilder();
+            for(CompilationError error : e.getErrors()) {
+                b2.append(error.description);
+                b2.append('\n');
+            }
+            System.err.println(b.toString() + b2.toString());
+            throw new SCLDatabaseException(b.toString()+b2.toString(), b2.toString(), e.getErrors());
+        } catch(Throwable e) {
+            // Should not happen!
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        } finally {
+            SCLContext.getCurrent().put("graph", oldGraph);
+        }
+    }
+
+    public List<TCon> getExpressionEffects(final ReadGraph graph) throws DatabaseException {
+        CompilationContext context = getCompilationContext(graph);
+        Type type = Types.metaVar(Kinds.STAR);
+        eval(prepareEvaluator(graph, context, type), graph);
+
+        try {
+            MultiFunction mfun = Types.matchFunction(type, 1);
+            ArrayList<TCon> concreteEffects = new ArrayList<TCon>();
+            mfun.effect.collectConcreteEffects(concreteEffects);
+            return concreteEffects;
+        } catch(MatchException e) {
+            // Should not happen!
+            e.printStackTrace();
+            throw new RuntimeException(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public ExpressionAnalysis<EvaluationContext> perform(final ReadGraph graph) throws DatabaseException {
+        CompilationContext context = getCompilationContext(graph);
+        Function1<EvaluationContext,Object> fn = eval(prepareEvaluator(graph, context, getExpectedType(graph, context)), graph);
+        return getAnalysis(context, fn);
+    }
+    
+    protected ExpressionAnalysis<EvaluationContext> getAnalysis(CompilationContext context, Function1<EvaluationContext,Object> fn) {
+       return new ExpressionAnalysis(fn, Collections.emptySet());
+    }
+
+    protected static Expression getProperty(Environment environment, Expression variable, String propertyName, Type type) {
+        return new EApply(
+                new EConstant(environment.getValue(FROM_DYNAMIC), type),
+                new EApply(
+                        new EConstant(environment.getValue(PROPERTY_VALUE), Types.DYNAMIC),
+                        variable,
+                        new ELiteral(new StringConstant(propertyName))));
+    }
+
+    protected static Expression getPropertyFlexible(Environment environment, Expression variable, String propertyName, Type type) {
+        return makeTypeFlexible(environment, getProperty(environment, variable, propertyName, type), type);
+    }
+
+    protected static Expression makeTypeFlexible(Environment environment, Expression base, Type originalType) {
+        if(originalType.equals(Types.DOUBLE))
+            return new EApply(
+                    new EConstant(environment.getValue(FROM_DOUBLE)),
+                    base);
+        else if(originalType.equals(Types.FLOAT))
+            return new EApply(
+                    new EConstant(environment.getValue(FROM_DOUBLE)),
+                    new EApply(
+                            new EConstant(environment.getValue(TO_DOUBLE), Types.FLOAT),
+                            base));
+        else
+            return base;
+    }
+    
+    protected static String resolveExpectedValueType(ReadGraph graph, org.simantics.db.layer0.variable.Variable context) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        String valueType = graph.getPossibleRelatedValue(context.getPredicateResource(graph), L0.RequiresValueType, Bindings.STRING);
+        return valueType;
+    }
+}
index d40f82d4dc1219055b83fe4c722edff93703d63e..21758a2e559d4191e2879a9a1baa0952edcc6449 100644 (file)
@@ -5,6 +5,7 @@ import java.util.List;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.RuntimeDatabaseException;
 import org.simantics.db.request.Read;
@@ -226,9 +227,9 @@ implements Read<Function1<EvaluationContext,Object>> {
             return base;
     }
     
-    protected static String resolveExpectedValueType(ReadGraph graph, org.simantics.db.layer0.variable.Variable context) throws DatabaseException {
+    protected static String resolveExpectedValueType(ReadGraph graph, Resource predicate) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
-        String valueType = graph.getPossibleRelatedValue(context.getPredicateResource(graph), L0.RequiresValueType, Bindings.STRING);
-        return valueType;
+        return graph.getPossibleRelatedValue(predicate, L0.RequiresValueType, Bindings.STRING);
     }
+    
 }
index e1804d790fc327c6713cc5e7bdf41b78b84c8b91..34a312003ab88b3e839a78541a8e9ee54c8c6d3a 100644 (file)
@@ -66,6 +66,23 @@ public class CompileValueRequest extends AbstractExpressionCompilationRequest<Co
         }
     }
 
+    public static Function1<Variable,Object> compile(ReadGraph graph, Resource component, Resource literal, Resource predicate) throws DatabaseException {
+        SCLContext sclContext = SCLContext.getCurrent();
+        Object oldGraph = sclContext.get("graph");
+        try {
+            Function1<Variable,Object> exp = graph.syncRequest(new CompileValueRequest(component, literal, predicate),
+                    TransientCacheListener.<Function1<Variable,Object>>instance());
+            sclContext.put("graph", graph);
+            return exp;
+        } catch (DatabaseException e) {
+            throw (DatabaseException)e;
+        } catch (Throwable t) {
+            throw new DatabaseException(t);
+        } finally {
+            sclContext.put("graph", oldGraph);
+        }
+    }
+
     @Override
     protected String getExpressionText(ReadGraph graph)
             throws DatabaseException {
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/ExpressionAnalysis.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/scl/ExpressionAnalysis.java
new file mode 100644 (file)
index 0000000..e09389d
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.db.layer0.scl;
+
+import java.util.Set;
+
+import org.simantics.scl.runtime.function.Function1;
+
+public class ExpressionAnalysis<EvaluationContext> {
+
+       final private Set<String> consumed;
+       final private Function1<EvaluationContext,Object> fn;
+       
+       public ExpressionAnalysis(Function1<EvaluationContext,Object> fn, Set<String> consumed) {
+               this.fn = fn;
+               this.consumed = consumed;
+       }
+       
+       public boolean isConsumed(String name) {
+               return consumed.contains(name);
+       }
+       
+       public Set<String> getConsumed() {
+               return consumed;
+       }
+       
+       public Function1<EvaluationContext,Object> getFunction() {
+               return fn;
+       }
+       
+}
index 5b6aa082001a4ae2be5f0547c3e983db9569c508..52ecbc705774b8fa1edc75d2da34923b0129778f 100644 (file)
@@ -18,9 +18,9 @@ abstract public class VariableMapImpl implements VariableMap {
        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
                
        Map<String,Variable> all = getVariables(graph, context, null);
-       if(all.isEmpty()) return all;
+    
+       for(Map.Entry<String, Variable> entry : all.entrySet()) {       if(all.isEmpty()) return all;
        
-       for(Map.Entry<String, Variable> entry : all.entrySet()) {
                Set<String> classifications = entry.getValue().getClassifications(graph);
                if(classifications.contains(classification)) {
                        if(map == null) map = new HashMap<String,Variable>();
index c8560bad89ae1257c2f0987a722f4e0fa962b7d5..8b4df608f2eda9755f9636be2d5d79903d3d4ec1 100644 (file)
@@ -28,11 +28,8 @@ import gnu.trove.iterator.TIntIterator;
 import gnu.trove.list.array.TIntArrayList;
 import gnu.trove.map.hash.TIntIntHashMap;
 import gnu.trove.map.hash.TIntObjectHashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
 import gnu.trove.procedure.TIntObjectProcedure;
 import gnu.trove.procedure.TIntProcedure;
-import gnu.trove.procedure.TObjectIntProcedure;
-import gnu.trove.procedure.TObjectProcedure;
 import gnu.trove.set.hash.TIntHashSet;
 
 public class CollectionSupportImpl implements CollectionSupport {
@@ -117,196 +114,6 @@ public class CollectionSupportImpl implements CollectionSupport {
                return new IntResourceMap(session);
        }
 
-       static final class ObjectResourceMap<T> implements Map<T, Resource> {
-
-               final private SessionImplSocket session;
-               final private TObjectIntHashMap<T> backend;
-
-               ObjectResourceMap(SessionImplSocket session) {
-                       this.session = session;
-                       backend = new TObjectIntHashMap<T>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
-               }
-
-               ObjectResourceMap(SessionImplSocket session, int capacity) {
-                       this.session = session;
-                       backend = new TObjectIntHashMap<T>(capacity, Constants.DEFAULT_LOAD_FACTOR, 0);
-               }
-
-               @Override
-               public int size() {
-                       return backend.size();
-               }
-               @Override
-               public boolean isEmpty() {
-                       return backend.isEmpty();
-               }
-
-               @Override
-               public boolean containsKey(Object key) {
-                       return backend.contains(key);
-               }
-
-               @Override
-               public boolean containsValue(Object value) {
-                       ResourceImpl impl = (ResourceImpl) value;
-                       return backend.containsValue(impl.id);
-               }
-
-               @Override
-               public Resource get(Object key) {
-                       try {
-                               int result = backend.get(key);
-                               if (result == 0)
-                                       return null;
-                               return session.getResourceByKey(result);
-                       } catch (ResourceNotFoundException e) {
-                               e.printStackTrace();
-                       }
-                       return null;
-               }
-
-               @Override
-               public Resource put(T key, Resource value) {
-                       ResourceImpl impl = (ResourceImpl) value;
-                       int i = backend.put(key, impl.id);
-                       if (i == 0)
-                               return null;
-                       else
-                               try {
-                                       return session.getResourceByKey(i);
-                               } catch (ResourceNotFoundException e) {
-                                       e.printStackTrace();
-                               }
-                       return null;
-               }
-
-               @Override
-               public Resource remove(Object key) {
-                       throw new UnsupportedOperationException("remove not supported, structure is immutable");
-               }
-
-               @Override
-               public void putAll(Map<? extends T, ? extends Resource> map) {
-                       @SuppressWarnings("unchecked")
-                       ObjectResourceMap<T> other = (ObjectResourceMap<T>) map;
-                       other.backend.forEachEntry(new TObjectIntProcedure<T>() {
-
-                               @Override
-                               public boolean execute(T a, int b) {
-                                       backend.put(a, b);
-                                       return true;
-                               }
-                       });
-               }
-
-               @Override
-               public void clear() {
-                       throw new UnsupportedOperationException("clear not supported, structure is immutable");
-               }
-
-               @Override
-               public Set<T> keySet() {
-                       final Set<T> result = new HashSet<T>();
-                       backend.forEach(new TObjectProcedure<T>() {
-
-                               @Override
-                               public boolean execute(T object) {
-                                       result.add(object);
-                                       return true;
-                               }
-                       });
-                       return result;
-               }
-
-               @Override
-               public Collection<Resource> values() {
-                       ArrayList<Resource> result = new ArrayList<Resource>();
-                       for (int key : backend.values()) {
-                               try {
-                                       result.add(session.getResourceByKey(key));
-                               } catch (ResourceNotFoundException e) {
-                                       e.printStackTrace();
-                               }
-                       }
-                       return result;
-               }
-
-               @Override
-               public Set<java.util.Map.Entry<T, Resource>> entrySet() {
-                       final HashSet<java.util.Map.Entry<T, Resource>> result = new HashSet<java.util.Map.Entry<T, Resource>>();
-                       backend.forEachEntry(new TObjectIntProcedure<T>() {
-
-                               @Override
-                               public boolean execute(final T a, final int b) {
-                                       return result.add(new Map.Entry<T, Resource>() {
-
-                                               @Override
-                                               public T getKey() {
-                                                       return a;
-                                               }
-
-                                               @Override
-                                               public Resource getValue() {
-                                                       return new ResourceImpl(session.resourceSupport, b);
-                                               }
-
-                                               @Override
-                                               public Resource setValue(Resource value) {
-                                                       throw new UnsupportedOperationException("Map.Entry.setValue not supported, structure is immutable");
-                                               }
-
-                                       });
-                               }
-                       });
-                       return result;
-               }
-
-               @Override
-               public int hashCode() {
-                       return backend.hashCode();
-               }
-
-               @Override
-               public boolean equals(Object obj) {
-                       if (this == obj)
-                               return true;
-                       if (obj == null)
-                               return false;
-                       if (getClass() != obj.getClass()) {
-                               if (obj instanceof Map) {
-                                       // Nonoptimal fallback for comparing against generic Map
-                                       Map<?,?> m = (Map<?,?>) obj;
-                                       if (m.size() != size())
-                                               return false;
-                                       try {
-                                               Iterator<Entry<T,Resource>> i = entrySet().iterator();
-                                               while (i.hasNext()) {
-                                                       Entry<T,Resource> e = i.next();
-                                                       T key = e.getKey();
-                                                       Resource value = e.getValue();
-                                                       if (value == null) {
-                                                               if (!(m.get(key)==null && m.containsKey(key)))
-                                                                       return false;
-                                                       } else {
-                                                               if (!value.equals(m.get(key)))
-                                                                       return false;
-                                                       }
-                                               }
-                                               return true;
-                                       } catch (ClassCastException unused) {
-                                               return false;
-                                       } catch (NullPointerException unused) {
-                                               return false;
-                                       }
-                               }
-                               return false;
-                       }
-                       ObjectResourceMap<?> other = (ObjectResourceMap<?>) obj;
-                       return session == other.session && backend.equals(other.backend);
-               }
-
-       }
-
        @SuppressWarnings("unchecked")
        @Override
        public <T, I> T createObjectResourceMap(Class<I> clazz) {
diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/ObjectResourceMap.java
new file mode 100644 (file)
index 0000000..b5171e1
--- /dev/null
@@ -0,0 +1,218 @@
+package fi.vtt.simantics.procore.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.db.ObjectResourceIdMap;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.ResourceNotFoundException;
+import org.simantics.db.impl.ResourceImpl;
+
+import gnu.trove.impl.Constants;
+import gnu.trove.map.hash.TObjectIntHashMap;
+import gnu.trove.procedure.TObjectIntProcedure;
+import gnu.trove.procedure.TObjectProcedure;
+
+final class ObjectResourceMap<T> implements Map<T, Resource>, ObjectResourceIdMap<T> {
+
+       final private SessionImplSocket session;
+       final private TObjectIntHashMap<T> backend;
+
+       ObjectResourceMap(SessionImplSocket session) {
+               this.session = session;
+               backend = new TObjectIntHashMap<T>(Constants.DEFAULT_CAPACITY, Constants.DEFAULT_LOAD_FACTOR, 0);
+       }
+
+       ObjectResourceMap(SessionImplSocket session, int capacity) {
+               this.session = session;
+               backend = new TObjectIntHashMap<T>(capacity, Constants.DEFAULT_LOAD_FACTOR, 0);
+       }
+
+       @Override
+       public int size() {
+               return backend.size();
+       }
+       @Override
+       public boolean isEmpty() {
+               return backend.isEmpty();
+       }
+
+       @Override
+       public boolean containsKey(Object key) {
+               return backend.contains(key);
+       }
+
+       @Override
+       public boolean containsValue(Object value) {
+               ResourceImpl impl = (ResourceImpl) value;
+               return backend.containsValue(impl.id);
+       }
+
+       @Override
+       public Resource get(Object key) {
+               try {
+                       int result = backend.get(key);
+                       if (result == 0)
+                               return null;
+                       return session.getResourceByKey(result);
+               } catch (ResourceNotFoundException e) {
+                       e.printStackTrace();
+               }
+               return null;
+       }
+
+       @Override
+       public Resource put(T key, Resource value) {
+               ResourceImpl impl = (ResourceImpl) value;
+               int i = backend.put(key, impl.id);
+               if (i == 0)
+                       return null;
+               else
+                       try {
+                               return session.getResourceByKey(i);
+                       } catch (ResourceNotFoundException e) {
+                               e.printStackTrace();
+                       }
+               return null;
+       }
+
+       @Override
+       public Resource remove(Object key) {
+               throw new UnsupportedOperationException("remove not supported, structure is immutable");
+       }
+
+       @Override
+       public void putAll(Map<? extends T, ? extends Resource> map) {
+               @SuppressWarnings("unchecked")
+               ObjectResourceMap<T> other = (ObjectResourceMap<T>) map;
+               other.backend.forEachEntry(new TObjectIntProcedure<T>() {
+
+                       @Override
+                       public boolean execute(T a, int b) {
+                               backend.put(a, b);
+                               return true;
+                       }
+               });
+       }
+
+       @Override
+       public void clear() {
+               throw new UnsupportedOperationException("clear not supported, structure is immutable");
+       }
+
+       @Override
+       public Set<T> keySet() {
+               final Set<T> result = new HashSet<T>();
+               backend.forEach(new TObjectProcedure<T>() {
+
+                       @Override
+                       public boolean execute(T object) {
+                               result.add(object);
+                               return true;
+                       }
+               });
+               return result;
+       }
+
+       @Override
+       public Collection<Resource> values() {
+               ArrayList<Resource> result = new ArrayList<Resource>();
+               for (int key : backend.values()) {
+                       try {
+                               result.add(session.getResourceByKey(key));
+                       } catch (ResourceNotFoundException e) {
+                               e.printStackTrace();
+                       }
+               }
+               return result;
+       }
+
+       @Override
+       public Set<java.util.Map.Entry<T, Resource>> entrySet() {
+               final HashSet<java.util.Map.Entry<T, Resource>> result = new HashSet<java.util.Map.Entry<T, Resource>>();
+               backend.forEachEntry(new TObjectIntProcedure<T>() {
+
+                       @Override
+                       public boolean execute(final T a, final int b) {
+                               return result.add(new Map.Entry<T, Resource>() {
+
+                                       @Override
+                                       public T getKey() {
+                                               return a;
+                                       }
+
+                                       @Override
+                                       public Resource getValue() {
+                                               return new ResourceImpl(session.resourceSupport, b);
+                                       }
+
+                                       @Override
+                                       public Resource setValue(Resource value) {
+                                               throw new UnsupportedOperationException("Map.Entry.setValue not supported, structure is immutable");
+                                       }
+
+                               });
+                       }
+               });
+               return result;
+       }
+
+       @Override
+       public int hashCode() {
+               return backend.hashCode();
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass()) {
+                       if (obj instanceof Map) {
+                               // Nonoptimal fallback for comparing against generic Map
+                               Map<?,?> m = (Map<?,?>) obj;
+                               if (m.size() != size())
+                                       return false;
+                               try {
+                                       Iterator<Entry<T,Resource>> i = entrySet().iterator();
+                                       while (i.hasNext()) {
+                                               Entry<T,Resource> e = i.next();
+                                               T key = e.getKey();
+                                               Resource value = e.getValue();
+                                               if (value == null) {
+                                                       if (!(m.get(key)==null && m.containsKey(key)))
+                                                               return false;
+                                               } else {
+                                                       if (!value.equals(m.get(key)))
+                                                               return false;
+                                               }
+                                       }
+                                       return true;
+                               } catch (ClassCastException unused) {
+                                       return false;
+                               } catch (NullPointerException unused) {
+                                       return false;
+                               }
+                       }
+                       return false;
+               }
+               ObjectResourceMap<?> other = (ObjectResourceMap<?>) obj;
+               return session == other.session && backend.equals(other.backend);
+       }
+
+       @Override
+       public void putId(T t, int r) {
+               backend.put(t, r);      
+       }
+
+       @Override
+       public int getId(T t) {
+               return backend.get(t);
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.db/src/org/simantics/db/ConverterExternalValue.java b/bundles/org.simantics.db/src/org/simantics/db/ConverterExternalValue.java
new file mode 100644 (file)
index 0000000..cf52616
--- /dev/null
@@ -0,0 +1,10 @@
+package org.simantics.db;
+
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.scl.runtime.function.Function1;
+
+public interface ConverterExternalValue extends ExternalValue {
+       
+       Function1 getFunction(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException;
+       
+}
diff --git a/bundles/org.simantics.db/src/org/simantics/db/ExternalValue.java b/bundles/org.simantics.db/src/org/simantics/db/ExternalValue.java
new file mode 100644 (file)
index 0000000..51d4934
--- /dev/null
@@ -0,0 +1,9 @@
+package org.simantics.db;
+
+import org.simantics.db.exception.DatabaseException;
+
+public interface ExternalValue {
+
+       public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException;
+       
+}
diff --git a/bundles/org.simantics.db/src/org/simantics/db/ObjectResourceIdMap.java b/bundles/org.simantics.db/src/org/simantics/db/ObjectResourceIdMap.java
new file mode 100644 (file)
index 0000000..2d104e7
--- /dev/null
@@ -0,0 +1,10 @@
+package org.simantics.db;
+
+import java.util.Map;
+
+public interface ObjectResourceIdMap<T> extends Map<T, Resource> {
+
+       void putId(T t, int r);
+       int getId(T t);
+       
+}
index 9c02bbe2a70806dfb8833e9b7a23a12310e7a015..a27cd30837e061c9642823891fedddbc60bb6e27 100644 (file)
@@ -560,7 +560,7 @@ public class VariableDebugger extends Composite {
         if(o instanceof Connection) {
             Connection c = (Connection)o;
             ArrayList<String> result = new ArrayList<String>();
-            for(VariableConnectionPointDescriptor v : c.getConnectionPointDescriptors(graph, null)) {
+            for(VariableConnectionPointDescriptor v : c.getConnectionPointDescriptors(graph, base, null)) {
                 result.add(v.getRelativeRVI(graph, base));
             }
             return "c " + result.toString();
index 5384db0b27210f3aed2d6dc220951b3d4a78d19f..df5665ea463bf41855b789f46e87e60f4fce37b5 100644 (file)
@@ -63,9 +63,9 @@ COMPONENTS.Component <T STR.Component
     @sclAttribute PROPERTIES.commands "commandList self" "[Command]"
 
 COMPONENTS.PrimitiveComponent <T COMPONENTS.Component
-    @L0.assert PROPERTIES.primitiveProperties
-      _ : L0.Value
-        L0.domainProperties FUNCTIONS.primitiveProperties
+    @L0.sclAssertion PROPERTIES.primitiveProperties "primitiveProperties" "DocumentProperties"
+//      _ : L0.Value
+//        L0.domainProperties FUNCTIONS.primitiveProperties
 
 COMPONENTS.ParentlessComponent <T COMPONENTS.PrimitiveComponent /* Component without a parent, e.g. Root, DialogBox */
 
index cd1877b76bdfc87acae2877e437d96f9d7b77969..a0325098f6c80e1e67fdc40ccac193643d1e940e 100644 (file)
@@ -39,7 +39,7 @@ FUNCTIONS.componentNamingStrategy : L0.Function
 FUNCTIONS.pathExists : L0.Function
   L0.HasValueType "Boolean"
 
-FUNCTIONS.primitiveProperties : L0.ExternalValue
-  L0.HasValueType "VariableMap"
+//FUNCTIONS.primitiveProperties : L0.ExternalValue
+//  L0.HasValueType "VariableMap"
 
   
\ No newline at end of file
index d502e3d2f2e860ed22dbdc56340c9e44954a643d..e1c71fe976a62df8b76c3a213c51418a8dbabd34 100644 (file)
@@ -52,7 +52,7 @@ PROPERTIES.model <R L0.HasProperty : L0.FunctionalRelation
     ==> "Variable"
 
 PROPERTIES.primitiveProperties <R L0.HasProperty : L0.FunctionalRelation
-    ==> "String"
+    ==> "DocumentProperties"
 
 PROPERTIES.exists
     @defAttribute L0.Value
index 7a14760250c6d15b15bbf93d9be342004a35b114..af1b8809a1553185658c47e7900fe82f5082f769 100644 (file)
@@ -15,4 +15,9 @@
     <target interface="org.simantics.db.layer0.variable.VariableBuilder">
         <type uri="http://www.simantics.org/Modeling-1.2/SCLCommandSession" class="org.simantics.document.server.state.StateVariableBuilder" />
     </target>
+       <target interface="org.simantics.db.ExternalValue">
+        <resource uri="http://www.simantics.org/Documentation-0.0/Functions/sclValue"
+               class="org.simantics.document.server.SCLExternalValue">
+           </resource>
+    </target>
 </adapters>
\ No newline at end of file
index 4db639f5bf2696a389669d527bae19b035978064..4e9cdeabc5da46d7ef3343c7f1d4d812b8c33564 100644 (file)
@@ -2,6 +2,9 @@ import "Simantics/DB"
 import "Simantics/Variables"
 import "JavaBuiltin" as Java
 
+importJava "org.simantics.document.server.DocumentProperties" where
+    data DocumentProperties
+
 importJava "org.simantics.document.server.io.IConsole" where
     data IConsole
     addMessage :: IConsole -> String -> <Proc> ()
@@ -139,6 +142,8 @@ importJava "org.simantics.document.server.Functions" where
     
     compileDocumentSCLValueExpression :: Variable -> <ReadGraph> String
     
+    primitiveProperties :: <Proc> DocumentProperties
+    
 propertyValueCached :: Serializable a => Typeable a => Variable -> String -> <ReadGraph> a
 propertyValueCached var prop = propertyValueCached_ var prop binding
     
diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentProperties.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/DocumentProperties.java
new file mode 100644 (file)
index 0000000..2951b93
--- /dev/null
@@ -0,0 +1,14 @@
+package org.simantics.document.server;
+
+import java.util.Collection;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.Variable;
+
+public interface DocumentProperties {
+       
+       Collection<String> getKeys(ReadGraph graph, Variable context) throws DatabaseException;
+       Object getValue(ReadGraph graph, Variable context, String key) throws DatabaseException;
+       
+}
index 5e1f5cc30e798aff45343b8f8c5f4483b6d8a9cc..d8294c5e09e0c202e6a96bf2ade19932281d6fae 100644 (file)
@@ -12,7 +12,7 @@ import java.util.TreeMap;
 import org.simantics.databoard.Bindings;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
-import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.common.request.BinaryRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.request.VariableRead;
 import org.simantics.db.layer0.variable.ProxyChildVariable;
@@ -24,7 +24,6 @@ import org.simantics.document.server.request.NodeRequest;
 import org.simantics.document.server.request.NodeRequestUtils;
 import org.simantics.structural2.variables.Connection;
 import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
-import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.strings.AlphanumComparator;
 
 public class DocumentServerUtils {
@@ -127,7 +126,7 @@ public class DocumentServerUtils {
 
        public static Variable getPossibleOtherConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
 
-               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
+               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
                if(descs.size() != 2) return null;
 
                for(VariableConnectionPointDescriptor desc : descs) {
@@ -141,7 +140,7 @@ public class DocumentServerUtils {
 
        public static Variable getPossibleChildConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
 
-               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
+               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
                if(descs.size() != 2) return null;
 
        DocumentationResource DOC = DocumentationResource.getInstance(graph);
@@ -161,7 +160,7 @@ public class DocumentServerUtils {
 
                ArrayList<Variable> connectionPoints = new ArrayList<Variable>();
                
-               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, null);
+               Collection<VariableConnectionPointDescriptor> descs = conn.getConnectionPointDescriptors(graph, connectionPoint.getParent(graph), null);
 
                for(VariableConnectionPointDescriptor desc : descs) {
                        if(desc.isFlattenedFrom(graph, connectionPoint)) continue;
@@ -174,7 +173,7 @@ public class DocumentServerUtils {
 
        public static Variable getPossibleCommandTriggerConnectionPoint(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
 
-               Collection<Variable> cpts = conn.getConnectionPoints(graph, null);
+               Collection<Variable> cpts = conn.getConnectionPoints(graph, connectionPoint.getParent(graph), null);
 
                Variable result = null;
                
@@ -192,7 +191,7 @@ public class DocumentServerUtils {
 
        public static Collection<Variable> getPossibleOtherConnectionPoints(ReadGraph graph, Variable connectionPoint, Connection conn) throws DatabaseException {
 
-           Collection<Variable> cpts = conn.getConnectionPoints(graph, null);
+           Collection<Variable> cpts = conn.getConnectionPoints(graph, connectionPoint.getParent(graph), null);
            if(cpts.size() < 2) 
                return Collections.emptyList();
 
@@ -237,11 +236,11 @@ public class DocumentServerUtils {
                if (otherCp != null) {
                        return otherCp;
                } else {
-                       Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
+                       Variable parentCp = graph.sync(new BinaryRead<Variable, Connection, Variable>(connectionPoint.getParent(graph), conn) {
                    @Override
                    public Variable perform(ReadGraph graph) throws DatabaseException {
                        DocumentationResource DOC = DocumentationResource.getInstance(graph);
-                       Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
+                       Collection<VariableConnectionPointDescriptor> descs = parameter2.getConnectionPointDescriptors(graph, parameter, null);
 
                                for(VariableConnectionPointDescriptor desc : descs) {
                                        if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
@@ -294,40 +293,33 @@ public class DocumentServerUtils {
                return variable.getProperties(graph, DOC.Document_AttributeRelation);
        }
        
-       public static class AttributesRequest extends VariableRead<Pair<JSONObject, Collection<Variable>>> {
+       public static class AttributesRequest extends VariableRead<JSONObject> {
 
                public AttributesRequest(Variable variable) {
                        super(variable);
                }
 
                @Override
-               public Pair<JSONObject,Collection<Variable>> perform(ReadGraph graph) throws DatabaseException {
-               ArrayList<Variable> statics = new ArrayList<Variable>();
-               DocumentationResource DOC = DocumentationResource.getInstance(graph);
-               
-               Variable primitives = variable.getProperty(graph, DOC.Properties_primitiveProperties);
-               for(Variable property : primitives.getProperties(graph)) {
-                       statics.add(property);
-                       // NO SUPPORT FOR DYNAMICS AT THIS STAGE
-               }
+               public JSONObject perform(ReadGraph graph) throws DatabaseException {
+
+                       DocumentationResource DOC = DocumentationResource.getInstance(graph);
                
-               JSONObject staticContent = computeStatic(graph, variable, statics);
+               DocumentProperties properties = variable.getPropertyValue(graph, DOC.Properties_primitiveProperties); 
                
-               return new Pair<JSONObject, Collection<Variable>>(staticContent, Collections.emptyList());
+               return computeStatic(graph, variable, properties);
                
                }
                
-               JSONObject computeStatic(ReadGraph graph, Variable variable, ArrayList<Variable> statics) throws DatabaseException {
+               JSONObject computeStatic(ReadGraph graph, Variable variable, DocumentProperties statics) throws DatabaseException {
                        
                        JSONObject base = graph.syncRequest(new org.simantics.document.server.request.DefaultFields(variable));
                        JSONObject object = base.clone();
                        
-                       for(Variable attrib : statics) {
-                               String name = attrib.getName(graph);
+                       for(String name : statics.getKeys(graph, variable)) {
                                try {
                                        if (name.equals(NodeRequest.PROPERTY_VALUE_EXCEPTIONS)) {
                                        @SuppressWarnings("unchecked")
-                                               Map<String, Exception> exceptions = (Map<String, Exception>)DocumentServerUtils.getValue(graph, attrib);
+                                               Map<String, Exception> exceptions = (Map<String, Exception>)statics.getValue(graph, variable, name);//(Map<String, Exception>)DocumentServerUtils.getValue(graph, attrib);
                                        
                                        List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
                                            if(errorList == null)
@@ -340,8 +332,7 @@ public class DocumentServerUtils {
                                        object.addJSONField(NodeRequest.ERRORS, errorList);
                                        
                                    } else {
-                                               Object value = DocumentServerUtils.getValue(graph, attrib);
-                                           object.addJSONField(name, value);
+                                           object.addJSONField(name, statics.getValue(graph, variable, name));
                                    }
                                } catch (Throwable t) {
                                    List<String> errorList = object.getJSONField(NodeRequest.ERRORS);
@@ -363,8 +354,7 @@ public class DocumentServerUtils {
        }
 
        public static Collection<Variable> getDynamicAttributes(ReadGraph graph, final DocumentationResource DOC, Variable variable) throws DatabaseException {
-       Pair<JSONObject, Collection<Variable>> attribs = graph.syncRequest(new AttributesRequest(variable));
-       return attribs.second;
+               return Collections.emptyList();
        }
        
        public static Variable getPossibleDocumentRootVariable(ReadGraph graph, Variable documentPart) throws DatabaseException {
index 66cc0047c3389fe4e559486c76f8eb52bf50a8ab..0e56a7dd2569f5e9ef8efa1cbef0e2eac1ebf52d 100644 (file)
@@ -25,7 +25,7 @@ import org.simantics.db.Statement;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.primitiverequest.Adapter;
 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
-import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.common.request.BinaryRead;
 import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.common.request.WriteResultRequest;
 import org.simantics.db.common.utils.Logger;
@@ -1254,11 +1254,11 @@ public class Functions {
                                                return true;
                                        }
                                } else {
-                                       Variable parentCp = graph.sync(new UnaryRead<Connection, Variable>(conn) {
+                                       Variable parentCp = graph.sync(new BinaryRead<Variable, Connection, Variable>(widget, conn) {
                                    @Override
                                    public Variable perform(ReadGraph graph) throws DatabaseException {
                                        DocumentationResource DOC = DocumentationResource.getInstance(graph);
-                                       Collection<VariableConnectionPointDescriptor> descs = parameter.getConnectionPointDescriptors(graph, null);
+                                       Collection<VariableConnectionPointDescriptor> descs = parameter2.getConnectionPointDescriptors(graph, parameter, null);
 
                                                for(VariableConnectionPointDescriptor desc : descs) {
                                                        if (DOC.Relations_partN.equals(desc.getConnectionPointResource(graph))) {
@@ -1310,5 +1310,33 @@ public class Functions {
             LOGGER.debug("", e);
         return e.getMessage();
     }
+    
+    static class StandardDocumentProperties implements DocumentProperties {
+
+               @Override
+               public Collection<String> getKeys(ReadGraph graph, Variable context) throws DatabaseException {
+                       
+               DocumentationResource DOC = DocumentationResource.getInstance(graph);
+                       StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
+                       Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
+                       return ps.keySet();
+                       
+               }
+
+               @Override
+               public Object getValue(ReadGraph graph, Variable context, String key) throws DatabaseException {
+                       
+               DocumentationResource DOC = DocumentationResource.getInstance(graph);
+                       StandardGraphPropertyVariable asd = new StandardGraphPropertyVariable(graph, context, DOC.Properties_primitiveProperties);
+                       Map<String, Variable> ps = primitiveProperties.getVariables(graph, asd, null);
+                       return ps.get(key).getValue(graph);
+                       
+               }
+       
+    }
+    
+    public static DocumentProperties primitiveProperties() throws DatabaseException {
+       return new StandardDocumentProperties();
+    }
 
 }
\ No newline at end of file
diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/SCLExternalValue.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/SCLExternalValue.java
new file mode 100644 (file)
index 0000000..d72335d
--- /dev/null
@@ -0,0 +1,29 @@
+package org.simantics.document.server;
+
+import org.simantics.db.ConverterExternalValue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.base.ontology.DocumentationResource;
+import org.simantics.document.server.request.ServerSCLValueRequest;
+import org.simantics.scl.reflection.ReflectionUtils;
+import org.simantics.scl.reflection.ValueNotFoundException;
+import org.simantics.scl.runtime.function.Function1;
+
+public class SCLExternalValue implements ConverterExternalValue {
+
+       @Override
+       public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException {
+               try {
+                       return (T)ReflectionUtils.getValue(DocumentationResource.URIs.Functions_sclValue).getValue();
+               } catch (ValueNotFoundException e) {
+                       throw new DatabaseException(e);
+               }
+       }
+
+       @Override
+       public Function1 getFunction(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+               return ServerSCLValueRequest.compile(graph, s, o, p);
+       }
+
+}
index d9418db9947d482fecd4daf547d85359363bea5c..50c8827efdf73d4cb7e238cac0a169de61462120 100644 (file)
@@ -17,60 +17,27 @@ public class NodeRequest extends VariableRead<JSONObject> {
 
     public static final String ERRORS = "Errors";
     public static final String PROPERTY_VALUE_EXCEPTIONS = "_PropertyValueExceptions";
-    
-       public NodeRequest(Variable node) {
-               super(node);
-       }
 
-       @SuppressWarnings("unchecked")
-    @Override
-       public JSONObject perform(ReadGraph graph) throws DatabaseException {
-
-               long s = System.nanoTime();
-
-               Pair<JSONObject, Collection<Variable>> attribs = graph.syncRequest(new AttributesRequest(variable));
-
-           JSONObject staticContent = attribs.first;
-           if(attribs.second.isEmpty()) {
-
-               if(DocumentRequest.PROFILE) {
-                       long dura = System.nanoTime()-s;
-                   if(dura > DocumentRequest.PROFILE_THRESHOLD_NODEREQUEST * 1e3) {
-                       System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
-                   }
-               }
-
-               return staticContent;
-           }
-
-           Map<String,Object> dynamicContent = graph.syncRequest(new NodeRequestDynamic(variable));
-           if(dynamicContent.isEmpty()) {
-               return staticContent;
-           }
-
-        JSONObject result = staticContent.clone();
-        result.add(dynamicContent);
+    public NodeRequest(Variable node) {
+       super(node);
+    }
 
-        if(dynamicContent.containsKey(ERRORS) || staticContent.getJSONField(ERRORS) != null) {
-            ArrayList<String> errorList = new ArrayList<>();
+    @SuppressWarnings("unchecked")
+    @Override
+    public JSONObject perform(ReadGraph graph) throws DatabaseException {
 
-            if(dynamicContent.containsKey(ERRORS))
-                errorList.addAll((List<String>)dynamicContent.get(ERRORS));
+       long s = System.nanoTime();
 
-            if(staticContent.getJSONField(ERRORS) != null)
-                errorList.addAll((List<String>)staticContent.getJSONField(ERRORS));
+       JSONObject staticContent = graph.syncRequest(new AttributesRequest(variable));
 
-            result.addJSONField(ERRORS, errorList);
-        }
+       if(DocumentRequest.PROFILE) {
+               long dura = System.nanoTime()-s;
+               if(dura > DocumentRequest.PROFILE_THRESHOLD_NODEREQUEST * 1e3) {
+                       System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
+               }
+       }
 
-        if(DocumentRequest.PROFILE) {
-            long dura = System.nanoTime()-s;
-            if(dura > DocumentRequest.PROFILE_THRESHOLD_NODEREQUEST * 1e3) {
-                System.err.println("NodeRequest " + System.identityHashCode(this) + " in " + 1e-6*dura + "ms. " + variable.getURI(graph));
-            }
-        }
-        
-        return result;
+       return staticContent;
 
     }
 
index 4a4164303613c1a2c9d963693804d727305cdb2a..67d4d7a44cf10694dc3e0e653043e4969dd733a4 100644 (file)
@@ -8,12 +8,14 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
 import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.common.request.PossibleTypedParent;
+import org.simantics.db.common.request.UnaryRead;
 import org.simantics.db.exception.DatabaseException;
-import org.simantics.db.layer0.request.VariableRead;
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
 import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
 import org.simantics.db.layer0.variable.Variable;
+import org.simantics.document.base.ontology.DocumentationResource;
 import org.simantics.document.server.request.ServerSCLHandlerValueRequest.CompilationContext;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.compiler.elaboration.expressions.EApply;
@@ -37,7 +39,6 @@ import org.simantics.utils.datastructures.Pair;
 
 public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationRequest<CompilationContext, Variable> {
 
-       private final Variable context;
        private final Pair<Resource,Resource> componentTypeAndRoot;
        private final Resource literal;
        protected String possibleExpectedValueType;
@@ -52,16 +53,19 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                }
        }
 
-       private ServerSCLHandlerValueRequest(Variable context, Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
+       private ServerSCLHandlerValueRequest(Pair<Resource,Resource> componentTypeAndRoot, Resource literal, String possibleExpectedValueType) {
                assert(literal != null);
-               this.context = context;
                this.literal = literal;
                this.componentTypeAndRoot = componentTypeAndRoot;
                this.possibleExpectedValueType = possibleExpectedValueType;
        }
 
        public ServerSCLHandlerValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
-               this(context, getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context));
+               this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
+       }
+
+       public ServerSCLHandlerValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+               this(getComponentTypeAndRoot(graph, s), o, resolveExpectedValueType(graph, p));
        }
 
        private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {
@@ -74,12 +78,14 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                                return Pair.make(type, root);
                        }
                }
-               parent = parent.getParent(graph);
+               while(represents == null) {
+                       parent = parent.getParent(graph);
+                       represents = parent.getPossibleRepresents(graph);
+               }
                Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
                return Pair.make(parent.getType(graph), root);
        }
 
-
     public static List<TCon> getEffects(ReadGraph graph, Variable context) throws DatabaseException {
         try {
                ServerSCLHandlerValueRequest req = new ServerSCLHandlerValueRequest(graph, context);
@@ -128,25 +134,18 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
        @Override
        protected CompilationContext getCompilationContext(ReadGraph graph) throws DatabaseException {
                
-               return graph.syncRequest(new VariableRead<CompilationContext>(context) {
+               return graph.syncRequest(new UnaryRead<Pair<Resource,Resource>,CompilationContext>(componentTypeAndRoot) {
                        
                        @Override
                        public CompilationContext perform(ReadGraph graph) throws DatabaseException {
                                
-                               Pair<Resource,Resource> parameter = getComponentTypeAndRoot(graph, variable);
                                RuntimeEnvironment runtimeEnvironment = graph.syncRequest(getRuntimeEnvironmentRequest(parameter.first, parameter.second));
-                               
                                Map<String, ComponentTypeProperty> propertyMap =
                                                graph.syncRequest(new ReadComponentTypeInterfaceRequest(parameter.first, runtimeEnvironment.getEnvironment()),
                                                                TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
-
-//                             Map<String, ComponentTypeProperty> result = new HashMap<String,ComponentTypeProperty>(propertyMap); 
-//                             for(DataDefinition dd : Functions.dataDefinitions(graph, variable)) {
-//                                     result.put(dd.target, null);
-//                             }
-                               
                                return new CompilationContext(runtimeEnvironment, propertyMap);
                                
+                               
                        }
                        
                });
@@ -229,10 +228,7 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
 
        @Override
        public int hashCode() {
-               final int prime = 31;
-               int result = 1;
-               result = prime * result + ((context == null) ? 0 : context.hashCode());
-               return result;
+               return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
        }
 
        @Override
@@ -244,27 +240,22 @@ public class ServerSCLHandlerValueRequest extends AbstractExpressionCompilationR
                if (getClass() != obj.getClass())
                        return false;
                ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest) obj;
-               if (context == null) {
-                       if (other.context != null)
-                               return false;
-               } else if (!context.equals(other.context))
-                       return false;
-               return true;
+               return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
+       }
+       
+       private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component)  throws DatabaseException {
+               if(component != null) {
+                       Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
+                       if(type != null) {
+                               Resource root = graph.syncRequest(new IndexRoot(type));
+                               return Pair.make(type, root);
+                       } else {
+                               Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
+                               Resource root = graph.syncRequest(new IndexRoot(component));
+                               return Pair.make(graph.getSingleType(doc), root);
+                       }
+               }
+               throw new IllegalStateException();
        }
-
-//     @Override
-//     public int hashCode() {
-//             return 31*(31*getClass().hashCode() + literal.hashCode()) + componentTypeAndRoot.hashCode();
-//     }
-//
-//     @Override
-//     public boolean equals(Object obj) {
-//             if(this == obj)
-//                     return true;
-//             if(obj == null || obj.getClass() != getClass())
-//                     return false;
-//             ServerSCLHandlerValueRequest other = (ServerSCLHandlerValueRequest)obj;
-//             return literal.equals(other.literal) && componentTypeAndRoot.equals(other.componentTypeAndRoot);
-//     }
        
 }
index f9181d271073964b6082fef5119a679e8c371075..77cd9b4f4a3a8cfe175b27c40508819dc3cfa880 100644 (file)
@@ -7,12 +7,14 @@ import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
 import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.common.request.PossibleTypedParent;
 import org.simantics.db.common.request.UnaryRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
 import org.simantics.db.layer0.scl.AbstractExpressionCompilationRequest;
 import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
 import org.simantics.db.layer0.variable.Variable;
+import org.simantics.document.base.ontology.DocumentationResource;
 import org.simantics.document.server.request.ServerSCLValueRequest.CompilationContext;
 import org.simantics.layer0.Layer0;
 import org.simantics.scl.compiler.common.names.Name;
@@ -64,7 +66,11 @@ public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<
        }
 
        public ServerSCLValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
-               this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context));
+               this(getComponentTypeAndRoot(graph, context), context.getRepresents(graph), resolveExpectedValueType(graph, context.getPredicateResource(graph)));
+       }
+
+       public ServerSCLValueRequest(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+               this(getComponentTypeAndRoot(graph, s), o, resolveExpectedValueType(graph, p));
        }
 
        private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Variable property)  throws DatabaseException {
@@ -77,11 +83,29 @@ public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<
                                return Pair.make(type, root);
                        }
                }
-               parent = parent.getParent(graph);
+               while(represents == null) {
+                       parent = parent.getParent(graph);
+                       represents = parent.getPossibleRepresents(graph);
+               }
                Resource root = graph.syncRequest(new IndexRoot(property.getRepresents(graph)));
                return Pair.make(parent.getType(graph), root);
        }
 
+       private static Pair<Resource,Resource> getComponentTypeAndRoot(ReadGraph graph, Resource component)  throws DatabaseException {
+               if(component != null) {
+                       Resource type = graph.syncRequest(new FindPossibleComponentTypeRequest(component));
+                       if(type != null) {
+                               Resource root = graph.syncRequest(new IndexRoot(type));
+                               return Pair.make(type, root);
+                       } else {
+                               Resource doc = graph.syncRequest(new PossibleTypedParent(component, DocumentationResource.getInstance(graph).Document));
+                               Resource root = graph.syncRequest(new IndexRoot(component));
+                               return Pair.make(graph.getSingleType(doc), root);
+                       }
+               }
+               throw new IllegalStateException();
+       }
+
        public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
                SCLContext sclContext = SCLContext.getCurrent();
         Object oldGraph = sclContext.get("graph");
@@ -102,6 +126,10 @@ public class ServerSCLValueRequest extends AbstractExpressionCompilationRequest<
            return graph.syncRequest(new ServerSCLValueRequest(graph, context), TransientCacheListener.<Function1<Variable,Object>>instance());
        }
 
+       public static Function1<Variable, Object> compile(ReadGraph graph, Resource s, Resource o, Resource p) throws DatabaseException {
+           return graph.syncRequest(new ServerSCLValueRequest(graph, s, o, p), TransientCacheListener.<Function1<Variable,Object>>instance());
+       }
+
        @Override
        protected String getExpressionText(ReadGraph graph)
                        throws DatabaseException {
index e013ef02531e1be08aa0230b1380f15cddf58c4f..516b9a15c5df84c4dc44d7a0ac32e24fb6191c72 100644 (file)
@@ -20,6 +20,7 @@ public class ComboWidget extends LeafWidgetManager<Combo> {
        private ModifyListener modifyListener = null;
 
        private StringList extractAvailable(Object o) {
+               if(o == null) return new StringList(new String[0]);
                if(o instanceof StringList) return (StringList)o;
                if(o instanceof List) return new StringList((List)o);
                if(o instanceof String[]) return new StringList((String[])o);
index 2b93df74dceeb0fed0b3f0c871a62fe043968d8a..b4a4ed3e23719aa6fa704d9c2b22d931f72499cc 100644 (file)
@@ -49,6 +49,7 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.WriteOnlyGraph;
 import org.simantics.db.common.CommentMetadata;
 import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.common.request.WriteOnlyRequest;
 import org.simantics.db.common.request.WriteRequest;
 import org.simantics.db.exception.CancelTransactionException;
@@ -595,6 +596,19 @@ public class TransferableGraphs {
                LOGGER.info("Wrote transferable graph in {} seconds.", 1e-9*(end-start));
        }
 
+       public static TransferableGraph1 create(RequestProcessor processor, TransferableGraphSource source) throws DatabaseException {
+               
+               return processor.syncRequest(new UniqueRead<TransferableGraph1>() {
+
+                       @Override
+                       public TransferableGraph1 perform(ReadGraph graph) throws DatabaseException {
+                               return create(graph, source);
+                       }
+                       
+               });
+               
+       }
+
        public static TransferableGraph1 create(ReadGraph graph, TransferableGraphSource source) throws DatabaseException {
                
                try {
index 783f4f401f271affbd497959b5ec60e2806ee6bd..8d745a354dcfa7059363ec9c873b66d45b2b2f0b 100644 (file)
@@ -2,6 +2,8 @@ L0 = <http://www.simantics.org/Layer0-1.1>
 
 L0.Functions : L0.Library
 
+// The logic of functionApplication assumes that the function is actually ExternalValue
+// but it is not since it would prevent it from being converted with functionApplication
 L0.Function <T L0.Value
     @L0.assert L0.ConvertsToValueWith L0.Functions.functionApplication
 
index c36cf60e56cffc6faf7d53cc1e7c10d2d0a3bd40..16f01a7bebfba9553314e5f12cff27648a3470c8 100644 (file)
@@ -40,6 +40,15 @@ L0.scl : L0.Template
               L0.SCLValue.expression %expression
               L0.HasValueType %valueType
 
+L0.sclAssertion : L0.Template
+    @template %type %property %expression %valueType
+        %type
+            L0.Asserts _ : L0.Assertion
+              L0.HasPredicate %property
+              L0.HasObject _ : L0.SCLValue
+                L0.SCLValue.expression %expression
+                L0.HasValueType %valueType
+
 L0.SCLValue.Environment <T L0.Entity
     >-- L0.SCLValue.Environment.moduleName --> L0.String <R L0.HasProperty : L0.TotalFunction
     >-- L0.SCLValue.Environment.namespace --> L0.String <R L0.HasProperty : L0.TotalFunction
index ff53cb579b533673483a2cfc2e33da8093905d52..3c3802df6e8608b197a4b5040d3f0ca9c889ab06 100644 (file)
                </resource>
        </target>
 
+       <target interface="org.simantics.db.layer0.variable.VariableBuilder">
+               <type uri="http://www.simantics.org/Structural-1.2/Component"
+                       class="org.simantics.modeling.ImmutableComponentVariableBuilder" >
+               </type>
+       </target>
+
 </adapters>
\ No newline at end of file
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContent.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContent.java
new file mode 100644 (file)
index 0000000..92808d0
--- /dev/null
@@ -0,0 +1,26 @@
+package org.simantics.modeling;
+
+import java.util.Map;
+
+import org.simantics.db.Resource;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.scl.runtime.function.Function1;
+
+public class ImmutableComponentPropertyContent {
+
+       final public PropertyInfo pi;
+       final public Resource valueResource;
+       final public Object value;
+       final public Function1<Object,Object> expression;
+       
+       public Map<String,ImmutableComponentPropertyContent> properties;
+       
+       ImmutableComponentPropertyContent(PropertyInfo pi, Resource valueResource, Object literal, Function1<Object,Object> expression) {
+               assert(valueResource != null);
+               this.pi = pi;
+               this.valueResource = valueResource;
+               this.value = literal;
+               this.expression = expression;
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContentRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyContentRequest.java
new file mode 100644 (file)
index 0000000..32db2bb
--- /dev/null
@@ -0,0 +1,159 @@
+package org.simantics.modeling;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.simantics.db.ConverterExternalValue;
+import org.simantics.db.ExternalValue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.BinaryRead;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource;
+import org.simantics.db.layer0.variable.ValueAccessor;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.scl.runtime.function.FunctionImpl1;
+
+public class ImmutableComponentPropertyContentRequest extends BinaryRead<Resource, PropertyInfo, ImmutableComponentPropertyContent> {
+
+       protected ImmutableComponentPropertyContentRequest(Resource subject, PropertyInfo predicate) {
+               super(subject, predicate);
+       }
+
+
+       static class ExcludedSubjects extends UniqueRead<Set<Resource>> {
+
+               @Override
+               public Set<Resource> perform(ReadGraph graph) throws DatabaseException {
+                       Layer0 L0 = Layer0.getInstance(graph);
+                       return new HashSet<Resource>(Arrays.asList(L0.HasName,
+                                       L0.HasLabel,
+                                       L0.HasDataType,
+                                       L0.HasValueType,
+                                       L0.RequiresValueType,
+                                       L0.hasStandardResource,
+                                       L0.RequiresValueType,
+                                       L0.HasDescription,
+                                       L0.valueAccessor,
+                                       L0.domainChildren,
+                                       L0.domainProperties,
+                                       L0.classifications,
+                                       L0.Entity_methods,
+                                       L0.default_,
+                                       L0.required,
+                                       L0.readOnly,
+                                       L0.valid,
+                                       L0.validator));
+
+               }
+               
+       }
+       
+       
+       public ImmutableComponentPropertyContent getPossibleContent(ReadGraph graph) throws DatabaseException {
+               
+               Layer0 L0 = Layer0.getInstance(graph);
+
+               Resource resource = parameter;
+               PropertyInfo pi = parameter2;
+
+               Resource value = graph.getPossibleObject(resource, pi.predicate);
+               if(value != null) {
+                       
+                       if(graph.isInstanceOf(value, L0.Literal)) {
+                               Object literal = graph.getPossibleValue(value);
+                               if(literal != null) {
+                                       return new ImmutableComponentPropertyContent(pi, value, literal, null);
+                               }
+                       } else if(graph.isInstanceOf(value, L0.SCLValue)) {
+                               
+                               Resource converter = graph.getPossibleObject(value, L0.ConvertsToValueWith);
+                               if(converter != null) {
+
+                                       ExternalValue ev = graph.adapt(converter, ExternalValue.class);
+                                       if(ev instanceof ConverterExternalValue) {
+                                               ConverterExternalValue cev = (ConverterExternalValue)ev; 
+                                               Function1 fn  = cev.getFunction(graph, resource, value, pi.predicate);
+                                               return new ImmutableComponentPropertyContent(pi, value, null, fn);
+                                       } else {
+                                               System.err.println("Undefined converter " + graph.getURI(converter));
+                                       }
+                                       
+                               }
+                               
+                       } else if(graph.isInstanceOf(value, L0.Value)) {
+                               
+                               Resource valueAccessor = graph.getPossibleObject(value, L0.valueAccessor);
+                               if(valueAccessor != null) {
+                                       FunctionImpl1 fn = new FunctionImpl1() {
+       
+                                               @Override
+                                               public Object apply(Object p0) {
+                                                       try {
+                                                               ReadGraph graph = (ReadGraph)SCLContext.getCurrent().get("graph");
+                                                               ValueAccessor accessor = graph.getValue2(valueAccessor, p0);
+                                                               return accessor.getValue(graph, (Variable)p0);
+                                                       } catch (DatabaseException e) {
+                                                               throw new IllegalStateException(e);
+                                                       }
+                                               }
+       
+                                       };
+                                       
+                                       return new ImmutableComponentPropertyContent(pi, value, null, fn);
+                                       
+                               }
+                               
+                       }
+               }
+               
+               return null;
+
+       }
+
+       private void process(ReadGraph graph, Resource subject, ImmutableComponentPropertyContent result) throws DatabaseException {
+               
+               Set<Resource> exclusions = graph.syncRequest(new ExcludedSubjects());
+               if(exclusions.contains(subject)) return;
+               
+               for(PropertyInfo pi : graph.syncRequest(new UnescapedPropertyMapOfResource(subject)).values()) {
+
+                       // This is somewhat awkward
+                       if(parameter2.predicate.equals(pi.predicate)) continue;
+                       
+                       try {
+                               if(pi.isHasProperty) {
+                                       ImmutableComponentPropertyContent pc = graph.syncRequest(new ImmutableComponentPropertyContentRequest(subject, pi));
+                                       if(pc != null) {
+                                               if(result.properties == null) result.properties = new HashMap<>();
+                                               result.properties.put(pc.pi.name, pc);
+                                       }
+                               }
+                       } catch (DatabaseException e) {
+                               e.printStackTrace();
+                       }
+               }
+       }
+       
+       @Override
+       public ImmutableComponentPropertyContent perform(ReadGraph graph) throws DatabaseException {
+
+               ImmutableComponentPropertyContent result = getPossibleContent(graph);
+               if(result == null) return null;
+
+               process(graph, result.pi.predicate, result);
+               process(graph, result.valueResource, result);
+
+               return result;
+               
+       }
+
+       
+}
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyVariable.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentPropertyVariable.java
new file mode 100644 (file)
index 0000000..2618536
--- /dev/null
@@ -0,0 +1,153 @@
+package org.simantics.modeling;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.Simantics;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.type.Datatype;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.layer0.variable.AbstractPropertyVariable;
+import org.simantics.db.layer0.variable.Variable;
+
+class ImmutableComponentPropertyVariable extends AbstractPropertyVariable {
+
+       final Variable parent;
+       final ImmutableComponentPropertyContent content;
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((content == null) ? 0 : content.hashCode());
+               result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               ImmutableComponentPropertyVariable other = (ImmutableComponentPropertyVariable) obj;
+               if (content == null) {
+                       if (other.content != null)
+                               return false;
+               } else if (!content.equals(other.content))
+                       return false;
+               if (parent == null) {
+                       if (other.parent != null)
+                               return false;
+               } else if (!parent.equals(other.parent))
+                       return false;
+               return true;
+       }
+
+       ImmutableComponentPropertyVariable(Variable parent, ImmutableComponentPropertyContent content) {
+               this.parent = parent;
+               this.content = content;
+       }
+
+       @Override
+       public Resource getPropertyResource(ReadGraph graph) throws DatabaseException {
+               return content.pi.predicate;
+       }
+
+       @Override
+       public Resource getPossiblePredicateResource(ReadGraph graph) throws DatabaseException {
+               return content.pi.predicate;
+       }
+
+       @Override
+       public Resource getContainerResource(ReadGraph graph) throws DatabaseException {
+               throw new IllegalStateException();
+       }
+
+       @Override
+       public Datatype getDatatype(ReadGraph graph) throws DatabaseException {
+               return Layer0Utils.getDatatype(graph, this);
+       }
+
+       @Override
+       public Resource getPredicateResource(ReadGraph graph) throws DatabaseException {
+               return content.pi.predicate;
+       }
+
+       @Override
+       public Variable getPredicate(ReadGraph graph) throws DatabaseException {
+               throw new IllegalStateException();
+       }
+
+       @Override
+       public <T> T getValue(ReadGraph graph) throws DatabaseException {
+               if(content.value != null) return (T)content.value;
+               return (T)Simantics.applySCLRead(graph, content.expression, this);
+       }
+
+       @Override
+       public <T> T getValue(ReadGraph graph, Binding binding) throws DatabaseException {
+               if(content.value != null) return (T)content.value;
+               return (T)Simantics.applySCLRead(graph, content.expression, this);
+       }
+
+       @Override
+       public void setValue(WriteGraph graph, Object value, Binding binding) throws DatabaseException {
+               throw new IllegalStateException();
+       }
+
+       @Override
+       public String getName(ReadGraph graph) throws DatabaseException {
+               return content.pi.name;
+       }
+
+       @Override
+       public Variable getParent(ReadGraph graph) throws DatabaseException {
+               return parent;
+       }
+
+       @Override
+       public Set<String> getClassifications(ReadGraph graph) throws DatabaseException {
+               return content.pi.classifications;
+       }
+
+       @Override
+       protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
+
+               if(content.properties == null)
+                       return null;
+
+               ImmutableComponentPropertyContent p = content.properties.get(name);
+               if(p != null)
+                       return new ImmutableComponentPropertyVariable(this, p);
+
+               return null;
+
+       }
+
+       @Override
+       public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> map)
+                       throws DatabaseException {
+
+               if(content.properties == null)
+                       return map;
+
+               if(map == null)
+                       map = new HashMap<>();
+
+               for(ImmutableComponentPropertyContent p : content.properties.values()) {
+                       map.put(p.pi.name, new ImmutableComponentPropertyVariable(this, p));
+               }
+
+               return map;
+
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariable.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariable.java
new file mode 100644 (file)
index 0000000..6ed9273
--- /dev/null
@@ -0,0 +1,122 @@
+package org.simantics.modeling;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.AbstractChildVariable;
+import org.simantics.db.layer0.variable.StandardGraphChildVariable;
+import org.simantics.db.layer0.variable.Variable;
+
+public class ImmutableComponentVariable extends AbstractChildVariable {
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((content == null) ? 0 : content.hashCode());
+               result = prime * result + ((parent == null) ? 0 : parent.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               ImmutableComponentVariable other = (ImmutableComponentVariable) obj;
+               if (content == null) {
+                       if (other.content != null)
+                               return false;
+               } else if (!content.equals(other.content))
+                       return false;
+               if (parent == null) {
+                       if (other.parent != null)
+                               return false;
+               } else if (!parent.equals(other.parent))
+                       return false;
+               return true;
+       }
+
+       final private Variable parent;
+       final private ImmutableComponentVariableContent content;
+       
+       ImmutableComponentVariable(Variable parent, ImmutableComponentVariableContent content) {
+               this.parent = parent;
+               this.content = content;
+       }
+       
+       @Override
+       public String getName(ReadGraph graph) throws DatabaseException {
+               return content.name;
+       }
+       
+       @Override
+       public Variable getParent(ReadGraph graph) throws DatabaseException {
+               return parent;
+       }
+       
+       @Override
+       public Resource getRepresents(ReadGraph graph) throws DatabaseException {
+               return content.resource;
+       }
+
+       @Override
+       public Variable getPossibleChild(ReadGraph graph, String name) throws DatabaseException {
+               if(content.children == null) return null;
+               ImmutableComponentVariableContent c = content.children.get(name);
+               if(c == null) return null;
+               return new ImmutableComponentVariable(this, c);
+       }
+       
+       @Override
+       public Collection<Variable> getChildren(ReadGraph graph) throws DatabaseException {
+               if(content.children == null) return Collections.emptyList();
+               ArrayList<Variable> result = new ArrayList<Variable>(content.children.size());
+               for(ImmutableComponentVariableContent c : content.children.values()) {
+                       result.add(new ImmutableComponentVariable(this, c));
+               }
+               return result;
+       }
+       
+       @Override
+       protected Variable getPossibleDomainProperty(ReadGraph graph, String name) throws DatabaseException {
+
+               if(content.properties == null)
+                       return null;
+
+               ImmutableComponentPropertyContent p = content.properties.get(name);
+               if(p != null)
+                       return new ImmutableComponentPropertyVariable(this, p);
+               
+               return new StandardGraphChildVariable(parent, node, content.resource).getPossibleProperty(graph, name);
+               
+       }
+       
+       @Override
+       public Map<String, Variable> collectDomainProperties(ReadGraph graph, Map<String, Variable> map)
+                       throws DatabaseException {
+               
+               if(content.properties == null)
+                       return map;
+
+               if(map == null)
+                       map = new HashMap<>();
+               
+               for(ImmutableComponentPropertyContent p : content.properties.values()) {
+                       map.put(p.pi.name, new ImmutableComponentPropertyVariable(this, p));
+               }
+
+               return map;
+               
+       }
+       
+}
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableBuilder.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableBuilder.java
new file mode 100644 (file)
index 0000000..37c882c
--- /dev/null
@@ -0,0 +1,31 @@
+package org.simantics.modeling;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.StandardGraphChildVariable;
+import org.simantics.db.layer0.variable.StandardGraphPropertyVariable;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.VariableBuilder;
+import org.simantics.db.layer0.variable.VariableNode;
+
+public class ImmutableComponentVariableBuilder<Node> implements VariableBuilder<Node> {
+
+       @Override
+       public Variable buildChild(ReadGraph graph, Variable parent, VariableNode<Node> node, Resource child) throws DatabaseException {
+               if(graph.isImmutable(child)) {
+                       ImmutableComponentVariableContent content = graph.syncRequest(new ImmutableComponentVariableContentRequest(child), TransientCacheListener.instance());
+                       return new ImmutableComponentVariable(parent, content);
+               } else {
+                       return new StandardGraphChildVariable(parent, node, child);
+               }
+       }
+
+       @Override
+       public Variable buildProperty(ReadGraph graph, Variable parent, VariableNode<Node> node, Resource subject, Resource predicate) throws DatabaseException {
+               return new StandardGraphPropertyVariable(graph, parent, node, subject, predicate);
+       }
+
+}
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContent.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContent.java
new file mode 100644 (file)
index 0000000..5124228
--- /dev/null
@@ -0,0 +1,19 @@
+package org.simantics.modeling;
+
+import java.util.Map;
+
+import org.simantics.db.Resource;
+
+public class ImmutableComponentVariableContent {
+
+       final public Resource resource;
+       final public String name;
+       public Map<String,ImmutableComponentVariableContent> children;
+       public Map<String,ImmutableComponentPropertyContent> properties;
+       
+       ImmutableComponentVariableContent(Resource resource, String name) {
+               this.resource = resource;
+               this.name = name;
+       }
+       
+}
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContentRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ImmutableComponentVariableContentRequest.java
new file mode 100644 (file)
index 0000000..ac08c94
--- /dev/null
@@ -0,0 +1,75 @@
+package org.simantics.modeling;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.ResourceRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.PropertyInfo;
+import org.simantics.db.layer0.request.UnescapedPropertyMapOfResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.structural2.ConnectionImpl;
+import org.simantics.structural2.Functions.StructuralChildMapOfResource;
+import org.simantics.structural2.queries.ConnectionPointMapOfResource;
+
+public class ImmutableComponentVariableContentRequest extends ResourceRead<ImmutableComponentVariableContent> {
+
+       protected ImmutableComponentVariableContentRequest(Resource resource) {
+               super(resource);
+       }
+       
+       @Override
+       public ImmutableComponentVariableContent perform(ReadGraph graph) throws DatabaseException {
+               
+               Layer0 L0 = Layer0.getInstance(graph);
+               String name = graph.getRelatedValue(resource, L0.HasName, Bindings.STRING);
+               ImmutableComponentVariableContent result = new ImmutableComponentVariableContent(resource, name);
+               
+               Map<String,PropertyInfo> pis = graph.syncRequest(new UnescapedPropertyMapOfResource(resource));
+               
+               for(Map.Entry<String, PropertyInfo> e : pis.entrySet()) {
+                       PropertyInfo pi = e.getValue();
+                       if(pi.isHasProperty) {
+                               ImmutableComponentPropertyContent pc = graph.syncRequest(new ImmutableComponentPropertyContentRequest(resource, pi));
+                               if(pc != null) {
+                                       if(result.properties == null) result.properties = new HashMap<>();
+                                       result.properties.put(pc.pi.name, pc);
+                               }
+                       }
+               }
+
+               Map<String,PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, resource));
+               for(Map.Entry<String, PropertyInfo> e : cps.entrySet()) {
+                       PropertyInfo pi = e.getValue();
+                       Resource conn = graph.getPossibleObject(resource, pi.predicate);
+                       if(conn != null) {
+                               if(result.properties == null) result.properties = new HashMap<>();
+                               result.properties.put(pi.name, new ImmutableComponentPropertyContent(pi, conn, new ConnectionImpl(pi.predicate), null));
+                       }
+               }
+               
+               HashSet<Resource> childSet = null;
+               for(Resource child : graph.syncRequest(new StructuralChildMapOfResource(resource)).values()) {
+                       if(childSet == null)
+                               childSet = new HashSet<>();
+                       childSet.add(child);
+               }
+               
+               if(childSet != null) {
+                       result.children = new HashMap<>();
+                       for(Resource child : childSet) {
+                               ImmutableComponentVariableContent content = graph.syncRequest(new ImmutableComponentVariableContentRequest(child)); 
+                               result.children.put(content.name, content);
+                       }
+               }
+               
+               return result;
+               
+       }
+
+       
+}
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/AnalyseSCLValueRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/AnalyseSCLValueRequest.java
new file mode 100644 (file)
index 0000000..f1149f9
--- /dev/null
@@ -0,0 +1,42 @@
+package org.simantics.modeling.scl;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.scl.ExpressionAnalysis;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.structural2.scl.AnalyseStructuralValueRequest;
+
+public class AnalyseSCLValueRequest extends AnalyseStructuralValueRequest {
+
+    public AnalyseSCLValueRequest(ReadGraph graph, Resource component, Resource value, Resource predicate)
+            throws DatabaseException {
+        super(component, value, predicate);
+    }
+
+    @Override
+    protected ExpressionAnalysis<Variable> getAnalysis(AnalysisCompilationContext context, Function1<Variable, Object> fn) {
+       return new ExpressionAnalysis(fn, context.getConsumed());
+    }
+    
+    public static ExpressionAnalysis analyse(ReadGraph graph, Resource component, Resource predicate, Resource value) throws DatabaseException {
+        SCLContext sclContext = SCLContext.getCurrent();
+        Object oldGraph = sclContext.get("graph");
+        try {
+            ExpressionAnalysis result = graph.syncRequest(new AnalyseSCLValueRequest(graph, component, value, predicate),
+                    TransientCacheListener.<ExpressionAnalysis<Variable>>instance());
+            sclContext.put("graph", graph);
+            return result;
+        } catch (DatabaseException e) {
+            throw (DatabaseException)e;
+        } catch (Throwable t) {
+            throw new DatabaseException(t);
+        } finally {
+            sclContext.put("graph", oldGraph);
+        }
+    }
+    
+}
index 9c7428416531a2da02c33d9ac10c895736a4797c..4847eb55139ac8a772753087b6a7867efde7bf41 100644 (file)
@@ -91,7 +91,7 @@ public class Synchronizer {
         for(Variable conn : child.getProperties(graph, StructuralResource2.URIs.SynchronizedConnectionRelation)) {
             String name = conn.getName(graph);
             org.simantics.structural2.variables.Connection vc = conn.getValue(graph);
-            Collection<VariableConnectionPointDescriptor> connectionPoints = vc.getConnectionPointDescriptors(graph, null);
+            Collection<VariableConnectionPointDescriptor> connectionPoints = vc.getConnectionPointDescriptors(graph, child, null);
             List<String> cps = new ArrayList<String>(connectionPoints.size());
             for(VariableConnectionPointDescriptor desc : connectionPoints) {
                if(desc.isFlattenedFrom(graph, conn)) continue;
index 33b0ec14713945bfbd30b2460a91bdc886a47ef7..c33e7ae9d2d32535a0aa1a09c2deba8daf9586da 100644 (file)
@@ -13,4 +13,4 @@ importJava "org.simantics.structural2.variables.Connection" where
   data StructuralConnection
 
 importJava "org.simantics.structural2.utils.StructuralUtils" where
-  structuralConnectionConnectionPoints :: StructuralConnection -> Resource -> <ReadGraph> [Variable]
+  structuralConnectionConnectionPoints :: Variable -> StructuralConnection -> Resource -> <ReadGraph> [Variable]
diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/ConnectionImpl.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/ConnectionImpl.java
new file mode 100644 (file)
index 0000000..e67851f
--- /dev/null
@@ -0,0 +1,72 @@
+package org.simantics.structural2;
+
+import java.util.Collection;
+import java.util.Set;
+
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.structural2.variables.Connection;
+import org.simantics.structural2.variables.ConnectionBrowser;
+import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
+
+import gnu.trove.set.hash.THashSet;
+
+public class ConnectionImpl implements Connection {
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((predicate == null) ? 0 : predicate.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               ConnectionImpl other = (ConnectionImpl) obj;
+               if (predicate == null) {
+                       if (other.predicate != null)
+                               return false;
+               } else if (!predicate.equals(other.predicate))
+                       return false;
+               return true;
+       }
+
+       final private Resource predicate;
+       
+       public ConnectionImpl(Resource predicate) {
+               this.predicate = predicate;
+       }
+       
+       @Override
+       public Collection<Variable> getConnectionPoints(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException {
+           Set<Variable> result = new THashSet<Variable>();
+           for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, predicate, relationType)) {
+               result.add(desc.getVariable(graph));
+           }
+           return result;
+       }
+       
+       @Override
+       public Collection<String> getConnectionPointURIs(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException {
+           Set<String> result = new THashSet<String>();
+           for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, component, predicate, relationType)) {
+               result.add(desc.getURI(graph));
+           }
+           return result;
+       }
+
+       @Override
+       public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException {
+           return ConnectionBrowser.flatten(graph, component, predicate, relationType);
+       }
+
+}
\ No newline at end of file
index d9d8857af77210acfa2be0f1d170981f547ca2a5..19c2e8c800d2562a5fbfdfa519ad33d37157edd7 100644 (file)
@@ -67,13 +67,10 @@ import org.simantics.structural2.queries.PossibleConnectionPointInfo;
 import org.simantics.structural2.scl.CompileStructuralValueRequest;
 import org.simantics.structural2.scl.procedural.CompileProceduralComponentTypeRequest;
 import org.simantics.structural2.variables.Connection;
-import org.simantics.structural2.variables.ConnectionBrowser;
 import org.simantics.structural2.variables.StandardProceduralChildVariable;
-import org.simantics.structural2.variables.VariableConnectionPointDescriptor;
 import org.simantics.utils.datastructures.MapList;
 
 import gnu.trove.map.hash.THashMap;
-import gnu.trove.set.hash.THashSet;
 
 public class Functions {
        
@@ -153,39 +150,6 @@ public class Functions {
                
        };
        
-       static class ConnectionImpl implements Connection {
-
-               final private StandardGraphPropertyVariable connectionPoint;
-               
-               public ConnectionImpl(StandardGraphPropertyVariable connectionPoint) {
-                       this.connectionPoint = connectionPoint;
-               }
-               
-               @Override
-               public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
-                   Set<Variable> result = new THashSet<Variable>();
-                   for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {
-                       result.add(desc.getVariable(graph));
-                   }
-                   return result;
-               }
-               
-               @Override
-               public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
-                   Set<String> result = new THashSet<String>();
-                   for(VariableConnectionPointDescriptor desc : ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType)) {
-                       result.add(desc.getURI(graph));
-                   }
-                   return result;
-               }
-
-               @Override
-               public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
-                   return ConnectionBrowser.flatten(graph, connectionPoint.parent, connectionPoint.property.predicate, relationType);
-               }
-
-       }
-       
        @SCLValue(type="ValueAccessor")
        public static final ValueAccessor connectionValueAccessor = new ValueAccessor() {
 
@@ -213,7 +177,7 @@ public class Functions {
                @Override
                public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
                        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; 
-                       return new ConnectionImpl(variable);
+                       return new ConnectionImpl(variable.property.predicate);
                }
 
                @Override
@@ -233,10 +197,10 @@ public class Functions {
        
                public Variable getPossibleConnectionPointFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
 
-                       Map<String, Resource> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());
-                       Resource cp = connectionPoints.get(name);
+                       Map<String, PropertyInfo> connectionPoints = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
+                       PropertyInfo cp = connectionPoints.get(name);
                        if(cp == null) return null;
-                       else return new StandardGraphPropertyVariable(graph, variable, cp);
+                       else return new StandardGraphPropertyVariable(graph, variable, cp.predicate);
                        
                }
                
@@ -244,16 +208,16 @@ public class Functions {
                        
                        if(graph.isImmutable(context)) {
 
-                               Map<String, Resource> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,Resource>>instance());
+                               Map<String, PropertyInfo> cps = graph.syncRequest(new ConnectionPointMapOfResource(graph, context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
                                if(cps.size() == 0) return map;
                                
                                if(map == null) map = new THashMap<String,Variable>(cps.size());
                                
-                               for(Map.Entry<String, Resource> entry : cps.entrySet()) {
+                               for(Map.Entry<String, PropertyInfo> entry : cps.entrySet()) {
                                        String name = entry.getKey();
-                                       Resource cp = entry.getValue();
-                                       if(needSynchronized && !graph.isInstanceOf(cp, STR.SynchronizedConnectionRelation)) continue;
-                                       map.put(name, new StandardGraphPropertyVariable(graph, variable, cp));
+                                       PropertyInfo cp = entry.getValue();
+                                       if(needSynchronized && !graph.isInstanceOf(cp.predicate, STR.SynchronizedConnectionRelation)) continue;
+                                       map.put(name, new StandardGraphPropertyVariable(graph, variable, cp.predicate));
                                }
                                
                                return map;
@@ -313,7 +277,7 @@ public class Functions {
                
        };
 
-       static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
+       public static class StructuralChildMapOfResource extends ResourceRead<Map<String, Resource>> {
 
                public StructuralChildMapOfResource(Resource resource) {
                        super(resource);
@@ -337,7 +301,7 @@ public class Functions {
 
        }
 
-    static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
+    public static class StructuralChildMapOfResourceT extends ResourceRead<Map<String, Resource>> {
 
         public StructuralChildMapOfResourceT(Resource resource) {
             super(resource);
index 3b2e42ae77f184f9e77bd141a9eef634eb495a9f..d7ba2901bc09bfe814b1fbace9a3ff91b8803908 100644 (file)
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.THashMap;
 
-public class ConnectionPointMapOfResource extends TransientResourceRead<Map<String, Resource>> {
+public class ConnectionPointMapOfResource extends TransientResourceRead<Map<String, PropertyInfo>> {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionPointMapOfResource.class);
 
@@ -41,18 +41,18 @@ public class ConnectionPointMapOfResource extends TransientResourceRead<Map<Stri
        }
 
        @Override
-       public Map<String,Resource> perform(ReadGraph graph, Resource resource) throws DatabaseException {
+       public Map<String,PropertyInfo> perform(ReadGraph graph, Resource resource) throws DatabaseException {
            
                Collection<Resource> predicates = graph.getPredicates(resource);
                
-               THashMap<String,Resource> result = null;
+               THashMap<String,PropertyInfo> result = null;
                
                for(Resource predicate : predicates) {
                        
                        PropertyInfo info = graph.syncRequest(new PossibleConnectionPointInfo(predicate), TransientCacheAsyncListener.<PropertyInfo>instance());
                        if(info != null) {
-                               if (result == null) result = new THashMap<String,Resource>(predicates.size());
-                               if (result.put(info.name, predicate) != null)
+                               if (result == null) result = new THashMap<String,PropertyInfo>(predicates.size());
+                               if (result.put(info.name, info) != null)
                                    LOGGER.error("The database contains siblings with the same name " + info.name + " (resource=$" + resource.getResourceId() + ").");
                        }                               
                        
diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AbstractAnalyseStructuralValueRequest.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AbstractAnalyseStructuralValueRequest.java
new file mode 100644 (file)
index 0000000..48c95cd
--- /dev/null
@@ -0,0 +1,154 @@
+package org.simantics.structural2.scl;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.request.PossibleIndexRoot;
+import org.simantics.db.common.request.ResourceRead2;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.scl.AbstractExpressionAnalysisRequest;
+import org.simantics.db.layer0.scl.AbstractExpressionCompilationContext;
+import org.simantics.db.layer0.util.RuntimeEnvironmentRequest;
+import org.simantics.db.layer0.util.RuntimeEnvironmentRequest2;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.compiler.elaboration.expressions.EApply;
+import org.simantics.scl.compiler.elaboration.expressions.EConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EVariable;
+import org.simantics.scl.compiler.elaboration.expressions.Expression;
+import org.simantics.scl.compiler.elaboration.modules.SCLValue;
+import org.simantics.scl.compiler.environment.Environment;
+import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
+import org.simantics.scl.compiler.top.SCLExpressionCompilationException;
+import org.simantics.scl.compiler.types.Type;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.structural2.scl.AbstractAnalyseStructuralValueRequest.AnalysisCompilationContext;
+
+/**
+ * Compiles an SCL expression that is attached to a literal
+ * whose parent is a component that is a part of a component type.
+ * 
+ * @author Antti Villberg
+ */
+abstract public class AbstractAnalyseStructuralValueRequest extends AbstractExpressionAnalysisRequest<AnalysisCompilationContext, Variable> {
+    
+    protected final Resource relation;
+    
+    public static class AnalysisCompilationContext extends AbstractExpressionCompilationContext {
+
+       final private Map<String, ComponentTypeProperty> propertyMap;
+       final private Set<String> consumed = new HashSet<>();
+       
+        public AnalysisCompilationContext(RuntimeEnvironment runtimeEnvironment,
+                Map<String, ComponentTypeProperty> propertyMap) {
+            super(runtimeEnvironment);
+            this.propertyMap = propertyMap;
+        }
+        
+        public ComponentTypeProperty consume(String name) {
+               consumed.add(name);
+               return propertyMap.get(name);
+        }
+        
+        public Set<String> getConsumed() {
+               return consumed;
+        }
+        
+    }
+    
+    public AbstractAnalyseStructuralValueRequest(Resource relation) {
+        this.relation = relation;
+    }
+
+    @Override
+    abstract protected String getExpressionText(ReadGraph graph) throws DatabaseException;
+    abstract protected Resource getIndexRoot(ReadGraph graph) throws DatabaseException;
+    abstract protected Resource getComponentType(ReadGraph graph) throws DatabaseException;
+    
+    @Override
+    protected Type getExpectedType(ReadGraph graph, AnalysisCompilationContext context)
+            throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        String valueType = graph.getPossibleRelatedValue(relation, L0.RequiresValueType, Bindings.STRING);
+        if(valueType != null) {
+            Resource relationIndexRoot = graph.syncRequest(new PossibleIndexRoot(relation));
+            RuntimeEnvironment relationRuntimeEnvironment = relationIndexRoot != null ? graph.syncRequest(new RuntimeEnvironmentRequest(relationIndexRoot)) : context.runtimeEnvironment;
+            try {
+                return Environments.getType(relationRuntimeEnvironment.getEnvironment(), valueType);
+            } catch (SCLExpressionCompilationException e) {
+                e.printStackTrace();
+            }
+        }
+        return super.getExpectedType(graph, context);
+    }
+    
+    
+
+    @Override
+    protected AnalysisCompilationContext getCompilationContext(ReadGraph graph)
+            throws DatabaseException {
+        Resource indexRoot = getIndexRoot(graph);
+        Resource componentType = getComponentType(graph);
+        if(componentType == null) {
+            RuntimeEnvironment runtimeEnvironment = graph.syncRequest(new RuntimeEnvironmentRequest(indexRoot));
+            return new AnalysisCompilationContext(runtimeEnvironment, Collections.<String,ComponentTypeProperty>emptyMap());
+        } else {
+               return graph.syncRequest(new ResourceRead2<AnalysisCompilationContext>(componentType, indexRoot) {
+                   @Override
+                   public AnalysisCompilationContext perform(ReadGraph graph)
+                           throws DatabaseException {
+                       RuntimeEnvironment runtimeEnvironment = graph.syncRequest(new RuntimeEnvironmentRequest2(resource, resource2));
+                       Map<String, ComponentTypeProperty> propertyMap =
+                               graph.syncRequest(new ReadComponentTypeInterfaceRequest(resource, runtimeEnvironment.getEnvironment()),
+                                       TransientCacheListener.<Map<String, ComponentTypeProperty>>instance());
+                       return new AnalysisCompilationContext(runtimeEnvironment, propertyMap);
+                   }
+               });
+        }
+    }
+
+    @Override
+    protected Type getContextVariableType() {
+        return VARIABLE; 
+    }
+
+    protected static Expression accessInputVariable(Environment environment,
+            org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable) {
+        SCLValue variableParentFunction = environment.getValue(VARIABLE_PARENT);
+        return new EApply(new EConstant(variableParentFunction),
+                new EApply(new EConstant(variableParentFunction),
+                        new EVariable(contextVariable)));
+    }
+    
+    @Override
+    protected Expression getVariableAccessExpression(
+            ReadGraph graph,
+            AnalysisCompilationContext context,
+            org.simantics.scl.compiler.elaboration.expressions.Variable contextVariable,
+            String name) throws DatabaseException {
+        ComponentTypeProperty property = context.consume(name);
+        if(property != null) {
+            Environment environment = context.runtimeEnvironment.getEnvironment();
+            return getPropertyFlexible(environment,
+                    accessInputVariable(environment, contextVariable),
+                    name,
+                    property.type);
+        }
+        else if(name.equals("input")) {
+            Environment environment = context.runtimeEnvironment.getEnvironment();
+            return accessInputVariable(environment, contextVariable);
+        }
+        else if(name.equals("self"))
+            return new EVariable(contextVariable);
+        else
+            return null;
+    }
+    
+}
diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AnalyseStructuralValueRequest.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/AnalyseStructuralValueRequest.java
new file mode 100644 (file)
index 0000000..8e37f87
--- /dev/null
@@ -0,0 +1,103 @@
+package org.simantics.structural2.scl;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.TransientCacheListener;
+import org.simantics.db.common.request.IndexRoot;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.scl.ExpressionAnalysis;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.runtime.SCLContext;
+
+/**
+ * Compiles an SCL expression that is attached to a literal
+ * whose parent is a component that is a part of a component type.
+ * 
+ * @author Hannu Niemist&ouml;
+ */
+public class AnalyseStructuralValueRequest extends AbstractAnalyseStructuralValueRequest {
+    
+    protected final Resource component;
+    protected final Resource literal;
+    
+    public AnalyseStructuralValueRequest(Resource component, Resource literal, Resource relation) {
+       super(relation);
+        this.component = component;
+        this.literal = literal;
+    }
+    
+//    public AnalyseStructuralValueRequest(ReadGraph graph, Variable context) throws DatabaseException {
+//        this(context.getParent(graph).getRepresents(graph),
+//                context.getRepresents(graph),
+//                context.getPredicateResource(graph));
+//    }
+    
+//    public static Object compileAndEvaluate(ReadGraph graph, Variable context) throws DatabaseException {
+//        SCLContext sclContext = SCLContext.getCurrent();
+//        Object oldGraph = sclContext.get("graph");
+//        AnalyseStructuralValueRequest request = new AnalyseStructuralValueRequest(graph, context);
+//        try {
+//            ExpressionAnalysis result = graph.syncRequest(request, TransientCacheListener.<ExpressionAnalysis<Variable>>instance());
+//            sclContext.put("graph", graph);
+//            return result;
+//        } catch (Throwable t) {
+//            throw new DatabaseException("Compiling structural value request for component=" + request.component + ", literal=" + request.literal + " and relation " + request.relation + " failed!", t);
+//        } finally {
+//            sclContext.put("graph", oldGraph);
+//        }
+//    }
+    
+    @Override
+    protected String getExpressionText(ReadGraph graph)
+            throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        return graph.getRelatedValue(literal, L0.SCLValue_expression, Bindings.STRING);
+    }
+
+    @Override
+    protected Resource getIndexRoot(ReadGraph graph) throws DatabaseException {
+       return graph.syncRequest(new IndexRoot(literal));
+    }
+
+    @Override
+    protected Resource getComponentType(ReadGraph graph)
+               throws DatabaseException {
+       // This is possible e.g. for interface expressions inside procedurals
+       if(component == null) return null;
+       return graph.syncRequest(new FindPossibleComponentTypeRequest(component));
+    }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((component == null) ? 0 : component.hashCode());
+               result = prime * result + ((literal == null) ? 0 : literal.hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (getClass() != obj.getClass())
+                       return false;
+               AnalyseStructuralValueRequest other = (AnalyseStructuralValueRequest) obj;
+               if (component == null) {
+                       if (other.component != null)
+                               return false;
+               } else if (!component.equals(other.component))
+                       return false;
+               if (literal == null) {
+                       if (other.literal != null)
+                               return false;
+               } else if (!literal.equals(other.literal))
+                       return false;
+               return true;
+       }
+       
+}
index 9a77d100fca3ded3b6924aee9915d05119f52ecb..3181dd7c45d7ea2434eed586393a2d2c7127c5b2 100644 (file)
@@ -265,7 +265,7 @@ public class StructuralUtils {
        if(property == null) return null;
        Connection conn = property.getPossibleValue(graph);
        if(conn == null) return null;
-       Collection<Variable> cps = conn.getConnectionPoints(graph, null);
+       Collection<Variable> cps = conn.getConnectionPoints(graph, component, null);
        if(cps.size() == 2) {
                for(Variable var : cps) {
                        if(property.equals(var)) continue;
@@ -287,8 +287,8 @@ public class StructuralUtils {
                 ;
     }
     
-    public static List<Variable> structuralConnectionConnectionPoints(ReadGraph graph, Connection conn, Resource relationType) throws DatabaseException {
-       return new ArrayList<Variable>(conn.getConnectionPoints(graph, relationType));
+    public static List<Variable> structuralConnectionConnectionPoints(ReadGraph graph, Variable component, Connection conn, Resource relationType) throws DatabaseException {
+       return new ArrayList<Variable>(conn.getConnectionPoints(graph, component, relationType));
     }
 
 }
index b404932e7a58c6d59bd98917c30dee81df36d788..b729d1f7747ff77349a385ca8f227025a2b59b17 100644 (file)
@@ -13,13 +13,13 @@ public interface Connection {
      * Return absolute URIs of the connection points. An optional (may be null) relationType may be used
      * to filter the returned connection points.
      */
-       Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException;
+       Collection<String> getConnectionPointURIs(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException;
     /**
      * Return the connection points. An optional (may be null) relationType may be used
      * to filter the returned connection points.
      */
-       Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException;
+       Collection<Variable> getConnectionPoints(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException;
        
-       Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException;
+       Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Variable component, Resource relationType) throws DatabaseException;
 
 }
index f133adee02e3c783b7e7fe5b8dc12ef93a6a4d5a..62d574633b8d948154b4804d997b9a6ef4da3b45 100644 (file)
@@ -75,7 +75,7 @@ public class StandardProceduralChildVariable extends AbstractChildVariable {
         }
         
         @Override
-        public Collection<Variable> getConnectionPoints(ReadGraph graph, Resource relationType) throws DatabaseException {
+        public Collection<Variable> getConnectionPoints(ReadGraph graph, Variable component_, Resource relationType) throws DatabaseException {
                
                Set<Variable> result = new THashSet<Variable>();
             for(Pair<String,Resource> cp : cps) {
@@ -93,7 +93,7 @@ public class StandardProceduralChildVariable extends AbstractChildVariable {
         }
         
                @Override
-               public Collection<String> getConnectionPointURIs(ReadGraph graph, Resource relationType) throws DatabaseException {
+               public Collection<String> getConnectionPointURIs(ReadGraph graph, Variable component_, Resource relationType) throws DatabaseException {
                        
                Set<String> result = new THashSet<String>();
             for(Pair<String,Resource> cp : cps) {
@@ -111,7 +111,7 @@ public class StandardProceduralChildVariable extends AbstractChildVariable {
                }
                
                @Override
-               public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Resource relationType) throws DatabaseException {
+               public Collection<VariableConnectionPointDescriptor> getConnectionPointDescriptors(ReadGraph graph, Variable component_, Resource relationType) throws DatabaseException {
                        
                Set<VariableConnectionPointDescriptor> result = new THashSet<VariableConnectionPointDescriptor>();
             for(Pair<String,Resource> cp : cps) {
index 59c22464375383ef51b34e2c4080e9c80a8b8937..be715fa9afe6647e558316949f2a4ac1849f290b 100644 (file)
          id="org.simantics.scl.rest.feature"
          version="0.0.0"/>
 
+   <includes
+         id="fi.semantum.simupedia"
+         version="0.0.0"/>
+
    <plugin
          id="org.simantics.desktop.product"
          download-size="0"