]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java
Fix non-compiling ReadGraphImpl.hasStatement implementation
[simantics/platform.git] / bundles / org.simantics.db.impl / src / org / simantics / db / impl / graph / ReadGraphImpl.java
index 77af46d557e740e8d73e4bc9c9252b2adb7e7a98..2309af76440b10bc2a3e9d336cf2fc4bdfc14819 100644 (file)
@@ -18,7 +18,6 @@ import java.io.IOException;
 import java.io.PrintStream;
 import java.lang.reflect.Array;
 import java.lang.reflect.InvocationTargetException;
-import java.nio.BufferUnderflowException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -46,10 +45,12 @@ import org.simantics.databoard.type.Datatype;
 import org.simantics.databoard.util.binary.BinaryFile;
 import org.simantics.databoard.util.binary.RandomAccessBinary;
 import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.ComputationalValue;
 import org.simantics.db.DevelopmentKeys;
 import org.simantics.db.ExternalValueSupport;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.RelationContext;
+import org.simantics.db.RelationInfo;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.Statement;
@@ -135,7 +136,6 @@ import org.simantics.db.exception.NoSingleResultException;
 import org.simantics.db.exception.ResourceNotFoundException;
 import org.simantics.db.exception.ServiceException;
 import org.simantics.db.exception.ValidationException;
-import org.simantics.db.impl.BlockingAsyncProcedure;
 import org.simantics.db.impl.RelationContextImpl;
 import org.simantics.db.impl.ResourceImpl;
 import org.simantics.db.impl.internal.RandomAccessValueSupport;
@@ -1107,9 +1107,10 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                assert (subject != null);
 
+               byte[] bytes = null;
                try {
                        
-                       byte[] bytes = processor.getValue(this, subject);
+                       bytes = processor.getValue(this, subject);
                        if (bytes == null) throw new DoesNotContainValueException("No value for resource " + subject);
 
                        Serializer serializer = getSerializer(binding);
@@ -1119,20 +1120,9 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                        throw new DoesNotContainValueException(e);
 
-               } catch (IOException e) {
-
-                       throw new ServiceException(e);
-
-               } catch (DatabaseException e) {
-                   
-            throw new ServiceException(e);
-            
-        } catch (BufferUnderflowException e) {
-            // This is sometimes thrown when deserialize fails because wrong format.
-            // For callers of this method this is just an service exception.
-            throw new ServiceException(e);
-        }
-
+               } catch (Throwable t) {
+                       throw new ServiceException("Could not getValue for subject " + debugString(subject) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(bytes), t);
+               }
        }
 
        @Override
@@ -1360,7 +1350,10 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                Statement stm = getSingleStatement(resource, relation);
                
-               return adaptContextual(stm.getObject(), new RelationContextImpl(resource, stm), RelationContext.class, clazz);
+               Object o = adaptContextual(stm.getObject(), new RelationContextImpl(resource, stm), RelationContext.class, clazz);
+               if (clazz.isInstance(o))
+                       return (T)o;
+               throw new AdaptionException("Returned value is not expected class , got " + o.getClass().getName()+ " , expected " + clazz.getName());
                
        }
 
@@ -1522,15 +1515,15 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                try {
 
-                   int result = processor.getSingleObject(this, subject, relation);
-                   if(result == 0) return null;
-                   
-                   return processor.querySupport.getResource(result);
+                       int result = processor.getSingleObject(this, subject, relation);
+                       if(result == 0) return null;
+
+                       return processor.querySupport.getResource(result);
 
-            } catch (ManyObjectsForFunctionalRelationException e) {
+               } catch (ManyObjectsForFunctionalRelationException e) {
+
+                       throw new ManyObjectsForFunctionalRelationException("Many objects in " + subject + " for functional relation " + relation);
 
-                throw new ManyObjectsForFunctionalRelationException("subject=" + subject + ", relation=" + relation, e);
-                
                } catch (DatabaseException e) {
 
                        throw new ServiceException(e);
@@ -1857,13 +1850,42 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                try {
 
-                       Collection<Resource> objects = getObjects(subject, relation);
-                       return !objects.isEmpty();
+                       RelationInfo rinfo = processor.getRelationInfo(this, relation);
+                       Collection<Resource> predicates = getPredicates(subject);
+
+                       if (rinfo.isFinal) {
+
+                               return predicates.contains(relation);
+
+                       } else if (rinfo.isFunctional) {
+
+                               try {
+                                       return processor.getSingleObject(this, subject, relation) != 0;
+                               } catch (ManyObjectsForFunctionalRelationException e) {
+                                       return true;
+                               } catch (DatabaseException e) {
+                                       throw new ServiceException(e);
+                               }
+
+                       } else {
+
+                               for (Resource predicate : getPredicates(subject)) {
+                                       if (isSubrelationOf(predicate, relation))
+                                               return true;
+                               }
+
+                       }
+
+                       return false;
 
                } catch (ServiceException e) {
 
                        throw new ServiceException(e);
 
+               } catch (DatabaseException e) {
+
+                       throw new ServiceException(INTERNAL_ERROR_STRING, e);
+
                } 
                
        }
@@ -1931,11 +1953,11 @@ public class ReadGraphImpl implements AsyncReadGraph {
         * Implementation of the interface RequestProcessor
         */
 
-       @Override
-       public <T> T syncRequest(final Read<T> request) throws DatabaseException {
-               assert (request != null);
-               return (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true);
-       }
+    @Override
+    public <T> T syncRequest(final Read<T> request) throws DatabaseException {
+        assert (request != null);
+        return (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true);
+    }
 
        @Override
        public <T> T syncRequest(Read<T> request, SyncListener<T> procedure)
@@ -1949,16 +1971,12 @@ public class ReadGraphImpl implements AsyncReadGraph {
                return syncRequest(request, new NoneToAsyncListener<T>(procedure));
        }
 
-       @Override
-       public <T> T syncRequest(final Read<T> request, final AsyncProcedure<T> procedure) throws DatabaseException {
-
-               assert (request != null);
-
-               ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
-
-               return QueryCache.resultReadEntry(this, request, parent, listener, procedure);
-
-       }
+    @Override
+    public <T> T syncRequest(final Read<T> request, final AsyncProcedure<T> procedure) throws DatabaseException {
+        assert (request != null);
+        ListenerBase listener = procedure != null ? getListenerBase(procedure) : null;
+        return (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true);
+    }
 
        @Override
        public <T> T syncRequest(final Read<T> request,
@@ -2034,19 +2052,13 @@ public class ReadGraphImpl implements AsyncReadGraph {
                return syncRequest(request, new NoneToAsyncListener<T>(procedure));
        }
 
-       @Override
-       final public <T> T syncRequest(final AsyncRead<T> request,
-                       final AsyncProcedure<T> procedure) throws DatabaseException {
-
-               assert (request != null);
-
-               ListenerBase listener = getListenerBase(procedure);
-
-//             BlockingAsyncProcedure<T> ap = new BlockingAsyncProcedure<>(this, procedure, request);
-               return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true);
-//             return ap.get();
-
-       }
+    @Override
+    final public <T> T syncRequest(final AsyncRead<T> request,
+            final AsyncProcedure<T> procedure) throws DatabaseException {
+        assert (request != null);
+        ListenerBase listener = getListenerBase(procedure);
+        return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); 
+    }
 
        @Override
        public <T> T syncRequest(AsyncRead<T> request,
@@ -3544,14 +3556,9 @@ public class ReadGraphImpl implements AsyncReadGraph {
 //                                     else
                                                procedure.execute(graph, (T) obj);
 
-                               } catch (IOException e) {
-                                       procedure.exception(graph, e);
-                               } catch (BufferUnderflowException e) {
-                                       procedure.exception(graph, e);
                                } catch (Throwable t) {
-                                       procedure.exception(graph, t);
+                                   procedure.exception(graph, new ServiceException("Could not forValue for subject " + debugString(resource) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(result), t));
                                }
-
                        }
 
                        @Override
@@ -3571,6 +3578,24 @@ public class ReadGraphImpl implements AsyncReadGraph {
                });
 
        }
+       
+    private static String safeArrayToString(byte[] a) {
+        if (a == null)
+            return "null";
+        int iMax = a.length - 1;
+        if (iMax == -1)
+            return "[]";
+
+        StringBuilder b = new StringBuilder();
+        b.append('[');
+        for (int i = 0; i < 100; i++) { // limit to first 100 items 
+            b.append(a[i]);
+            if (i == iMax)
+                return b.append(']').toString();
+            b.append(", ");
+        }
+        return b.append(", ... (" + a.length + ")]").toString();
+    }
 
        @Override
        public <T> void forValue(Resource subject, Binding binding,
@@ -4265,14 +4290,9 @@ public class ReadGraphImpl implements AsyncReadGraph {
                                        else
                                                procedure.execute(graph, (T) obj);
 
-                               } catch (IOException e) {
-                                       procedure.exception(graph, e);
-                               } catch (BufferUnderflowException e) {
-                                       procedure.exception(graph, e);
                                } catch (Throwable t) {
-                                       procedure.exception(graph, t);
+                                       procedure.exception(graph, new ServiceException("Could not forValue for subject " + debugString(resource) + " and binding " + String.valueOf(binding) + " with bytes " + safeArrayToString(result), t));
                                }
-
                        }
 
                        @Override
@@ -5154,8 +5174,12 @@ public class ReadGraphImpl implements AsyncReadGraph {
 
                assert (request != null);
                assert (procedure != null);
-       
-               processor.schedule(new SessionTask(this) {
+               
+               AsyncBarrierImpl barrier = asyncBarrier;
+               if(barrier != null)
+                   barrier.inc();
+               
+               processor.scheduleNow(new SessionTask(this) {
 
                        @Override
                        public void run0(int thread) {
@@ -5164,6 +5188,9 @@ public class ReadGraphImpl implements AsyncReadGraph {
                                        QueryCache.runnerReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false);
                                } catch (DatabaseException e) {
                                        Logger.defaultLogError(e);
+                               } finally {
+                               if(barrier != null)
+                                   barrier.dec();
                                }
                        }
                        
@@ -5228,28 +5255,55 @@ public class ReadGraphImpl implements AsyncReadGraph {
                asyncRequest(request, new NoneToAsyncListener<T>(procedure));
        }
 
-       @Override
-       final public <T> void asyncRequest(final AsyncRead<T> request,
-                       final AsyncProcedure<T> procedure) {
+    @Override
+    final public <T> void asyncRequest(final AsyncRead<T> request,
+            final AsyncProcedure<T> procedure) {
 
-               assert (request != null);
-               assert (procedure != null);
+        assert (request != null);
+        assert (procedure != null);
 
-               processor.schedule(new SessionTask(this) {
+        AsyncBarrierImpl barrier = asyncBarrier;
+        if(barrier != null)
+            barrier.inc();
 
-                       @Override
-                       public void run0(int thread) {
-                               try {
-                                       final ListenerBase listener = getListenerBase(procedure);
-                                       QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, procedure, false);
-                               } catch (DatabaseException e) {
-                                       Logger.defaultLogError(e);
-                               }
-                       }
-                       
-               });
+        processor.scheduleNow(new SessionTask(this) {
 
-       }
+            @Override
+            public void run0(int thread) {
+
+                if(barrier != null)
+                    barrier.inc();
+
+                try {
+                    final ListenerBase listener = getListenerBase(procedure);
+                    QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure<T>() {
+
+                        @Override
+                        public void execute(AsyncReadGraph graph, T result) {
+                            procedure.execute(graph, result);
+                            if(barrier != null)
+                                barrier.dec();
+                        }
+
+                        @Override
+                        public void exception(AsyncReadGraph graph, Throwable throwable) {
+                            procedure.exception(graph, throwable);
+                            if(barrier != null)
+                                barrier.dec();
+                        }
+
+                    }, false);
+                } catch (DatabaseException e) {
+                    LOGGER.error("Error while executing async request", e);
+                } finally {
+                    if(barrier != null)
+                        barrier.dec();
+                }
+            }
+
+        });
+
+    }
 
        @Override
        public <T> void asyncRequest(AsyncRead<T> request,
@@ -5629,28 +5683,44 @@ public class ReadGraphImpl implements AsyncReadGraph {
                this.parentGraph = parentGraph;
                this.parent = parent;
                this.processor = support;
-               this.asyncBarrier = new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent);
+               this.asyncBarrier = prepareBarrier(parentGraph, parent, null, false);
        }
 
+    ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, QueryProcessor support, AsyncBarrierImpl asyncBarrier) {
+        this.parentGraph = parentGraph;
+        this.parent = parent;
+        this.processor = support;
+        this.asyncBarrier = asyncBarrier;
+    }
+
        ReadGraphImpl(ReadGraphImpl graph, CacheEntry parent) {
                this(graph, parent, graph.processor);
        }
 
+    ReadGraphImpl(ReadGraphImpl parentGraph, CacheEntry parent, Runnable callback, boolean needsToBlock) {
+        this(parentGraph, parent, parentGraph.processor, prepareBarrier(parentGraph, parent, callback, needsToBlock));
+    }
+
+    static AsyncBarrierImpl prepareBarrier(ReadGraphImpl parentGraph, CacheEntry parent, Runnable callback, boolean needsToBlock) {
+        return new AsyncBarrierImpl(parentGraph != null ? parentGraph.asyncBarrier : null, parent, callback, needsToBlock);
+    }
+    
        ReadGraphImpl(ReadGraphImpl graph) {
                this(graph, graph.parent);
        }
 
-       public ReadGraphImpl withParent(CacheEntry parent) {
-               return new ReadGraphImpl(this, parent);
+       public ReadGraphImpl withParent(CacheEntry parent, Runnable callback, boolean needsToBlock) {
+               return new ReadGraphImpl(this, parent, callback, needsToBlock);
        }
 
        public ReadGraphImpl forRecompute(CacheEntry parent) {
                return new ReadGraphImpl(null, parent, processor);
        }
 
-       public static ReadGraphImpl create(QueryProcessor support) {
-               return new ReadGraphImpl(null, null, support);
-       }
+    public static ReadGraphImpl create(QueryProcessor support) {
+        ReadGraphImpl result = new ReadGraphImpl(null, null, support);
+        return result;
+    }
 
        public ReadGraphImpl newRestart(ReadGraphImpl impl) {
 
@@ -5917,6 +5987,8 @@ public class ReadGraphImpl implements AsyncReadGraph {
             }
             Serializer serializer = binding.serializer();
             byte[] bytes = serializer.serialize(initialValue);
+            // In case the file has been previously accessed and was larger we set the correct size now
+            rd.binaryFile.setLength(bytes.length);
             rd.binaryFile.write(bytes);
             ravs.put(resource, rd);
             return rd;
@@ -6106,12 +6178,18 @@ public class ReadGraphImpl implements AsyncReadGraph {
                        return getValue(r, binding);
                }
        } else if(types.contains(L0.ExternalValue)) {
-               try {
-                       return (T)ReflectionUtils.getValue(getURI(r)).getValue();
-               } catch(ValueNotFoundException e) {
-                       throw new DatabaseException(e);
-               } catch(ClassCastException e) {
-                       throw new DatabaseException(e);
+               ComputationalValue cv = syncRequest(new PossibleAdapter<ComputationalValue>(r, ComputationalValue.class), TransientCacheAsyncListener.instance());
+               if(cv != null) {
+                       return cv.getValue(this, r);
+               } else {
+                       // This should not even be possible since L0 defines an adapter for all values
+                       try {
+                               return (T)ReflectionUtils.getValue(getURI(r)).getValue();
+                       } catch(ValueNotFoundException e) {
+                               throw new DatabaseException(e);
+                       } catch(ClassCastException e) {
+                               throw new DatabaseException(e);
+                       }
                }
        }
        else {
@@ -6176,11 +6254,12 @@ public class ReadGraphImpl implements AsyncReadGraph {
     @Override
     public <T> T getRelatedValue2(Resource subject, Resource relation, Object context) throws DatabaseException {
                if(Development.DEVELOPMENT) {
-                       String error = L0Validations.checkValueType(this, subject, relation);
-                       if(error != null) {
-                               Logger.defaultLogError(new ValidationException(error));
-                               //throw new ValidationException(error);
-                               new ValidationException(error).printStackTrace();
+                       if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
+                               String error = L0Validations.checkValueType(this, subject, relation);
+                               if(error != null) {
+                                       Logger.defaultLogError(new ValidationException(error));
+                                       throw new ValidationException(error);
+                               }
                        }
                }
         return getValue2(getSingleObject(subject, relation), context);
@@ -6189,12 +6268,13 @@ public class ReadGraphImpl implements AsyncReadGraph {
     @Override
     public Variant getRelatedVariantValue2(Resource subject, Resource relation, Object context) throws DatabaseException {
         if(Development.DEVELOPMENT) {
-            String error = L0Validations.checkValueType(this, subject, relation);
-            if(error != null) {
-                Logger.defaultLogError(new ValidationException(error));
-                //throw new ValidationException(error);
-                new ValidationException(error).printStackTrace();
-            }
+                       if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
+                               String error = L0Validations.checkValueType(this, subject, relation);
+                               if(error != null) {
+                                       Logger.defaultLogError(new ValidationException(error));
+                                       throw new ValidationException(error);
+                               }
+                       }
         }
         return getVariantValue2(getSingleObject(subject, relation), context);
     }
@@ -6305,7 +6385,7 @@ public class ReadGraphImpl implements AsyncReadGraph {
     public boolean performPending() {
         return processor.performPending(this);
     }
-
+    
     public Set<ReadGraphImpl> ancestorSet() {
         HashSet<ReadGraphImpl> result = new HashSet<>();
         ReadGraphImpl g = this;
@@ -6315,5 +6395,35 @@ public class ReadGraphImpl implements AsyncReadGraph {
         }
         return result;
     }
+    
+    public int getLevel() {
+        return getLevelStatic(this);
+    }
+    
+    private static int getLevelStatic(ReadGraphImpl impl) {
+        if(impl == null) return 0;
+        else return 1 + getLevelStatic(impl.parentGraph);
+    }
+    
+    public boolean isParent(ReadGraphImpl impl) {
+        if(impl == null) return false;
+        if(this == impl) return true;
+        return isParent(impl.parentGraph);
+    }
+    
+    public ReadGraphImpl getTopLevelGraph() {
+        return getTopLevelGraphStatic(this);
+    }
+
+    private static ReadGraphImpl getTopLevelGraphStatic(ReadGraphImpl impl) {
+        if(impl.parentGraph == null) return impl;
+        else return getTopLevelGraphStatic(impl.parentGraph);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T l0() {
+        return (T) processor.getL0();
+    }
 
 }