]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Revert "Prime SCL BindingRegistry to shave ~0.5s from startup""
authorTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Tue, 7 Apr 2020 09:00:26 +0000 (09:00 +0000)
committerGerrit Code Review <gerrit2@simantics>
Tue, 7 Apr 2020 09:00:26 +0000 (09:00 +0000)
71 files changed:
.mvn/extensions.xml
bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartCopyHandler.java
bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartPreferencesAction.java [new file with mode: 0644]
bundles/org.simantics.charts/src/org/simantics/charts/editor/Messages.java [new file with mode: 0644]
bundles/org.simantics.charts/src/org/simantics/charts/editor/TimeSeriesEditor.java
bundles/org.simantics.charts/src/org/simantics/charts/editor/messages.properties [new file with mode: 0644]
bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java
bundles/org.simantics.db.common/src/org/simantics/db/common/processor/ProcessorBase.java
bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java
bundles/org.simantics.db.common/src/org/simantics/db/common/request/TransientResourceRead.java
bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/AsyncBarrierImpl.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/WriteGraphImpl.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/QueryListening.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/Scheduler.java [new file with mode: 0644]
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TaskList.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ContextualRelatedValue.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyResources.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java [new file with mode: 0644]
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QueryControlImpl.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplVirtual.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/State.java
bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java
bundles/org.simantics.db/src/org/simantics/db/RequestProcessor.java
bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java [new file with mode: 0644]
bundles/org.simantics.db/src/org/simantics/db/service/QueryControl.java
bundles/org.simantics.desktop.product/splash.svg
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/SimpleConnectionUtility.java
bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java
bundles/org.simantics.diagram/src/org/simantics/diagram/symbolcontribution/GroupProxySymbolItem.java
bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementReorder.java
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java
bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ZOrderHandler.java
bundles/org.simantics.gnuplot/pom.xml
bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java
bundles/org.simantics.history/src/org/simantics/history/csv/CSVFormatter.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/expression/InvertBasicExpressionVisitor.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/CSVPreferencePage.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java
bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java
bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitorBase.java [new file with mode: 0644]
bundles/org.simantics.modeling/src/org/simantics/modeling/ProceduralSubstructureMapRequest.java
bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java
bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF
bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java [new file with mode: 0644]
bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java
bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java
bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java
bundles/org.simantics.simulator.variable/src/org/simantics/simulator/variable/NodeManager.java
bundles/org.simantics.trend/src/org/simantics/trend/impl/HorizRuler.java
features/org.simantics.sdk.feature/feature.xml
releng/org.simantics.sdk.build.targetdefinition/simantics.target
releng/org.simantics.sdk.build.targetdefinition/simantics.tpd
releng/org.simantics.sdk.repository/pom.xml
releng/org.simantics.tycho.configuration/pom.xml

index 3b43bdfdd6c475790cc5db2e38b62ad33da8875d..e73295bbd2337b55a005ac88ba80e22d00981d46 100644 (file)
@@ -3,6 +3,6 @@
   <extension>
     <groupId>org.eclipse.tycho.extras</groupId>
     <artifactId>tycho-pomless</artifactId>
-    <version>1.5.0</version>
+    <version>1.6.0</version>
   </extension>
 </extensions> 
index 65108d6f7a4ab4e3dde7d664d2e147ffdbff2584..183000045aed17cd3f2f6b44ed60fe834e1f8292 100644 (file)
@@ -1,6 +1,6 @@
 /*******************************************************************************
- * Copyright (c) 2011 Association for Decentralized Information Management in
- * Industry THTH ry.
+ * Copyright (c) 2011,2020 Association for Decentralized Information Management
+ * in Industry THTH ry.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -8,6 +8,7 @@
  *
  * Contributors:
  *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - #501
  *******************************************************************************/
 package org.simantics.charts.editor;
 
@@ -33,11 +34,14 @@ import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.jface.action.IStatusLineManager;
 import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.window.Window;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IEditorPart;
 import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.dialogs.PreferencesUtil;
 import org.eclipse.ui.handlers.HandlerUtil;
 import org.eclipse.ui.preferences.ScopedPreferenceStore;
 import org.simantics.charts.ui.CSVProgressMonitor;
@@ -74,8 +78,28 @@ public class ChartCopyHandler extends AbstractHandler {
         IStatusLineManager status = editor.getEditorSite().getActionBars().getStatusLineManager();
         final Shell shell = HandlerUtil.getActiveShell(event);
 
-        final AtomicBoolean result = new AtomicBoolean(false);
+        // Find a good value to use for START_TIME based on the current horizontal ruler
+        // time range and the data start time.
+        IPreferenceStore csvnode = new ScopedPreferenceStore( InstanceScope.INSTANCE, CSVPreferences.P_NODE );
+        double oldStartTime = csvnode.getDouble(CSVPreferences.P_CSV_START_TIME);
+        double timeStep = csvnode.getDouble(CSVPreferences.P_CSV_TIME_STEP);
+        double visibleChartMinTime = trendNode.horizRuler.from;
+        double dataStartTime = trendNode.horizRuler.getItemFromTime();
+        // Find the first sample time that contains data if startTime < _from 
+        double n = Math.max(0, Math.ceil((visibleChartMinTime-dataStartTime) / timeStep));
+        double temporaryStartTime = dataStartTime + n*timeStep;
+        csvnode.setValue(CSVPreferences.P_CSV_START_TIME, temporaryStartTime);
+
         try {
+            PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
+                    shell, "org.simantics.modeling.csv.preferences",
+                    new String[] { "org.simantics.modeling.csv.preferences" },
+                    null);
+            dialog.setMessage("Select Used CSV Export Settings");
+            if (dialog.open() != Window.OK)
+                return null;
+
+            AtomicBoolean result = new AtomicBoolean(false);
             PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
                 @Override
                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
@@ -92,6 +116,8 @@ public class ChartCopyHandler extends AbstractHandler {
             ErrorLogger.defaultLogError(e.getCause());
         } catch (InterruptedException e) {
             ErrorLogger.defaultLogError(e);
+        } finally {
+            csvnode.setValue(CSVPreferences.P_CSV_START_TIME, oldStartTime);
         }
 
         return null;
diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartPreferencesAction.java b/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartPreferencesAction.java
new file mode 100644 (file)
index 0000000..0cc5820
--- /dev/null
@@ -0,0 +1,38 @@
+package org.simantics.charts.editor;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.preference.PreferenceDialog;
+import org.eclipse.jface.window.IShellProvider;
+import org.eclipse.ui.dialogs.PreferencesUtil;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class ChartPreferencesAction extends Action {
+
+       private static final String CHART_DEFAULTS_PREF_PAGE_ID = "org.simantics.charts.defaults"; //$NON-NLS-1$
+       private static final String CHART_PREF_PAGE_ID = "org.simantics.charts.pref"; //$NON-NLS-1$
+       private static final String CSV_PREF_PAGE_ID = "org.simantics.modeling.csv.preferences"; //$NON-NLS-1$ 
+
+       private IShellProvider shell;
+
+       public ChartPreferencesAction(IShellProvider shell) {
+               super(Messages.ChartPreferencesAction_ChartPreferences);
+               this.shell = shell;
+       }
+
+       @Override
+       public void run() {
+               PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(
+                               shell.getShell(),
+                               CHART_PREF_PAGE_ID,
+                               new String[] {
+                                               CHART_PREF_PAGE_ID,
+                                               CHART_DEFAULTS_PREF_PAGE_ID,
+                                               CSV_PREF_PAGE_ID
+                               },
+                               null);
+               dialog.open();
+       }
+
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/Messages.java b/bundles/org.simantics.charts/src/org/simantics/charts/editor/Messages.java
new file mode 100644 (file)
index 0000000..5771b14
--- /dev/null
@@ -0,0 +1,15 @@
+package org.simantics.charts.editor;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+       private static final String BUNDLE_NAME = "org.simantics.charts.editor.messages"; //$NON-NLS-1$
+       public static String ChartPreferencesAction_ChartPreferences;
+       static {
+               // initialize resource bundle
+               NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+       }
+
+       private Messages() {
+       }
+}
index bffd4c8a24952fb60bfae8cd517be91a9d24e36d..ad718e49ec353c11c5de660ea77fd767af3bc23b 100644 (file)
@@ -635,6 +635,8 @@ public class TimeSeriesEditor extends ResourceEditorPart {
                             if (chartItem != null) {
                                 manager.add(new HideItemsAction("Hide Item", true, Collections.singletonList(chartItem)));
                                 manager.add(new Separator());
+                                manager.add(new ChartPreferencesAction(getSite()));
+                                manager.add(new Separator());
                                 manager.add(new PropertiesAction("Item Properties", canvas, chartItem));
                                 manager.add(new PropertiesAction("Chart Properties", canvas, chart));
                             }
@@ -674,6 +676,8 @@ public class TimeSeriesEditor extends ResourceEditorPart {
                     manager.add(new SendCommandAction("Zoom to Fit Vertically", IMG_ZOOM_TO_FIT_VERT, cvsCtx, Commands.ZOOM_TO_FIT_VERT));
                     manager.add(new SendCommandAction("Autoscale Chart", IMG_AUTOSCALE, cvsCtx, Commands.AUTOSCALE));
                     manager.add(new Separator());
+                    manager.add(new ChartPreferencesAction(getSite()));
+                    manager.add(new Separator());
                     manager.add(new PropertiesAction("Chart Properties", canvas, chart));
                 }
             }
diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/messages.properties b/bundles/org.simantics.charts/src/org/simantics/charts/editor/messages.properties
new file mode 100644 (file)
index 0000000..37bbe90
--- /dev/null
@@ -0,0 +1 @@
+ChartPreferencesAction_ChartPreferences=Chart Preferences
index e9523c0c899628ee03fb29a4130067131044708a..dfb5780f96da2edfe4e8f7079c20812a8dfd051f 100644 (file)
@@ -33,7 +33,6 @@ import org.simantics.db.common.procedure.adapter.SyncMultiProcedureAdapter;
 import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.request.WriteRequest;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.CancelTransactionException;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.procedure.AsyncListener;
@@ -63,9 +62,13 @@ import org.simantics.db.request.WriteOnlyResult;
 import org.simantics.db.request.WriteResult;
 import org.simantics.utils.DataContainer;
 import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(MergingGraphRequestProcessor.class);
+
     private static class SyncWriteRequestAdapter implements Write {
 
         private Semaphore semaphore = new Semaphore(0);
@@ -128,7 +131,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
             try {
                 semaphore.acquire();
             } catch (InterruptedException e) {
-                       Logger.defaultLogError(e);
+                LOGGER.error("SyncWriteRequestAdapter interrupted", e);
             }
         }
 
@@ -223,7 +226,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
                             try {
                                 MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod);
                             } catch (InterruptedException e) {
-                                       Logger.defaultLogError(e);
+                                LOGGER.error("MergedRead interrupted", e);
                             }
                             if (requestQueue.isEmpty())
                                 break;
@@ -262,7 +265,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
                     } catch(Throwable t) {
 
-                               Logger.defaultLogError(t);
+                        LOGGER.error("MergedRead failed", t);
 
 //                        if(currentRequest.second instanceof AsyncProcedure<?>) {
 //                            ((AsyncProcedure<?>)currentRequest.second).exception(graph, t);
@@ -281,7 +284,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
                 } else {
 
-                    try{
+                    try {
 
                         if(currentRequest.second instanceof AsyncProcedure<?>) {
                             if(currentRequest.first instanceof AsyncRead) {
@@ -298,7 +301,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
                     } catch(Throwable t) {
 
-                               Logger.defaultLogError(t);
+                        LOGGER.error("MergedRead failed", t);
 
 //                        if(currentRequest.second instanceof AsyncProcedure<?>) {
 //                            ((AsyncProcedure<?>)currentRequest.second).exception(graph, t);
@@ -355,7 +358,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
                             try {
                                 MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod);
                             } catch (InterruptedException e) {
-                                       Logger.defaultLogError(e);
+                                LOGGER.error("RunnerWriteGraphRequest interrupted", e);
                             }
                             if (requestQueue.isEmpty())
                                 break;
@@ -385,7 +388,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
                         graph.syncRequest(adapter);
                         if(callback != null) callback.accept(null);
                     } catch(Throwable t) {
-                               Logger.defaultLogError(t);
+                        LOGGER.error("RunnerWriteGraphRequest failed", t);
                         if(callback != null) callback.accept(t);
                     }
 
@@ -399,7 +402,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
                         else if(currentRequest.first instanceof DelayedWrite) graph.syncRequest((DelayedWrite)currentRequest.first); 
                         if(callback != null) callback.accept(null);
                     } catch(Throwable t) {
-                               Logger.defaultLogError(t);
+                        LOGGER.error("RunnerWriteGraphRequest failed", t);
                         if(callback != null) callback.accept(t);
                     }
 
@@ -572,7 +575,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
         Throwable t = throwable.get();
 
         if(t != null) {
-               Logger.defaultLogError(t);
+            LOGGER.error("syncRequest(AsyncMultiRead, AsyncMultiProcedure) failed", t);
             throw new RuntimeException(t.getMessage());
         }
         
@@ -625,7 +628,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
         Throwable t = throwable.get();
 
         if(t != null) {
-               Logger.defaultLogError(t);
+            LOGGER.error("syncRequest(AsyncRead, AsyncProcedure) failed", t);
             throw new RuntimeException(t.getMessage());
         }
         
@@ -691,7 +694,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
             @Override
             public void exception(Throwable t) {
-                       Logger.defaultLogError(t);
+                LOGGER.error("asyncRequest(AsyncRead) failed", t);
             }
 
         });
@@ -736,7 +739,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
         Throwable t = throwable.get();
 
         if(t != null) {
-               Logger.defaultLogError(t);
+            LOGGER.error("syncRequest(AsyncRead) failed", t);
             throw new RuntimeException(t.getMessage());
         }
 
@@ -775,7 +778,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
         Throwable t = throwable.get();
 
         if(t != null) {
-               Logger.defaultLogError(t);
+            LOGGER.error("syncRequest(AsyncMultiRead) failed", t);
             throw new RuntimeException(t.getMessage());
         }
 
@@ -878,7 +881,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
 
             @Override
             public void exception(Throwable t) {
-                Logger.defaultLogError(t);
+                LOGGER.error("asyncRequest(Read) failed", t);
             }
 
         });
@@ -1305,4 +1308,9 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor {
                throw new UnsupportedOperationException();
        }
        
+       @Override
+       public <T> T l0() {
+               return processor.l0();
+       }
+       
 }
index 1f00ff008674e73ada990c71e297e9f01afe2f19..f47ebb3f342ac302cb2dd43bf6bfaaf56d251d28 100644 (file)
@@ -46,6 +46,11 @@ import org.simantics.db.request.WriteResult;
 
 public class ProcessorBase implements AsyncRequestProcessor {
 
+    @Override
+    public <T> T l0() {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public <T> void asyncRequest(AsyncMultiRead<T> request, AsyncMultiProcedure<T> procedure) {
         throw new UnsupportedOperationException();
index b3eba37fbdb4a0e395a90ea75c21a82abd1ad089..aeea33f0276c8a1de7dc0736bda0e86f03b0f72f 100644 (file)
@@ -14,7 +14,7 @@ import org.simantics.scl.runtime.function.FunctionImpl3;
  * @author Hannu Niemist&ouml;
  */
 public class AdaptValue extends ResourceRead<Object> {
-    
+
     public AdaptValue(Resource resource) {
         super(resource);
     }
@@ -31,14 +31,14 @@ public class AdaptValue extends ResourceRead<Object> {
                }
 
        };
-    
+
     @Override
     public Object perform(ReadGraph graph) throws DatabaseException {
-        String uri = graph.getURI(resource);        
-        if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication;
+        Layer0 L0 = graph.l0();
+        if (L0.Functions_functionApplication.equalsResource(resource))
+            return functionApplication;
         ComputationalValue ev = graph.adapt(resource, ComputationalValue.class);
         return ev.getValue(graph, resource);
-
     }
 
 }
index 117a1a27fb3d0e2fba3acab9ef9a57f7280858c2..73e612a9f4004b154478ad3893213e6960d5d8d3 100644 (file)
@@ -19,37 +19,41 @@ import org.simantics.db.service.QueryControl;
 
 abstract public class TransientResourceRead<R> extends BinaryRead<Object,Resource,R> implements ReadExt {
 
-       protected static final Object WITH_PARENT = new Object();
-       
-       public TransientResourceRead(ReadGraph graph, Resource parameter) throws DatabaseException {
-               this(graph, graph.getService(QueryControl.class), parameter);
-       }
-       
-       public TransientResourceRead(ReadGraph graph, QueryControl qc, Resource parameter) throws DatabaseException {
-               super(resolveFirstParameter(graph, qc), parameter);
-       }
-
-       final private static Object resolveFirstParameter(ReadGraph graph, QueryControl qc) throws DatabaseException {
-               if(qc.hasParentRequest(graph)) return WITH_PARENT;
-               else return graph.getModificationCounter();
-       }
-
-       @Override
-       final public R perform(ReadGraph _graph) throws DatabaseException {
-               if(parameter == WITH_PARENT) {
-                       return perform(_graph, parameter2);
-               } else {
-                       QueryControl qc = _graph.getService(QueryControl.class);
-                       ReadGraph graph = qc.getIndependentGraph(_graph);
-                       return perform(graph, parameter2);
-               }
-       }
-
-       abstract public R perform(ReadGraph graph, Resource parameter) throws DatabaseException;
-    
-       @Override
-       public boolean isImmutable(ReadGraph graph) throws DatabaseException {
-               return graph.isImmutable(parameter2);
-       }
-       
+    protected static final Object WITH_PARENT = new Object();
+
+    public TransientResourceRead(ReadGraph graph, Resource parameter) throws DatabaseException {
+        this(graph, graph.getService(QueryControl.class), parameter);
+    }
+
+    public TransientResourceRead(ReadGraph graph, QueryControl qc, Resource parameter) throws DatabaseException {
+        super(resolveFirstParameter(graph, qc), parameter);
+    }
+
+    final private static Object resolveFirstParameter(ReadGraph graph, QueryControl qc) throws DatabaseException {
+        if(qc.hasParentRequest(graph)) return WITH_PARENT;
+        else return graph.getModificationCounter();
+    }
+
+    @Override
+    final public R perform(ReadGraph _graph) throws DatabaseException {
+        if(parameter == WITH_PARENT) {
+            return perform(_graph, parameter2);
+        } else {
+            QueryControl qc = _graph.getService(QueryControl.class);
+            return qc.syncRequestIndependent(_graph, new UniqueRead<R>() {
+                @Override
+                public R perform(ReadGraph graph) throws DatabaseException {
+                    return TransientResourceRead.this.perform(graph, parameter2);
+                }
+            });
+        }
+    }
+
+    abstract public R perform(ReadGraph graph, Resource parameter) throws DatabaseException;
+
+    @Override
+    public boolean isImmutable(ReadGraph graph) throws DatabaseException {
+        return graph.isImmutable(parameter2);
+    }
+
 }
index 143d3e443099f31c703503dfea77b1da7ea115f1..8e8171f85273e460bdf519df9eab706ba395b539 100644 (file)
@@ -220,6 +220,27 @@ public class OrderedSetUtils {
             }
     }
 
+    /**
+     * Reorders elements with a minimum number of writes. The set of elements must remain the same. 
+     */
+    public static void reorder(WriteGraph g, Resource l, Iterable<Resource> order) throws DatabaseException {
+        Resource newPrev = l;
+        for (Resource r : order) {
+            Resource prev = OrderedSetUtils.prev(g, l, r);
+            if (!prev.equals(newPrev)) {
+                g.deny(prev, l, r);
+                g.claim(newPrev, l, r);
+            }
+            newPrev = r;
+        }
+        Resource newLast = newPrev;
+        Resource last = OrderedSetUtils.prev(g, l, l);
+        if (!last.equals(newLast)) {
+            g.deny(last, l, l);
+            g.claim(newLast, l, l);
+        }
+    }
+
     /**
      * Converts ordered set into a list.
      */
index 8f96bb9e6d3a51a48c7b98baa40f962fc83f5617..9f89a0d8fa2a4f2ede8474513ac9f8ae5ce33de1 100644 (file)
@@ -19,34 +19,31 @@ import org.simantics.db.impl.query.AsyncReadEntry;
 import org.simantics.db.impl.query.PendingTaskSupport;
 import org.simantics.db.procedure.AsyncProcedure;
 import org.simantics.db.request.AsyncRead;
-public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
+
+public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result>, Runnable {
 
     private static final Object NO_RESULT = new Object();
 
     private final Object key;
     private final ReadGraphImpl queryGraph;
     private final ReadGraphImpl callerGraph;
+    private final AsyncReadEntry<Result> entry;
     private final AsyncProcedure<Result> procedure;
     private PendingTaskSupport pendingTaskSupport;
     private final boolean needsToBlock;
     private Object result = NO_RESULT;
     private Throwable exception = null;
-
-    private ReadGraphImpl queryGraph() {
-        return queryGraph;
-    }
     
     public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure, Object key, boolean needsToBlock) {
         
         // A new graph for evaluating the query with correct parent and asyncBarrier
-        queryGraph = callerGraph.withParent(entry, () -> {
-
-            dispatchProcedure(queryGraph(), callerGraph, entry, procedure, needsToBlock);
-            
-        }, needsToBlock);
-        
+        queryGraph = callerGraph.withParent(entry, this, needsToBlock);
         queryGraph.asyncBarrier.inc();
+        
+        // This makes sure that caller does not quit before dispatch
+        callerGraph.asyncBarrier.inc();
 
+        this.entry = entry;
         this.procedure = procedure;
         this.key = key;
         this.queryGraph.asyncBarrier.inc();
@@ -112,34 +109,39 @@ public class BlockingAsyncProcedure<Result> implements AsyncProcedure<Result> {
         return "." + procedure; 
     }
     
-    private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry<Result> entry, AsyncProcedure<Result> procedure_, boolean needsToBlock) {
+    @Override
+    public void run() {
         
-        AsyncProcedure<Result> procedure = entry != null ? entry : procedure_;
+        AsyncProcedure<Result> procedure__ = entry != null ? entry : procedure;
 
-        ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent, null, needsToBlock);
+        ReadGraphImpl executeGraph = callerGraph.withParent(callerGraph.parent, null, needsToBlock);
         executeGraph.asyncBarrier.inc();
+        
+        // This counters the inc in the constructor 
+        callerGraph.asyncBarrier.dec();
+        
         try {
-            if(procedure != null) {
-                procedure.execute(executeGraph, get());
+            if(procedure__ != null) {
+                procedure__.execute(executeGraph, get());
             }
         } catch (DatabaseException e) {
-            if(procedure != null) procedure.exception(executeGraph, e);
+            if(procedure__ != null) procedure__.exception(executeGraph, e);
             exception = e;
         } catch (Throwable t) {
             DatabaseException dbe = new DatabaseException(t);
-            if(procedure != null) procedure.exception(executeGraph, dbe);
+            if(procedure__ != null) procedure__.exception(executeGraph, dbe);
             exception = dbe;
         } finally {
 
             if (entry != null) {
                 assert(entry.isReady());
                 // This does not throw
-                entry.performFromCache(executeGraph, procedure_);
+                entry.performFromCache(executeGraph, procedure);
             }
 
             executeGraph.asyncBarrier.dec();
             if(needsToBlock)
-                executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph);
+                executeGraph.asyncBarrier.waitBarrier(procedure__, executeGraph);
         }
 
         if (BarrierTracing.BOOKKEEPING) {
index 637db3f26f8e119173fbf29cbe54b46ed9b17002..f1e5b5cce10cc4758207a257c2f6cfeb4f0a3372 100644 (file)
@@ -14,13 +14,15 @@ package org.simantics.db.impl.graph;
 import java.util.Collection;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.RuntimeDatabaseException;
 import org.simantics.db.impl.query.CacheEntry;
 import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier;
+import org.slf4j.LoggerFactory;
 
 public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier {
 
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AsyncBarrierImpl.class);
+
     private static final long serialVersionUID = 4724463372850048672L;
 
     static final int WAIT_TIME = 60000;
@@ -107,7 +109,7 @@ public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier {
                 }
             }
             if (count < 0) {
-                Logger.defaultLogError(
+                LOGGER.error(
                         "Database request processing error. The application code has performed illegal actions (probably called multiple times the execute or exception method of a single result request.",
                         new Exception());
             }
index 48662d1903a08267a13dded57e04e04f8b85db6d..27336b23d32474eda7bf7b00ab368a9cb5b56e02 100644 (file)
@@ -188,8 +188,6 @@ import org.simantics.utils.DataContainer;
 import org.simantics.utils.Development;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.collections.CollectionUtils;
-import org.simantics.utils.threads.logger.ITask;
-import org.simantics.utils.threads.logger.ThreadLogger;
 import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.TObjectIntHashMap;
@@ -1513,15 +1511,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);
@@ -1922,14 +1920,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);
-
-               T result = (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true);
-               return result;
-               
-       }
+    @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)
@@ -1943,16 +1938,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;
-               T result = (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true);
-               return result;
-
-       }
+    @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,
@@ -2028,17 +2019,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);
-               T result = (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); 
-               return result;
-
-       }
+    @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,
@@ -5235,54 +5222,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);
 
         AsyncBarrierImpl barrier = asyncBarrier;
         if(barrier != null)
             barrier.inc();
 
-               processor.scheduleNow(new SessionTask(this) {
+        processor.scheduleNow(new SessionTask(this) {
 
-                       @Override
-                       public void run0(int thread) {
+            @Override
+            public void run0(int thread) {
 
-                           if(barrier != null)
-                           barrier.inc();
+                if(barrier != null)
+                    barrier.inc();
 
-                           try {
-                                       final ListenerBase listener = getListenerBase(procedure);
-                                       QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure<T>() {
+                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 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);
+                        @Override
+                        public void exception(AsyncReadGraph graph, Throwable throwable) {
+                            procedure.exception(graph, throwable);
                             if(barrier != null)
                                 barrier.dec();
-                                               }
-                                               
-                                       }, false);
-                               if(barrier != null)
-                                   barrier.dec();
-                               } catch (DatabaseException e) {
-                                       Logger.defaultLogError(e);
-                               }
-                       }
-                       
-               });
+                        }
+
+                    }, 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,
@@ -6399,4 +6387,10 @@ public class ReadGraphImpl implements AsyncReadGraph {
         else return getTopLevelGraphStatic(impl.parentGraph);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T l0() {
+        return (T) processor.getL0();
+    }
+
 }
index 0c4e681385da7ab25a4c5afae9217a649c1a7966..8cb1688fb73f584f1900f6589fd0a45c448c96c6 100644 (file)
@@ -14,10 +14,13 @@ package org.simantics.db.impl.graph;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.StringWriter;
+import java.util.IdentityHashMap;
+import java.util.Map;
 import java.util.TreeMap;
 import java.util.function.Consumer;
 
 import org.simantics.databoard.Bindings;
+import org.simantics.databoard.Datatypes;
 import org.simantics.databoard.accessor.Accessor;
 import org.simantics.databoard.binding.Binding;
 import org.simantics.databoard.binding.error.BindingConstructionException;
@@ -31,7 +34,16 @@ import org.simantics.databoard.primitives.MutableLong;
 import org.simantics.databoard.primitives.MutableString;
 import org.simantics.databoard.serialization.SerializationException;
 import org.simantics.databoard.serialization.Serializer;
+import org.simantics.databoard.type.ArrayType;
+import org.simantics.databoard.type.BooleanType;
+import org.simantics.databoard.type.ByteType;
 import org.simantics.databoard.type.Datatype;
+import org.simantics.databoard.type.DoubleType;
+import org.simantics.databoard.type.FloatType;
+import org.simantics.databoard.type.IntegerType;
+import org.simantics.databoard.type.LongType;
+import org.simantics.databoard.type.StringType;
+import org.simantics.databoard.type.VariantType;
 import org.simantics.databoard.util.binary.RandomAccessBinary;
 import org.simantics.db.DevelopmentKeys;
 import org.simantics.db.ExternalValueSupport;
@@ -69,8 +81,6 @@ import org.simantics.layer0.Layer0;
 import org.simantics.utils.Development;
 import org.simantics.utils.datastructures.Pair;
 
-import gnu.trove.map.hash.THashMap;
-
 
 final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph {
 
@@ -683,7 +693,7 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph {
         
     }
 
-    THashMap<Class<?>, Resource> builtinValues = new THashMap<Class<?>, Resource>(32);
+    Map<Object, Resource> builtinValues = new IdentityHashMap<>(40);
 
     private void initBuiltinValues(Layer0 b) {
 
@@ -714,6 +724,76 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph {
         builtinValues.put(MutableByte.class, b.Byte);
         builtinValues.put(MutableBoolean.class, b.Boolean);
 
+        builtinValues.put(Datatypes.DOUBLE, b.Double);
+        builtinValues.put(Datatypes.STRING, b.String);
+        builtinValues.put(Datatypes.INTEGER, b.Integer);
+        builtinValues.put(Datatypes.LONG, b.Long);
+        builtinValues.put(Datatypes.FLOAT, b.Float);
+        builtinValues.put(Datatypes.BYTE, b.Byte);
+        builtinValues.put(Datatypes.BOOLEAN, b.Boolean);
+        builtinValues.put(Datatypes.VARIANT, b.Variant);
+
+        builtinValues.put(Datatypes.DOUBLE_ARRAY, b.DoubleArray);
+        builtinValues.put(Datatypes.STRING_ARRAY, b.StringArray);
+        builtinValues.put(Datatypes.INTEGER_ARRAY, b.IntegerArray);
+        builtinValues.put(Datatypes.LONG_ARRAY, b.LongArray);
+        builtinValues.put(Datatypes.FLOAT_ARRAY, b.FloatArray);
+        builtinValues.put(Datatypes.BYTE_ARRAY, b.ByteArray);
+        builtinValues.put(Datatypes.BOOLEAN_ARRAY, b.BooleanArray);
+        builtinValues.put(Datatypes.VARIANT_ARRAY, b.VariantArray);
+    }
+
+    private static Datatype canonicalizeToBuiltinDatatype(Datatype datatype) {
+        if (datatype instanceof ArrayType) {
+            ArrayType at = (ArrayType) datatype;
+            datatype = at.componentType();
+            if (datatype instanceof ByteType) {
+                return Datatypes.BYTE_ARRAY;
+            } else if (datatype instanceof DoubleType) {
+                return Datatypes.DOUBLE_ARRAY;
+            } else if (datatype instanceof FloatType) {
+                return Datatypes.FLOAT_ARRAY;
+            } else if (datatype instanceof IntegerType) {
+                return Datatypes.INTEGER_ARRAY;
+            } else if (datatype instanceof LongType) {
+                return Datatypes.LONG_ARRAY;
+            } else if (datatype instanceof BooleanType) {
+                return Datatypes.BOOLEAN_ARRAY;
+            } else if (datatype instanceof StringType) {
+                return Datatypes.STRING_ARRAY;
+            } else if (datatype instanceof VariantType) {
+                return Datatypes.VARIANT_ARRAY;
+            }
+            return null;
+        }
+        if (datatype instanceof ByteType) {
+            return Datatypes.BYTE;
+        } else if (datatype instanceof DoubleType) {
+            return Datatypes.DOUBLE;
+        } else if (datatype instanceof FloatType) {
+            return Datatypes.FLOAT;
+        } else if (datatype instanceof IntegerType) {
+            return Datatypes.INTEGER;
+        } else if (datatype instanceof LongType) {
+            return Datatypes.LONG;
+        } else if (datatype instanceof BooleanType) {
+            return Datatypes.BOOLEAN;
+        } else if (datatype instanceof StringType) {
+            return Datatypes.STRING;
+        } else if (datatype instanceof VariantType) {
+            return Datatypes.VARIANT;
+        }
+        return null;
+    }
+
+    private Resource resolveBuiltinResourceType(Class<?> valueClass, Datatype datatype) {
+        Resource type = builtinValues.get(valueClass);
+        return type != null ? type : builtinValues.get(datatype);
+    }
+
+    private Resource resolveBuiltinResourceTypeByCanonicalizedDatatype(Datatype datatype, Resource defaultResult) {
+        Datatype cdt = canonicalizeToBuiltinDatatype(datatype);
+        return cdt != null ? builtinValues.get(cdt) : defaultResult;
     }
 
     @Override
@@ -734,13 +814,13 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph {
         initBuiltinValues(b);
         Resource literal = newResource();
         
-        Class<?> clazz = value.getClass();
-        Resource type = builtinValues.get(clazz);
+        Datatype dt = binding.type();
+        Resource type = resolveBuiltinResourceType(value.getClass(), dt);
         if (type == null) {
-            type = b.Literal;
+            type = resolveBuiltinResourceTypeByCanonicalizedDatatype(dt, b.Literal);
             Resource dataType = newResource();
             claim(dataType, b.InstanceOf, null, b.DataType);
-            claimValue(dataType, binding.type(), DATA_TYPE_BINDING);
+            claimValue(dataType, dt, DATA_TYPE_BINDING);
             claim(literal, b.HasDataType, b.HasDataType_Inverse, dataType);
         }
         
@@ -805,14 +885,14 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph {
 
         } else {
 
-            Class<?> clazz = value.getClass();
-            Resource type = builtinValues.get(clazz);
             Resource literal = newResource();
+            Datatype dt = binding.type();
+            Resource type = resolveBuiltinResourceType(value.getClass(), dt);
             if (type == null) {
-                type = b.Literal;
+                type = resolveBuiltinResourceTypeByCanonicalizedDatatype(dt, b.Literal);
                 Resource dataType = newResource();
                 claim(dataType, b.InstanceOf, null, b.DataType);
-                claimValue(dataType, binding.type(), DATA_TYPE_BINDING);
+                claimValue(dataType, dt, DATA_TYPE_BINDING);
                 claim(literal, b.HasDataType, null, dataType);
             }
             claim(literal, b.InstanceOf, null, type);
index f74344b2fdb807dad60e1b746580f81cb106ad80..8bac422636ff9a13d8064f5ab0ef64cee6a4d476 100644 (file)
@@ -37,569 +37,566 @@ import org.simantics.db.request.RequestFlags;
 
 public final class Objects extends CollectionBinaryQuery<IntProcedure> implements IntProcedure {
 
-       public Objects(final int r1, final int r2) {
-               super(r1, r2);
-       }
-
-       @Override
-       final public void removeEntry(QueryProcessor provider) {
-               provider.cache.remove(this);
-       }
-
-       final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Objects entry) throws DatabaseException {
-
-               class AssertionMapProc implements IntProcedure {
-
-                       boolean first = true;
-
-                       private IntArray result;
-
-                       public void addStatement(int s, int p, int o) {
-
-                               if(result.size() == 0) {
-                                       result.add(s);
-                                       result.add(p);
-                                       result.add(o);
-                               } else {
-                                       for(int i = 0;i < result.sizeOrData ; i+=3) {
-                                               int existingP = result.data[i+1];
-                                               if(p == existingP) {
-                                                       int existingO = result.data[i+2];
-                                                       if(existingO == o) return;
-                                               }
-                                       }
-                                       result.add(s);
-                                       result.add(p);
-                                       result.add(o);
-                               }
-
-                       }
-
-                       @Override
-                       public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
-                               if(result == null) {
-                                       result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
-                               } else {
-                                       if (first) {
-                                               IntArray ia = result;
-                                               result = new IntArray();
-                                               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]);
-                                               }
-                                               first = false;
-                                       }
-                                       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]);
-                                       }
-                               }
-                       }
+    public Objects(final int r1, final int r2) {
+        super(r1, r2);
+    }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                       }
+    @Override
+    final public void removeEntry(QueryProcessor provider) {
+        provider.cache.remove(this);
+    }
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable throwable) {
-                       }
+    final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Objects entry) throws DatabaseException {
+
+        class AssertionMapProc implements IntProcedure {
+
+            boolean first = true;
+
+            private IntArray result;
+
+            public void addStatement(int s, int p, int o) {
+
+                if(result.size() == 0) {
+                    result.add(s);
+                    result.add(p);
+                    result.add(o);
+                } else {
+                    for(int i = 0;i < result.sizeOrData ; i+=3) {
+                        int existingP = result.data[i+1];
+                        if(p == existingP) {
+                            int existingO = result.data[i+2];
+                            if(existingO == o) return;
+                        }
+                    }
+                    result.add(s);
+                    result.add(p);
+                    result.add(o);
+                }
+
+            }
+
+            @Override
+            public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
+                if(result == null) {
+                    result = QueryCacheBase.resultAssertedStatements(graph, type, r2, entry, null);
+                } else {
+                    if (first) {
+                        IntArray ia = result;
+                        result = new IntArray();
+                        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]);
+                        }
+                        first = false;
+                    }
+                    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]);
+                    }
+                }
+            }
+
+            @Override
+            public void finished(ReadGraphImpl graph) {
+            }
+
+            @Override
+            public void exception(ReadGraphImpl graph, Throwable throwable) {
+            }
 
-               }
+        }
 
-               AssertionMapProc amp = new AssertionMapProc();
+        AssertionMapProc amp = new AssertionMapProc();
 
-               // This dependency could be cut
-               QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
+        // This dependency could be cut
+        QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
 
-               return amp.result;
+        return amp.result;
 
-       }
+    }
 
-       final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
+    final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
 
-               IntArray map = getAssertionMap(graph, r1, r2, parent);
-               if(map == null) {
-                       procedure.finished(graph);
-                       return;
-               }
+        IntArray map = getAssertionMap(graph, r1, r2, parent);
+        if(map == null) {
+            procedure.finished(graph);
+            return;
+        }
 
-               int size = map.size();
-               if(size == 3) {
-                   int value = map.data[2];
-                   procedure.execute(graph, value);
-                   procedure.finished(graph);
-               } else if(size == 0) {
-                       procedure.finished(graph);
-               } else {
+        int size = map.size();
+        if(size == 3) {
+            int value = map.data[2];
+            procedure.execute(graph, value);
+            procedure.finished(graph);
+        } else if(size == 0) {
+            procedure.finished(graph);
+        } else {
 
-                       int candidateS = map.data[0];
-                       int candidateO = map.data[2];
+            int candidateS = map.data[0];
+            int candidateO = map.data[2];
 
-                       IntSet candidateIs = null;
-                       try {
-                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
-                       } catch (DatabaseException e) {
-                               procedure.exception(graph, e);
-                               return;
-                       }
+            IntSet candidateIs = null;
+            try {
+                candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
+            } catch (DatabaseException e) {
+                procedure.exception(graph, e);
+                return;
+            }
 
-                       for(int i=3;i<map.size();i+=3) {
+            for(int i=3;i<map.size();i+=3) {
 
-                               int nextS = map.data[i];
-                               int nextO = map.data[i+2];
+                int nextS = map.data[i];
+                int nextO = map.data[i+2];
 
-                               if(nextS != candidateS) {
+                if(nextS != candidateS) {
 
-                                       if(candidateIs.contains(nextS)) {
+                    if(candidateIs.contains(nextS)) {
 
-                                               // Next is a super type of candidate => ignore next
+                        // Next is a super type of candidate => ignore next
 
-                                       } else {
+                    } else {
 
-                                               IntSet nextIs = null;
-                                               try {
-                                                       nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
-                                               } catch (DatabaseException e) {
-                                                       procedure.exception(graph, e);
-                                                       return;
-                                               }
+                        IntSet nextIs = null;
+                        try {
+                            nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
+                        } catch (DatabaseException e) {
+                            procedure.exception(graph, e);
+                            return;
+                        }
 
-                                               if(nextIs.contains(candidateS)) {
+                        if(nextIs.contains(candidateS)) {
 
-                                                       // Candidate is a super type of next => next is the new candidate
+                            // Candidate is a super type of next => next is the new candidate
 
-                                                       candidateS = nextS;
-                                                       candidateO = nextO;
-                                                       candidateIs = nextIs;
+                            candidateS = nextS;
+                            candidateO = nextO;
+                            candidateIs = nextIs;
 
-                                               } else {
+                        } else {
 
-                                                       // candidate and next are unrelated => error
-                                                       ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
-                                                       procedure.exception(graph, exception);
-                                                       return;                                         
+                            // candidate and next are unrelated => error
+                            ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions " + r1 + ", " + r2 + " " + map , r1);
+                            procedure.exception(graph, exception);
+                            return;
 
-                                               }
+                        }
 
-                                       }
+                    }
 
-                               }
+                }
 
-                       }
+            }
 
-                       procedure.execute(graph, candidateO);
-                       procedure.finished(graph);
+            procedure.execute(graph, candidateO);
+            procedure.finished(graph);
 
-               }
+        }
 
-       }
+    }
 
-       final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
+    final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
 
-               @Override
-               public void execute(ReadGraphImpl graph, IntSet result) {
-               }
+        @Override
+        public void execute(ReadGraphImpl graph, IntSet result) {
+        }
 
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
+        @Override
+        public void exception(ReadGraphImpl graph, Throwable throwable) {
+        }
 
-       };
+    };
 
-       final static TripleIntProcedure NOPT = new TripleIntProcedure() {
+    final static TripleIntProcedure NOPT = new TripleIntProcedure() {
 
 
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
+        @Override
+        public void exception(ReadGraphImpl graph, Throwable throwable) {
+        }
 
-               @Override
-               public void execute(ReadGraphImpl graph, int s, int p, int o) {
-               }
+        @Override
+        public void execute(ReadGraphImpl graph, int s, int p, int o) {
+        }
 
-               @Override
-               public void finished(ReadGraphImpl graph) {
-               }
+        @Override
+        public void finished(ReadGraphImpl graph) {
+        }
 
-       };
+    };
 
-       // Search for one statement
-       final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
-               computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
-       }
+    // Search for one statement
+    final public void computeFunctionalIndex(ReadGraphImpl graph, final QueryProcessor provider, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
+        computeFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
+    }
 
-       // Search for one statement
-       final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
+    // Search for one statement
+    final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
 
-               if(ri.isFinal) {
+        if(ri.isFinal) {
 
-                       int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
+            int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
 
-                       if(result == 0) {
+            if(result == 0) {
 
-                               // Check for assertions
-                               forSingleAssertion(graph, r1, r2, parent, procedure);
+                // Check for assertions
+                forSingleAssertion(graph, r1, r2, parent, procedure);
 
-                       } else if (result == -1) {
+            } else if (result == -1) {
 
-                               graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
+                graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
 
-                                       @Override
-                                       public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                           procedure.execute(graph, i);
-                                       }
+                    @Override
+                    public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                        procedure.execute(graph, i);
+                    }
 
-                                       @Override
-                                       public void exception(ReadGraphImpl graph, Throwable t) {
-                                               if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                                       }
+                    @Override
+                    public void exception(ReadGraphImpl graph, Throwable t) {
+                        if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                    }
 
-                                       @Override
-                                       public void finished(ReadGraphImpl graph) {
-                                       }
+                    @Override
+                    public void finished(ReadGraphImpl graph) {
+                    }
 
-                               });
+                });
 
-                               // Check for assertions
-                               forSingleAssertion(graph, r1, r2, parent, procedure);
+                // Check for assertions
+                forSingleAssertion(graph, r1, r2, parent, procedure);
 
-                       } else {
+            } else {
 
-                               // If functional relation was found there is no need to check assertions
+                // If functional relation was found there is no need to check assertions
                 procedure.execute(graph, result);
                 procedure.finished(graph);
 
-                               
-                       }
+            }
 
-               } else {
+        } else {
 
-                       // Note! The dependency is intentionally cut!
+            // Note! The dependency is intentionally cut!
             IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
 
-                               boolean found = false;
-
-                               @Override
-                               public void run(ReadGraphImpl graph) throws DatabaseException {
-
-                                       if(found) {
-                                               procedure.finished(graph);
-                                       } else {
+                /*
+                 * 0 = not found
+                 * 1 = found
+                 * 2 = exception
+                 */
+                int found = 0;
 
-                                               // Check for assertions
-                                               forSingleAssertion(graph, r1, r2, parent, procedure);
+                @Override
+                public void run(ReadGraphImpl graph) throws DatabaseException {
 
-                                       }
+                    if(found == 1) {
 
-                               }
+                        procedure.finished(graph);
 
-                               @Override
-                               public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
+                    } else if(found == 0) {
 
-                                       if(found) return;
+                        // Check for assertions
+                        forSingleAssertion(graph, r1, r2, parent, procedure);
 
-                                       if(pred == r2) {
+                    }
 
-                                               // Note! The dependency is intentionally cut!
-                                               QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
+                }
 
-                                                       @Override
-                                                       public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                @Override
+                public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
 
-                                                               if(!found) {
+                    if(found > 0)
+                        return;
 
-                                                                       procedure.execute(graph, i);
-                                                                       found = true;
+                    if(pred == r2) {
 
-                                                               } else {
+                        // Note! The dependency is intentionally cut!
+                        QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
 
-                                                                       ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
-                                                                       procedure.exception(graph, exception);
+                            @Override
+                            public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
 
-                                                               }
+                                if(found == 0) {
 
-                                                       }
+                                    procedure.execute(graph, i);
+                                    found = 1;
 
-                                                       @Override
-                                                       public void finished(ReadGraphImpl graph) {
-                                                       }
+                                } else {
 
-                                                       @Override
-                                                       public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                               procedure.exception(graph, t);
-                                                       }
+                                    ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
+                                    procedure.exception(graph, exception);
+                                    found = 2;
 
-                                               });
+                                }
 
-                                       } else {
+                            }
 
-                                               QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
+                            @Override
+                            public void finished(ReadGraphImpl graph) {
+                            }
 
-                                                       @Override
-                                                       public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
 
-                                                               if(found) return;
+                                procedure.exception(graph, t);
+                                found = 2;
 
-                                                               if(result.contains(r2)) {
+                            }
 
-                                                                       // Note! The dependency is intentionally cut!
-                                                                       QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
+                        });
 
-                                                                               @Override
-                                                                               public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                    } else {
 
-                                                                                       if(!found) {
+                        QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
 
-                                                                                               procedure.execute(graph, i);
-                                                                                               found = true;
+                            @Override
+                            public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
 
-                                                                                       } else {
+                                if(found > 0)
+                                    return;
 
-                                                                                               ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
-                                                                                               procedure.exception(graph, exception);
+                                if(result.contains(r2)) {
 
-                                                                                       }
+                                    // Note! The dependency is intentionally cut!
+                                    QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
 
-                                                                               }
+                                        @Override
+                                        public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
 
-                                                                               @Override
-                                                                               public void finished(ReadGraphImpl graph) {
-                                                                               }
+                                            if(found == 0) {
 
-                                                                               @Override
-                                                                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                                                       procedure.exception(graph, t);
-                                                                               }
+                                                procedure.execute(graph, i);
+                                                found = 1;
 
-                                                                       });
+                                            } else {
 
-                                                               }
+                                                ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
+                                                procedure.exception(graph, exception);
+                                                found = 2;
 
-                                                       }
+                                            }
 
-                                                       @Override
-                                                       public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                               procedure.exception(graph, t);
-                                                       }
+                                        }
 
-                                               });
+                                        @Override
+                                        public void finished(ReadGraphImpl graph) {
+                                        }
 
-                                       }
+                                        @Override
+                                        public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                            procedure.exception(graph, t);
+                                            found = 2;
+                                        }
 
-                               }
+                                    });
 
-                               @Override
-                               public void finished(ReadGraphImpl graph) throws DatabaseException {
+                                }
 
-                                       dec(graph);
+                            }
 
-                               }
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                procedure.exception(graph, t);
+                                found = 2;
+                            }
 
-                       });
+                        });
 
+                    }
 
-               }
+                }
 
-       }
+                @Override
+                public void finished(ReadGraphImpl graph) throws DatabaseException {
+                    dec(graph);
+                }
 
-       final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
+            });
 
-               // Note! The dependency is intentionally cut!
-               QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
 
-                       @Override
-                       public void run(ReadGraphImpl graph) throws DatabaseException {
-                               procedure.finished(graph);
-                       }
-
-                       TripleIntProcedure proc = new TripleIntProcedure() {
+        }
 
-                               @Override
-                               public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
-                                       procedure.execute(graph, o);
-                               }
+    }
 
-                               @Override
-                               public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                       dec(graph);
-                               }
+    final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, final IntProcedure procedure) throws DatabaseException {
 
-                               @Override
-                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                       if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                                       procedure.exception(graph, t);
-                                       dec(graph);
-                               }
+        // Note! The dependency is intentionally cut!
+        QueryCache.runnerPrincipalTypes(graph, r1, null, null, new SyncIntProcedure() {
 
-                       };
+            @Override
+            public void run(ReadGraphImpl graph) throws DatabaseException {
+                procedure.finished(graph);
+            }
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
+            TripleIntProcedure proc = new TripleIntProcedure() {
 
-                               inc();
-                               QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
+                @Override
+                public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
+                    procedure.execute(graph, o);
+                }
 
-                       }
+                @Override
+                public void finished(ReadGraphImpl graph) throws DatabaseException {
+                    dec(graph);
+                }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) throws DatabaseException {
-                               dec(graph);
-                       }
+                @Override
+                public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                    if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                    procedure.exception(graph, t);
+                    dec(graph);
+                }
 
-               });
+            };
 
+            @Override
+            public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
 
-       }
+                inc();
+                QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
 
-       final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
-               throw new Error();
-       }
+            }
 
-       final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
-               computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
-       }
+            @Override
+            public void finished(ReadGraphImpl graph) throws DatabaseException {
+                dec(graph);
+            }
 
-       final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
+        });
 
-               if(ri.isFinal) {
 
-                       graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
+    }
 
-                               @Override
-                               public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                       procedure.execute(graph, i);
-                               }
+    final public static void computeNotFunctionalFinalIndex(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, RelationInfo ri, AsyncMultiProcedure<Resource> procedure) {
+        throw new Error();
+    }
 
-                               @Override
-                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                       if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                                       procedure.exception(graph, t);
-                               }
+    final public void computeNotFunctionalIndex(ReadGraphImpl graph, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
+        computeNotFunctionalIndex(graph, r1(), r2(), this, ri, procedure);
+    }
 
-                               @Override
-                               public void finished(ReadGraphImpl graph) {
-                               }
+    final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Objects parent, RelationInfo ri, final IntProcedure procedure) throws DatabaseException {
 
-                       });
+        if(ri.isFinal) {
 
-                       if(ri.isAsserted) {
-                               forAssertions(graph, r1, r2, parent, procedure);
-                       } else {
-                               procedure.finished(graph);
-                       }
+            graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
 
-               } else {
+                @Override
+                public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                    procedure.execute(graph, i);
+                }
 
-                       // Note! The dependency is intentionally cut!
-                       IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
-                       direct.forEach(graph, new SyncIntProcedure() {
+                @Override
+                public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                    if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                    procedure.exception(graph, t);
+                }
 
-                               @Override
-                               public void run(ReadGraphImpl graph) throws DatabaseException {
-                                       forAssertions(graph, r1, r2, parent, procedure);
-                               }
+                @Override
+                public void finished(ReadGraphImpl graph) {
+                }
 
-                               @Override
-                               public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
+            });
 
-                                       if(pred == r2) {
+            if(ri.isAsserted) {
+                forAssertions(graph, r1, r2, parent, procedure);
+            } else {
+                procedure.finished(graph);
+            }
 
-                                               inc();
+        } else {
 
-                                               // Note! The dependency is intentionally cut!
-                                               QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
+            // Note! The dependency is intentionally cut!
+            IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
+            direct.forEach(graph, new SyncIntProcedure() {
 
-                                                       @Override
-                                                       public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                                               procedure.execute(graph, i);
-                                                       }
+                @Override
+                public void run(ReadGraphImpl graph) throws DatabaseException {
+                    forAssertions(graph, r1, r2, parent, procedure);
+                }
 
-                                                       @Override
-                                                       public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                                               dec(graph);
-                                                       }
+                @Override
+                public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
 
-                                                       @Override
-                                                       public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                               procedure.exception(graph, t);
-                                                               dec(graph);
-                                                       }
+                    if(pred == r2) {
 
-                                               });
+                        // Note! The dependency is intentionally cut!
+                        QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
 
-                                       } else {
+                            @Override
+                            public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                                procedure.execute(graph, i);
+                            }
 
-                                               inc();
+                            @Override
+                            public void finished(ReadGraphImpl graph) throws DatabaseException {
+                            }
 
-                                               QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                procedure.exception(graph, t);
+                            }
 
-                                                       @Override
-                                                       public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
+                        });
 
-                                                               if(result.contains(r2)) {
+                    } else {
 
-                                                                       inc();
+                        try {
 
-                                                                       // Note! The dependency is intentionally cut!
-                                                                       QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
+                            IntSet result = QueryCache.resultSuperRelations(graph, pred, parent, null);
+                            if(result.contains(r2)) {
 
-                                                                               @Override
-                                                                               public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                                                                       procedure.execute(graph, i);
-                                                                               }
+                                inc();
 
-                                                                               @Override
-                                                                               public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                                                                       dec(graph);
-                                                                               }
+                                // Note! The dependency is intentionally cut!
+                                QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
 
-                                                                               @Override
-                                                                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                                                       if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                                                                                       procedure.exception(graph, t);
-                                                                                       dec(graph);
-                                                                               }
+                                    @Override
+                                    public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                                        procedure.execute(graph, i);
+                                    }
 
-                                                                       });
+                                    @Override
+                                    public void finished(ReadGraphImpl graph) throws DatabaseException {
+                                        dec(graph);
+                                    }
 
-                                                               }
+                                    @Override
+                                    public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                        if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                                        procedure.exception(graph, t);
+                                        dec(graph);
+                                    }
 
-                                                               dec(graph);
+                                });
 
-                                                       }
+                            }
 
-                                                       @Override
-                                                       public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                               procedure.exception(graph, t);
-                                                               dec(graph);
-                                                       }
+                        } catch (Throwable e) {
+                            procedure.exception(graph, e);
+                        }
 
-                                               });
+                    }
 
-                                       }
+                }
 
-                               }
+                @Override
+                public void finished(ReadGraphImpl graph) throws DatabaseException {
+                    dec(graph);
+                }
 
-                               @Override
-                               public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                       dec(graph);
-                               }
+            });
 
-                       });
+        }
 
-               }
+    }
 
-       }
+    public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
+        computeForEach(graph, r1(), r2(), this, procedure);
+        return getResult();
+    }
 
-       public Object compute(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
-               computeForEach(graph, r1(), r2(), this, procedure);
-               return getResult();
-       }
+    public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
 
-       public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Objects entry, final IntProcedure procedure_) throws DatabaseException {
+        IntProcedure procedure = entry != null ? entry : procedure_;
 
-           IntProcedure procedure = entry != null ? entry : procedure_;
-           
         RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
         graph.ensureLoaded(r1, r2);
         if(ri.isFunctional) {
@@ -607,63 +604,63 @@ public final class Objects extends CollectionBinaryQuery<IntProcedure> implement
         } else {
             computeNotFunctionalIndex(graph, r1, r2, entry, ri, procedure);
         }
-               
-               if(entry != null) entry.performFromCache(graph, procedure_);
 
-       }
+        if(entry != null) entry.performFromCache(graph, procedure_);
 
-       @Override
-       public String toString() {
-               return "Objects[" + r1() + " - " + r2() + "]";
-       }
+    }
 
-       @Override
-       public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
+    @Override
+    public String toString() {
+        return "Objects[" + r1() + " - " + r2() + "]";
+    }
 
-               assert(isReady());
+    @Override
+    public Object performFromCache(ReadGraphImpl graph, final IntProcedure procedure) throws DatabaseException {
 
-               if(handleException(graph, procedure)) return getResult();
+        assert(isReady());
 
-               final IntArray value = (IntArray)getResult();
-               if(value.data == null) {
-                       if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
-               } else {
-                       for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
-               }
+        if(handleException(graph, procedure)) return getResult();
 
-               procedure.finished(graph);
-               
-               return value;
+        final IntArray value = (IntArray)getResult();
+        if(value.data == null) {
+            if(value.sizeOrData != IntArray.NO_DATA) procedure.execute(graph, value.sizeOrData);
+        } else {
+            for(int i = 0;i < value.sizeOrData ; i++) procedure.execute(graph, value.data[i]);
+        }
+
+        procedure.finished(graph);
 
-       }
+        return value;
 
-       @Override
-       public void recompute(ReadGraphImpl graph) throws DatabaseException {
+    }
 
-               compute(graph, new IntProcedureAdapter() {
+    @Override
+    public void recompute(ReadGraphImpl graph) throws DatabaseException {
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                       }
+        compute(graph, new IntProcedureAdapter() {
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               new Error("Error in recompute.", t).printStackTrace();
-                       }
+            @Override
+            public void finished(ReadGraphImpl graph) {
+            }
 
-               });
+            @Override
+            public void exception(ReadGraphImpl graph, Throwable t) {
+                new Error("Error in recompute.", t).printStackTrace();
+            }
 
-       }
+        });
 
-       @Override
-       public int type() {
-               return RequestFlags.IMMEDIATE_UPDATE;
-       }
+    }
 
-       @Override
-       boolean isImmutable(ReadGraphImpl graph) {
-               return graph.processor.isImmutable(r1());
-       }
+    @Override
+    public int type() {
+        return RequestFlags.IMMEDIATE_UPDATE;
+    }
+
+    @Override
+    boolean isImmutable(ReadGraphImpl graph) {
+        return graph.processor.isImmutable(r1());
+    }
 
     @Override
     public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
index dd410b4ce7e8c57fba7e86d94a30dbb7b9ec1e9f..91200f1fc3ad037393bc5e3794d6acc4c29a4e7b 100644 (file)
@@ -14,15 +14,12 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.concurrent.Semaphore;
-import java.util.function.Consumer;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.db.DevelopmentKeys;
 import org.simantics.db.debug.ListenerReport;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.impl.graph.ReadGraphImpl;
-import org.simantics.db.impl.graph.WriteGraphImpl;
 import org.simantics.db.procedure.ListenerBase;
 import org.simantics.utils.Development;
 import org.simantics.utils.datastructures.Pair;
@@ -34,11 +31,10 @@ import gnu.trove.set.hash.THashSet;
 
 public class QueryListening {
 
-    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QueryListening.class);
+    static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(QueryListening.class);
 
     private final QueryProcessor                                    processor;
     private final Scheduler                                         scheduler;
-    private final Consumer<Runnable>                                consumer;
     private final Map<ListenerBase,ListenerEntry>                   addedEntries = new HashMap<>();
 
     private THashSet<ListenerEntry>                                 scheduledListeners    = new THashSet<ListenerEntry>();
@@ -46,210 +42,11 @@ public class QueryListening {
 
     final THashMap<CacheEntry, ArrayList<ListenerEntry>>    listeners = new THashMap<CacheEntry, ArrayList<ListenerEntry>>(10, 0.75f);
 
-    private static class ThreadQueue extends ThreadLocal<ArrayList<Runnable>> {
-
-        private final Map<Thread,ArrayList<Runnable>> allQueues = new HashMap<>();
-        
-        private ArrayList<ArrayList<Runnable>> dispatchedQueues = new ArrayList<>();
-
-        @Override
-        protected synchronized ArrayList<Runnable> initialValue() {
-            ArrayList<Runnable> result = new ArrayList<>();
-            allQueues.put(Thread.currentThread(), result);
-            return result;
-        }
-
-        synchronized void sendToExecution() {
-            ArrayList<Runnable> rs = allQueues.remove(Thread.currentThread());
-            dispatchedQueues.add(rs);
-            notify();
-        }
-
-        synchronized ArrayList<ArrayList<Runnable>> getDispatchedQueues() {
-            ArrayList<ArrayList<Runnable>> result = dispatchedQueues;
-            dispatchedQueues = new ArrayList<>();
-            return result;
-        }
-
-    }
-
-    private static class Scheduler {
-
-        private static final int BUFFER_SIZE = 100;
-
-        private final QueryProcessor processor;
-        
-        private final ThreadQueue queues = new ThreadQueue();
-
-        /*
-         * Access to this field is synchronized using the monitor of 'queues'
-         * The method flush() shall be called by the single writing thread and the field has been nulled before the
-         * method can exit. Thus it is not possible for multiple instances of flush Semaphore to exist at the same time.
-         */
-        private Semaphore flush = null;
-
-        Scheduler(QueryProcessor processor) {
-            this.processor = processor;
-        }
-        
-        private boolean isTerminated() {
-            return processor.isDisposed();
-        }
-
-        Consumer<Runnable> newConsumer() {
-            return (task) -> {
-
-                ArrayList<Runnable> l = queues.get();
-                l.add(task);
-                if(l.size() == BUFFER_SIZE) {
-                    queues.remove();
-                    queues.sendToExecution();
-                }
-                
-            };
-        }
-
-        void start() {
-            
-            Thread thread = new Thread() {
-                
-                public void run() {
-
-                    synchronized(queues) {
-                        while(!isTerminated()) {
-                            try {
-                                ArrayList<ArrayList<Runnable>> qs = queues.getDispatchedQueues();
-                                for(ArrayList<Runnable> queue : qs) {
-                                    for(Runnable r : queue)
-                                        r.run();
-                                }
-                                if(flush != null) {
-                                    for(ArrayList<Runnable> queue : queues.allQueues.values()) {
-                                        for(Runnable r : queue) {
-                                            r.run();   
-                                        }
-                                        queue.clear();
-                                    }
-                                    Semaphore s = flush;
-                                    flush = null;
-                                    s.release();
-                                }
-                                queues.wait(1000);
-                            } catch (InterruptedException e) {
-                                LOGGER.error("Unexpected interrupt", e);
-                            }
-                        }
-                    }
-
-                };
-                
-            };
-            
-            thread.setName("QueryListening");
-            thread.start();
-            
-        }
-
-        private Semaphore createFlush() {
-            synchronized(queues) {
-                flush = new Semaphore(0);
-                queues.notify();
-                return flush;
-            }
-        }
-        
-        void flush() {
-            try {
-                createFlush().acquire();
-            } catch (InterruptedException e) {
-                LOGGER.error("Unexpected interrupt", e);
-            }
-        }
-
-    }
-
-    private static class RegisterParentRunnable implements Runnable {
-        
-        private final CacheEntry parent;
-        private final CacheEntry child;
-        
-        public RegisterParentRunnable(CacheEntry parent, CacheEntry child) {
-            this.parent = parent;
-            this.child = child;
-        }
-
-        @Override
-        public void run() {
-            child.addParent(parent);
-            if (Development.DEVELOPMENT) {
-                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_DEPENDENCIES, Bindings.BOOLEAN)) {
-                    System.out.println(child + " -> " + parent);
-                }
-            }
-        }
-        
-    }
-    
-    private static class RegisterListenerRunnable implements Runnable {
-
-        private final QueryListening queryListening;
-        private final ListenerBase base;
-        private final Object procedure;
-        private final CacheEntry parent;
-        private final CacheEntry entry;
-
-        public RegisterListenerRunnable(QueryListening queryListening, ListenerBase base, Object procedure, CacheEntry parent, CacheEntry entry) {
-            this.queryListening = queryListening;
-            this.base = base;
-            this.procedure = procedure;
-            this.parent = parent;
-            this.entry = entry;
-        }
-
-        @Override
-        public void run() {
-
-            assert (entry != null);
-            assert (procedure != null);
-
-            ArrayList<ListenerEntry> list = queryListening.listeners.get(entry);
-            if (list == null) {
-                list = new ArrayList<>(1);
-                queryListening.listeners.put(entry, list);
-            }
-
-            ListenerEntry result = new ListenerEntry(entry, base, procedure);
-            // Equals is here based on base
-            int currentIndex = list.indexOf(result);
-            // There was already a listener
-            if(currentIndex > -1) {
-                ListenerEntry current = list.get(currentIndex);
-                if(!current.base.isDisposed())
-                    return;
-                list.set(currentIndex, result);
-            } else {
-                list.add(result);
-            }
-
-            if (Development.DEVELOPMENT) {
-                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
-                    new Exception().printStackTrace();
-                    System.err.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
-                }
-            }
-
-            queryListening.addedEntries.put(base, result);
-
-        }
-
-        
-    }
     
     QueryListening(QueryProcessor processor) {
         
         this.processor = processor;
         scheduler = new Scheduler(processor);
-        consumer = scheduler.newConsumer();
         scheduler.start();
         
     }
@@ -260,7 +57,7 @@ public class QueryListening {
     
     void sync() {
         try {
-            scheduler.flush();
+            scheduler.sync();
         } catch (Throwable t) {
             LOGGER.error("Error while waiting for query dependency management", t);
         }
@@ -276,7 +73,7 @@ public class QueryListening {
         if(parent != null) {
             try {
                 if(!child.isImmutable(graph))
-                    consumer.accept(new RegisterParentRunnable(parent, child));
+                    scheduler.accept(new RegisterParentRunnable(parent, child));
             } catch (DatabaseException e) {
                 LOGGER.error("Error while registering query dependencies", e);
             }
@@ -284,7 +81,7 @@ public class QueryListening {
 
         if(listener != null)
             if(!listener.isDisposed())
-                consumer.accept(new RegisterListenerRunnable(this, listener, procedure, parent, child));
+               scheduler.accept(new RegisterListenerRunnable(this, listener, procedure, parent, child));
 
     }
 
@@ -292,10 +89,7 @@ public class QueryListening {
         
         if(base == null) return;
 
-        consumer.accept(() -> {
-            ListenerEntry entry = addedEntries.get(base);
-            if(entry != null) entry.setLastKnown(result);
-        });
+        scheduler.accept(new RegisterFirstKnownRunnable(addedEntries, base, result));
 
     }
 
@@ -413,7 +207,7 @@ public class QueryListening {
 
     }
 
-    public void fireListeners(WriteGraphImpl graph) {
+    public void fireListeners(ReadGraphImpl graph) {
 
         assert (!processor.updating);
         assert (!processor.cache.collecting);
@@ -529,5 +323,102 @@ public class QueryListening {
         else 
             return Collections.emptyList();
     }
-    
+
+    private static class RegisterParentRunnable implements Runnable {
+
+        private final CacheEntry parent;
+        private final CacheEntry child;
+
+        public RegisterParentRunnable(CacheEntry parent, CacheEntry child) {
+            this.parent = parent;
+            this.child = child;
+        }
+
+        @Override
+        public void run() {
+            child.addParent(parent);
+            if (Development.DEVELOPMENT) {
+                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_DEPENDENCIES, Bindings.BOOLEAN)) {
+                    System.out.println(child + " -> " + parent);
+                }
+            }
+        }
+
+    }
+
+    private static class RegisterListenerRunnable implements Runnable {
+
+        private final QueryListening queryListening;
+        private final ListenerBase base;
+        private final Object procedure;
+        private final CacheEntry parent;
+        private final CacheEntry entry;
+
+        public RegisterListenerRunnable(QueryListening queryListening, ListenerBase base, Object procedure, CacheEntry parent, CacheEntry entry) {
+            this.queryListening = queryListening;
+            this.base = base;
+            this.procedure = procedure;
+            this.parent = parent;
+            this.entry = entry;
+        }
+
+        @Override
+        public void run() {
+
+            assert (entry != null);
+            assert (procedure != null);
+
+            ArrayList<ListenerEntry> list = queryListening.listeners.get(entry);
+            if (list == null) {
+                list = new ArrayList<>(1);
+                queryListening.listeners.put(entry, list);
+            }
+
+            ListenerEntry result = new ListenerEntry(entry, base, procedure);
+            // Equals is here based on base
+            int currentIndex = list.indexOf(result);
+            // There was already a listener
+            if(currentIndex > -1) {
+                ListenerEntry current = list.get(currentIndex);
+                if(!current.base.isDisposed())
+                    return;
+                list.set(currentIndex, result);
+            } else {
+                list.add(result);
+            }
+
+            if (Development.DEVELOPMENT) {
+                if(Development.<Boolean>getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) {
+                    new Exception().printStackTrace();
+                    System.err.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure);
+                }
+            }
+
+            queryListening.addedEntries.put(base, result);
+
+        }
+
+
+    }
+
+    private static class RegisterFirstKnownRunnable implements Runnable {
+
+        private final Map<ListenerBase,ListenerEntry> addedEntries;
+        private final ListenerBase base;
+        private final Object result;
+
+        public RegisterFirstKnownRunnable(Map<ListenerBase,ListenerEntry> addedEntries, ListenerBase base, Object result) {
+            this.addedEntries = addedEntries;
+            this.base = base;
+            this.result = result;
+        }
+
+        @Override
+        public void run() {
+            ListenerEntry entry = addedEntries.get(base);
+            if(entry != null) entry.setLastKnown(result);
+        }
+
+    }
+
 }
index a46bc0e8dd4e1b024dea3b0dd8d7269b10a19192..6d9560940be2b1c19b73616c85a2996ee2b65d25 100644 (file)
@@ -1279,8 +1279,9 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                        entry.prepareRecompute(querySupport);
                        
                        ReadGraphImpl parentGraph = graph.forRecompute(entry);
-
+                       parentGraph.asyncBarrier.inc();
                        query.recompute(parentGraph);
+                       parentGraph.asyncBarrier.dec();
 
                        if(entry.isExcepted()) return ListenerEntry.NO_VALUE;
 
@@ -4053,6 +4054,10 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap
                return L0;
        }
 
+       public Layer0 getL0() {
+               return L0;
+       }
+
     public static ThreadLocal<Integer> thread = new ThreadLocal<Integer>() {
         protected Integer initialValue() {
             return -1;
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Scheduler.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Scheduler.java
new file mode 100644 (file)
index 0000000..2c9c475
--- /dev/null
@@ -0,0 +1,203 @@
+package org.simantics.db.impl.query;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+
+class Scheduler extends ThreadLocal<TaskList> {
+
+    private final QueryProcessor processor;
+
+    private static final int MAX_TASKLIST_SIZE = 1<<8;
+
+    /*
+     * New TaskList objects shall be assigned this size.
+     * This shall grow exponentially upon task list creation to max size and shall reset to 1 when a write synchronizes the tasks.
+     * The intention is to make sure that upon frequent syncs the tasks shall be scheduled
+     */
+    private int currentTaskListSize = 1;
+
+    /*
+     * Anyone wishing to execute any tasks needs to hold this monitor
+     */
+    private Object taskExecutionMonitor = new Object();
+
+    /*
+     * Anyone wishing to manipulate the list of dispatched tasks needs to hold this monitor
+     */
+    private Object taskDispatchMonitor = new Object();
+
+    /*
+     * When a thread-specific TaskList becomes full it is added into this list for execution.
+     * The executor thread takes TaskLists from this list.
+     * The sync operation can also execute remaining tasks.
+     */
+    private ArrayList<TaskList> dispatchedTaskLists;
+
+    /*
+     * This replicates the ThreadLocal map of TaskList objects to enable listing of tasks active queues
+     */
+    private final Map<Thread,TaskList> activeTaskLists = new HashMap<>();
+
+    /*
+     * This semaphore is incremented each time s task list gets dispatched. The execution thread waits for the semaphore.
+     */
+    private final Semaphore taskDispatchNotifications = new Semaphore(0);
+
+    Scheduler(QueryProcessor processor) {
+        this.processor = processor;
+    }
+
+    /*
+     * This gets called by multiple query threads
+     */
+    void accept(Runnable task) {
+        TaskList l = get();
+        l.add(task);
+        if(l.shouldSchedule()) {
+            remove();
+            sendToExecution();
+        }
+    }
+
+    /*
+     * A task list has reached full size and is moved into execution by the execution thread
+     */
+    void sendToExecution() {
+        synchronized(activeTaskLists) {
+            // This is dispatched so it should not anymore be in list of active TaskList objects.
+            TaskList l = activeTaskLists.remove(Thread.currentThread());
+            synchronized(taskDispatchMonitor) {
+                if(dispatchedTaskLists == null)
+                    dispatchedTaskLists = new ArrayList<TaskList>();
+                dispatchedTaskLists.add(l);
+            }
+            if(currentTaskListSize < MAX_TASKLIST_SIZE)
+                currentTaskListSize = currentTaskListSize<<1;
+        }
+        // Release the execution thread
+        taskDispatchNotifications.release();
+    }
+
+    /*
+     * Gets dispatched TaskList objects for execution.
+     * Returns null when there's nothing to execute (and thread shall go to sleep).
+     */
+    ArrayList<TaskList> getDispatchedQueues() {
+        synchronized(taskDispatchMonitor) {
+            if(dispatchedTaskLists == null)
+                return null;
+            ArrayList<TaskList> result = dispatchedTaskLists;
+            dispatchedTaskLists = null;
+            return result;
+        }
+    }
+
+    void start() {
+
+        Thread thread = new Thread() {
+
+            public void run() {
+
+                // We execute tasks as long as the query processor is alive
+                while(!processor.isDisposed()) {
+
+                    try {
+
+                        // This is a mutex between this place and sync()
+                        synchronized(taskExecutionMonitor) {
+
+                            // Execute busily while there is something to execute
+                            while(true) {
+
+                                ArrayList<TaskList> qs = getDispatchedQueues();
+                                if(qs == null) {
+                                    // No tasks - go to sleep
+                                    break;
+                                }
+
+                                // Execute everything we got
+                                for(TaskList queue : qs) {
+                                    for(Runnable r : queue) {
+                                        r.run();
+                                    }
+                                }
+
+                            }
+
+                        }
+
+                        // sendToExecution shall release this 
+                        taskDispatchNotifications.acquire();
+
+                    } catch (InterruptedException e) {
+                        QueryListening.LOGGER.error("Unexpected interrupt", e);
+                    }
+
+                }
+
+            };
+
+        };
+
+        thread.setName("QueryListening");
+        thread.start();
+
+    }
+
+    /*
+     * ThreadLocal calls this to create a TaskList.
+     * Called with first list per thread and also when accepting next task after sendToExecution. 
+     */
+    @Override
+    protected TaskList initialValue() {
+        TaskList result = new TaskList(currentTaskListSize);
+        synchronized(activeTaskLists) {
+            activeTaskLists.put(Thread.currentThread(), result);
+        }
+        return result;
+    }
+
+    /*
+     * This makes sure that all tasks have been executed upon return.
+     * It takes the taskExecutionMonitor from the thread and executes possible dispatched work and
+     * also executes anything in active task lists. It resets the dispatch sizes of current and
+     * subsequently created task lists to 1.
+     */
+    void sync() {
+
+        // This is a mutex between this place and execution thread
+        synchronized(taskExecutionMonitor) {
+
+            currentTaskListSize = 1;
+
+            // Perform all dispatched work
+            ArrayList<TaskList> qs = getDispatchedQueues();
+            if(qs != null) {
+                for(TaskList queue : qs) {
+                    for(Runnable r : queue) {
+                        r.run();
+                    }
+                }
+            }
+
+            // Also perform any tasks in active queues.
+            // This assumes that all query threads that send new tasks are now parked and shall not interfere.
+            synchronized(activeTaskLists) {
+                for(TaskList queue : activeTaskLists.values()) {
+                    // Run all tasks
+                    for(Runnable r : queue) {
+                        if(r != null)
+                            r.run();
+                    }
+                    // Remove the tasks from list and reset the max size to 1.
+                    queue.reset();
+                }
+            }
+
+        }
+
+    }
+
+}
\ No newline at end of file
index 6652f1b6bac9aac657ec22aa8c2f2d329591b8aa..218777413fe496a3afbba9d8dfb142a1fd0f1194 100644 (file)
@@ -11,8 +11,6 @@
  *******************************************************************************/
 package org.simantics.db.impl.query;
 
-import java.util.concurrent.atomic.AtomicBoolean;
-
 import org.simantics.db.RelationInfo;
 import org.simantics.db.common.exception.DebugException;
 import org.simantics.db.exception.DatabaseException;
@@ -24,93 +22,93 @@ import org.simantics.db.procedure.ListenerBase;
 import org.simantics.db.request.RequestFlags;
 
 public final class Statements extends CollectionBinaryQuery<TripleIntProcedure> implements TripleIntProcedure {
-       
+
     public Statements(final int r1, final int r2) {
         super(r1, r2);
     }
-    
+
     final public static void queryEach(ReadGraphImpl graph, final int r1, final int r2, final QueryProcessor provider, final CacheEntry parent, final ListenerBase listener, final TripleIntProcedure procedure) throws DatabaseException {
-        
-       assert(r1 != 0);
-       assert(r2 != 0);
-       
+
+        assert(r1 != 0);
+        assert(r2 != 0);
+
         if(parent == null && listener == null) {
-               Statements.computeForEach(graph, r1, r2, null, procedure);
-               return;
+            Statements.computeForEach(graph, r1, r2, null, procedure);
+            return;
         }
-        
+
         QueryCache.runnerStatements(graph, r1, r2, parent, listener, procedure);
-         
+
     }
 
-       @Override
-       final public void removeEntry(QueryProcessor provider) {
+    @Override
+    final public void removeEntry(QueryProcessor provider) {
         provider.cache.remove(this);
-       }
-       
+    }
+
     final static TripleIntProcedure NOPT = new TripleIntProcedure() {
 
 
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
+        @Override
+        public void exception(ReadGraphImpl graph, Throwable throwable) {
+        }
 
-               @Override
-               public void execute(ReadGraphImpl graph, int s, int p, int o) {
-               }
+        @Override
+        public void execute(ReadGraphImpl graph, int s, int p, int o) {
+        }
+
+        @Override
+        public void finished(ReadGraphImpl graph) {
+        }
 
-               @Override
-               public void finished(ReadGraphImpl graph) {
-               }
-       
     };
-       
+
     final static private IntArray getAssertionMap(ReadGraphImpl graph, final int r1, final int r2, final Statements entry) throws DatabaseException {
-       
+
         class AssertionMapProc implements IntProcedure {
-               
-               boolean first = true;
-
-               private IntArray result;
-
-               public void addStatement(int s, int p, int o) {
-                       
-                       if(result.size() == 0) {
-                               result.add(s);
-                               result.add(p);
-                               result.add(o);
-                       } else {
-                               for(int i = 0;i < result.sizeOrData ; i+=3) {
-                                       int existingP = result.data[i+1];
-                                       if(p == existingP) {
-                                               int existingO = result.data[i+2];
-                                               if(existingO == o) return;
-                                       }
-                               }
-                               result.add(s);
-                               result.add(p);
-                               result.add(o);
-                       }
-                       
-               }
-               
+
+            boolean first = true;
+
+            private IntArray result;
+
+            public void addStatement(int s, int p, int o) {
+
+                if(result.size() == 0) {
+                    result.add(s);
+                    result.add(p);
+                    result.add(o);
+                } else {
+                    for(int i = 0;i < result.sizeOrData ; i+=3) {
+                        int existingP = result.data[i+1];
+                        if(p == existingP) {
+                            int existingO = result.data[i+2];
+                            if(existingO == o) return;
+                        }
+                    }
+                    result.add(s);
+                    result.add(p);
+                    result.add(o);
+                }
+
+            }
+
             @Override
             public void execute(ReadGraphImpl graph, int type) throws DatabaseException {
                 if(result == null) {
-                       result = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
+                    result = QueryCache.resultAssertedStatements(graph, type, r2, entry, null);
                 } else {
-                       if (first) {
-                               IntArray ia = result;
-                               result = new IntArray();
-                               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]);
-                               }
-                               first = false;
-                       }
-                       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]);
-                       }
+                    if (first) {
+                        IntArray ia = result;
+                        result = new IntArray();
+                        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]);
+                        }
+                        first = false;
+                    }
+                    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]);
+                    }
                 }
             }
 
@@ -118,322 +116,336 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
             public void finished(ReadGraphImpl graph) {
             }
 
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
+            @Override
+            public void exception(ReadGraphImpl graph, Throwable throwable) {
+            }
 
         }
-        
+
         AssertionMapProc amp = new AssertionMapProc();
 
         // This dependency could be cut
         QueryCache.runnerPrincipalTypes(graph, r1, entry, null, amp);
-       
+
         return amp.result;
-       
+
     }
-       
+
     final static private void forSingleAssertion(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final TripleIntProcedure procedure) throws DatabaseException {
-       
-       IntArray map = getAssertionMap(graph, r1, r2, parent);
-       if(map == null) {
-               procedure.finished(graph);
+
+        IntArray map = getAssertionMap(graph, r1, r2, parent);
+        if(map == null) {
+            procedure.finished(graph);
             return;
-       }
-        
+        }
+
         int size = map.size();
         if(size == 3) {
 
-               int s = map.data[0];
-               int p = map.data[1];
-               int o = map.data[2];
-               
-                       procedure.execute(graph, s,p,o);
-                       procedure.finished(graph);
+            int s = map.data[0];
+            int p = map.data[1];
+            int o = map.data[2];
+
+            procedure.execute(graph, s,p,o);
+            procedure.finished(graph);
 
         } else if(size == 0) {
 
-               procedure.finished(graph);
-               
+            procedure.finished(graph);
+
         } else {
 
-               int candidateS = map.data[0];
-               int candidateP = map.data[1];
-               int candidateO = map.data[2];
-               
-                       IntSet candidateIs = null;
-                       try {
-                               candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
-                       } catch (DatabaseException e) {
-                               procedure.exception(graph, e);
-                               return;
-                       }
-
-                       for(int i=3;i<map.size();i+=3) {
-
-                               int nextS = map.data[i];
-                               int nextP = map.data[i+1];
-                               int nextO = map.data[i+2];
-                       
-                               if(nextS != candidateS) {
-
-                               if(candidateIs.contains(nextS)) {
-                                       
-                                       // Next is a super type of candidate => ignore next
-                                       
-                               } else {
-                               
-                                       IntSet nextIs = null;
-                                       try {
-                                               nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
-                                       } catch (DatabaseException e) {
-                                               procedure.exception(graph, e);
-                                               return;
-                                       }
-                                       
-                                       if(nextIs.contains(candidateS)) {
-
-                                               // Candidate is a super type of next => next is the new candidate
-                                               
-                                               candidateS = nextS;
-                                               candidateP = nextP;
-                                               candidateO = nextO;
-                                               candidateIs = nextIs;
-                                               
-                                       } else {
-                                               // candidate and next are unrelated => error
-                                               ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions.", r1);
-                                               procedure.exception(graph, exception);
-                                               return;                                         
-                                       }
-                               
-                               }
-                               
-                       }
-                       
-               }
-               
+            int candidateS = map.data[0];
+            int candidateP = map.data[1];
+            int candidateO = map.data[2];
+
+            IntSet candidateIs = null;
+            try {
+                candidateIs = QueryCache.resultSuperTypes(graph, candidateS, parent, null);
+            } catch (DatabaseException e) {
+                procedure.exception(graph, e);
+                return;
+            }
+
+            for(int i=3;i<map.size();i+=3) {
+
+                int nextS = map.data[i];
+                int nextP = map.data[i+1];
+                int nextO = map.data[i+2];
+
+                if(nextS != candidateS) {
+
+                    if(candidateIs.contains(nextS)) {
+
+                        // Next is a super type of candidate => ignore next
+
+                    } else {
+
+                        IntSet nextIs = null;
+                        try {
+                            nextIs = QueryCache.resultSuperTypes(graph, nextS, parent, null);
+                        } catch (DatabaseException e) {
+                            procedure.exception(graph, e);
+                            return;
+                        }
+
+                        if(nextIs.contains(candidateS)) {
+
+                            // Candidate is a super type of next => next is the new candidate
+
+                            candidateS = nextS;
+                            candidateP = nextP;
+                            candidateO = nextO;
+                            candidateIs = nextIs;
+
+                        } else {
+                            // candidate and next are unrelated => error
+                            ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has conflicting assertions.", r1);
+                            procedure.exception(graph, exception);
+                            return;                                            
+                        }
+
+                    }
+
+                }
+
+            }
+
             procedure.execute(graph, candidateS, candidateP, candidateO);
             procedure.finished(graph);
-               
+
         }
-        
+
     }
-    
+
     final static InternalProcedure<IntSet> NOP = new InternalProcedure<IntSet>() {
 
-               @Override
-               public void execute(ReadGraphImpl graph, IntSet result) {
-               }
+        @Override
+        public void execute(ReadGraphImpl graph, IntSet result) {
+        }
+
+        @Override
+        public void exception(ReadGraphImpl graph, Throwable throwable) {
+        }
 
-               @Override
-               public void exception(ReadGraphImpl graph, Throwable throwable) {
-               }
-       
     };
-       
-       // Search for one statement
-       final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
-        
+
+    // Search for one statement
+    final static public void computeFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
+
         if(ri.isFinal) {
-            
-               int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
 
-               if(result == 0) {
+            int result = graph.processor.querySupport.getFunctionalObject(r1, r2);
 
-               // Check for assertions
-               forSingleAssertion(graph, r1, r2, parent, procedure);
+            if(result == 0) {
 
-               } else if(result == -1) {
+                // Check for assertions
+                forSingleAssertion(graph, r1, r2, parent, procedure);
 
-               graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
+            } else if(result == -1) {
+
+                graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
+
+                    @Override
+                    public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                        procedure.execute(graph, r1, r2, i);
+                    }
 
-                       @Override
-                       public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                               procedure.execute(graph, r1, r2, i);
-                       }
+                    @Override
+                    public void exception(ReadGraphImpl graph, Throwable t) {
+                        if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                    }
 
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                       }
+                    @Override
+                    public void finished(ReadGraphImpl graph) {
+                    }
 
-                       @Override
-                       public void finished(ReadGraphImpl graph) {
-                       }
+                });
 
-               });
+                // Check for assertions
+                forSingleAssertion(graph, r1, r2, parent, procedure);
 
-               // Check for assertions
-               forSingleAssertion(graph, r1, r2, parent, procedure);
-                       
-               } else {
+            } else {
 
-               // If functional relation was found there is no need to check assertions
+                // If functional relation was found there is no need to check assertions
                 procedure.execute(graph, r1, r2, result);
                 procedure.finished(graph);
-                       
-               }
 
-            
+            }
+
+
         } else {
-            
-            final AtomicBoolean found = new AtomicBoolean(false);
-            
+
             // Note! The dependency is intentionally cut!
             IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
-                
+
+                /*
+                 * 0 = not found
+                 * 1 = found
+                 * 2 = exception
+                 */
+                int found = 0;
+
                 @Override
                 public void run(ReadGraphImpl graph) throws DatabaseException {
-                    
-                    if(found.get()) {
-                       procedure.finished(graph);
-                    } else {
+
+                    if(found == 1) {
+
+                        procedure.finished(graph);
+
+                    } else if(found == 0) {
+
                         // Check for assertions
                         forSingleAssertion(graph, r1, r2, parent, procedure);
+
                     }
-                    
+
                 }
 
                 @Override
                 public void execute(ReadGraphImpl graph, final int pred) throws DatabaseException {
-                    
-                    if(found.get()) return;
+
+                    if(found > 0)
+                        return;
 
                     if(pred == r2) {
-                        
-                        inc();
-                        
+
                         // Note! The dependency is intentionally cut!
                         QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
 
                             @Override
                             public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                
-                               if(found.compareAndSet(false, true)) {
+
+                                if(found == 0) {
+
                                     procedure.execute(graph, r1, pred, i);
-                               } else {
-                                       ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement.", r1);
-                                       procedure.exception(graph, exception);
-                               }
+                                    found = 1;
+
+                                } else {
+
+                                    ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement.", r1);
+                                    procedure.exception(graph, exception);
+                                    found = 2;
+
+                                }
 
                             }
 
                             @Override
                             public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                dec(graph);
                             }
-                                               
-                                               @Override
-                                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                       procedure.exception(graph, t);
-                                dec(graph);
-                                   }
+
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+
+                                procedure.exception(graph, t);
+                                found = 2;
+
+                            }
 
                         });
 
                     } else {
-                        
-                        inc();
-                    
+
                         QueryCache.runnerSuperRelations(graph, pred, parent, null, new InternalProcedure<IntSet>() {
-    
+
                             @Override
                             public void execute(ReadGraphImpl graph, IntSet result) throws DatabaseException {
-                                
-                                if(found.get()) {
-                                    dec(graph);
+
+                                if(found > 0)
                                     return;
-                                }
 
                                 if(result.contains(r2)) {
-                                    
+
                                     inc();
-                                    
+
                                     // Note! The dependency is intentionally cut!
                                     QueryCache.runnerDirectObjects(graph, r1, pred, null, null, new IntProcedure() {
-    
+
                                         @Override
                                         public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                            
-                                               if(found.compareAndSet(false, true)) {
-                                               procedure.execute(graph, r1, pred, i);
-                                               } else {
-                                               ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement.", r1);
-                                               procedure.exception(graph, exception);
-                                               }
-                                            
+
+                                            if(found == 0) {
+
+                                                procedure.execute(graph, r1, pred, i);
+                                                found = 1;
+
+                                            } else {
+
+                                                ManyObjectsForFunctionalRelationException exception = new ManyObjectsForFunctionalRelationException("Functional relation has more than one statement (r1=" + r1 + ", r2=" + r2 + ").", r1);
+                                                procedure.exception(graph, exception);
+                                                found = 2;
+
+                                            }
+
                                         }
-    
+
                                         @Override
                                         public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                            dec(graph);
                                         }
-                                                       
-                                                       @Override
-                                                       public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                               procedure.exception(graph, t);
-                                            dec(graph);
-                                           }
+
+                                        @Override
+                                        public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                            procedure.exception(graph, t);
+                                            found = 2;
+                                        }
 
                                     });
-    
+
                                 }
-                                
-                                dec(graph);
-                                
+
+                            }
+
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                procedure.exception(graph, t);
+                                found = 2;
                             }
-                                               
-                                               @Override
-                                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                       procedure.exception(graph, t);
-                                dec(graph);
-                                   }
 
                         });
-                        
+
                     }
-                    
+
                 }
 
                 @Override
                 public void finished(ReadGraphImpl graph) throws DatabaseException {
                     dec(graph);
                 }
-                
+
             });
-            
+
         }
 
-       }
-    
+    }
+
     final static private void forAssertions(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final TripleIntProcedure procedure) throws DatabaseException {
 
-       QueryCache.runnerPrincipalTypes(graph, r1, parent, null, new SyncIntProcedure() {
-            
+        QueryCache.runnerPrincipalTypes(graph, r1, parent, null, new SyncIntProcedure() {
+
             @Override
             public void run(ReadGraphImpl graph) throws DatabaseException {
                 procedure.finished(graph);
             }
-            
+
             TripleIntProcedure proc = new TripleIntProcedureAdapter() {
 
                 @Override
                 public void execute(ReadGraphImpl graph, int s, int p, int o) throws DatabaseException {
-                       procedure.execute(graph, s, p, o);
+                    procedure.execute(graph, s, p, o);
                 }
 
                 @Override
                 public void finished(ReadGraphImpl graph) throws DatabaseException {
                     dec(graph);
                 }
-                               
-                               @Override
-                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+
+                @Override
+                public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
                     dec(graph);
-                                       procedure.exception(graph, t);
-                   }
+                    procedure.exception(graph, t);
+                }
 
             }; 
 
@@ -442,57 +454,57 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                 inc();
                 QueryCache.runnerAssertedStatements(graph, type, r2, parent, null, proc);
             }
-            
+
             @Override
             public void finished(ReadGraphImpl graph) throws DatabaseException {
                 dec(graph);       
             }
-            
+
             @Override
             public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
                 dec(graph);
             }
-            
+
         });
-        
+
 
     }
 
-       final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
+    final static public void computeNotFunctionalIndex(ReadGraphImpl graph, final int r1, final int r2, final Statements parent, final RelationInfo ri, final TripleIntProcedure procedure) throws DatabaseException {
 
-               if(ri.isFinal) {
+        if(ri.isFinal) {
 
-                       graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
+            graph.processor.querySupport.getObjects(graph, r1, r2, new IntProcedure() {
 
-                               @Override
-                               public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                                       procedure.execute(graph, r1, r2, i);
-                               }
+                @Override
+                public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
+                    procedure.execute(graph, r1, r2, i);
+                }
 
-                               @Override
-                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                       if(DebugException.DEBUG) new DebugException(t).printStackTrace();
-                                       procedure.exception(graph, t);
-                               }
+                @Override
+                public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                    if(DebugException.DEBUG) new DebugException(t).printStackTrace();
+                    procedure.exception(graph, t);
+                }
 
-                               @Override
-                               public void finished(ReadGraphImpl graph) {
-                               }
+                @Override
+                public void finished(ReadGraphImpl graph) {
+                }
 
-                       });
+            });
 
-                       if(ri.isAsserted) {
-                               forAssertions(graph, r1, r2, parent, procedure);
-                       } else {
-                               procedure.finished(graph);
-                       }
+            if(ri.isAsserted) {
+                forAssertions(graph, r1, r2, parent, procedure);
+            } else {
+                procedure.finished(graph);
+            }
 
         } else {
 
             // Note! The dependency is intentionally cut!
             IntSet direct = QueryCache.resultDirectPredicates(graph, r1, null, null);
             direct.forEach(graph, new SyncIntProcedure() {
-                
+
                 @Override
                 public void run(ReadGraphImpl graph) throws DatabaseException {
                     forAssertions(graph, r1, r2, parent, procedure);
@@ -502,36 +514,30 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                 public void execute(ReadGraphImpl graph, final int pred2) throws DatabaseException {
 
                     if(pred2 == r2) {
-                        
-                        inc();
-                        
+
                         // Note! The dependency is intentionally cut!
                         QueryCache.runnerDirectObjects(graph, r1, pred2, null, null, new IntProcedure() {
 
                             @Override
                             public void execute(ReadGraphImpl graph, int i) throws DatabaseException {
-                               procedure.execute(graph, r1, pred2, i);
+                                procedure.execute(graph, r1, pred2, i);
                             }
 
                             @Override
                             public void finished(ReadGraphImpl graph) throws DatabaseException {
-                                dec(graph);
                             }
-                                               
-                                               @Override
-                                               public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
-                                                       procedure.exception(graph, t);
-                                dec(graph);
-                                   }
+
+                            @Override
+                            public void exception(ReadGraphImpl graph, Throwable t) throws DatabaseException {
+                                procedure.exception(graph, t);
+                            }
 
                         });
 
                     } else {
-                    
-//                        inc();
 
                         try {
-                            
+
                             IntSet result = QueryCache.resultSuperRelations(graph, pred2, parent, null);
                             if(result.contains(r2)) {
 
@@ -560,30 +566,30 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
                                 });
 
                             }
-                            
+
                         } catch (Throwable e) {
                             procedure.exception(graph, e);
                         }
 
                     }
-                    
+
                 }
 
                 @Override
                 public void finished(ReadGraphImpl graph) throws DatabaseException {
                     dec(graph);
                 }
-                
+
             });
-            
+
         }
-        
+
     }
-       
+
     public static void computeForEach(ReadGraphImpl graph, final int r1, final int r2, final Statements entry, final TripleIntProcedure procedure_) throws DatabaseException {
-        
+
         TripleIntProcedure procedure = entry != null ? entry : procedure_;
-       
+
         RelationInfo ri = QueryCache.resultRelationInfoQuery(graph, r2, entry, null);
         graph.ensureLoaded(r1, r2);
         if(ri.isFunctional) {
@@ -593,16 +599,16 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
         }
 
         if(entry != null) entry.performFromCache(graph, procedure_);
-        
+
     }
-    
+
     @Override
     public String toString() {
-       return "Statements[" + r1() + " - " + r2() + "]";
+        return "Statements[" + r1() + " - " + r2() + "]";
     }
 
     final private void finish(ReadGraphImpl graph, TripleIntProcedure procedure) throws DatabaseException {
-       
+
         assert(assertPending());
 
         synchronized(this) {
@@ -614,95 +620,95 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
         final IntArray value = (IntArray)getResult();
 
         for(int i=0;i<value.size();i+=3) {
-               procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
+            procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
         }
-        
+
         procedure.finished(graph);
-       
+
     }
 
     synchronized public void addOrSet(int s, int p, int o) {
-        
-       assert(assertPending());
-        
-       IntArray value = (IntArray)getResult();
+
+        assert(assertPending());
+
+        IntArray value = (IntArray)getResult();
         value.add(s);
         value.add(p);
         value.add(o);
-        
+
     }
 
     final static public int r1(long id) {
         return (int)(id>>>32);
     }
-    
+
     final static public int r2(long id) {
         return (int)id;
     }
-    
+
     final public void addOrSetFunctional(int s, long po) {
-       
-       addOrSetFunctional(s, r1(po), r2(po));
-       
+
+        addOrSetFunctional(s, r1(po), r2(po));
+
     }
 
     final public void addOrSetFunctional(int s, int p, int o) {
-        
-       assert(assertPending());
-        
-       IntArray value = (IntArray)getResult();
+
+        assert(assertPending());
+
+        IntArray value = (IntArray)getResult();
         value.add(s);
         value.add(p);
         value.add(o);
-        
+
     }
-    
+
     @Override
     public Object performFromCache(ReadGraphImpl graph, final TripleIntProcedure procedure) throws DatabaseException {
 
-       assert(isReady());
+        assert(isReady());
 
         final IntArray value = (IntArray)getResult();
 
-       if(handleException(graph, procedure)) return value;
-       
+        if(handleException(graph, procedure)) return value;
+
         for(int i=0;i<value.size();i+=3) {
-               procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
+            procedure.execute(graph, value.data[i], value.data[i+1], value.data[i+2]);
         }
 
         procedure.finished(graph);
-        
+
         return value;
-        
+
     }
-    
+
     @Override
     public void recompute(ReadGraphImpl graph) throws DatabaseException {
-        
+
         computeForEach(graph, r1(), r2(), this, new TripleIntProcedureAdapter() {
 
             @Override
             public void finished(ReadGraphImpl graph) {
             }
-                       
-                       @Override
-                       public void exception(ReadGraphImpl graph, Throwable t) {
-                               new Error("Error in recompute.", t).printStackTrace();
+
+            @Override
+            public void exception(ReadGraphImpl graph, Throwable t) {
+                new Error("Error in recompute.", t).printStackTrace();
             }
 
         });
-        
+
     }
 
     @Override
     public int type() {
         return RequestFlags.IMMEDIATE_UPDATE;
     }
-    
+
 
     @Override
     boolean isImmutable(ReadGraphImpl graph) {
-       return graph.processor.isImmutable(r1());
+        return graph.processor.isImmutable(r1());
     }
 
     @Override
@@ -719,5 +725,5 @@ public final class Statements extends CollectionBinaryQuery<TripleIntProcedure>
     public void exception(ReadGraphImpl graph, Throwable throwable) throws DatabaseException {
         except(throwable);
     }
-    
+
 }
diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TaskList.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TaskList.java
new file mode 100644 (file)
index 0000000..7734bae
--- /dev/null
@@ -0,0 +1,24 @@
+package org.simantics.db.impl.query;
+
+import java.util.ArrayList;
+
+class TaskList extends ArrayList<Runnable> {
+
+       private static final long serialVersionUID = -8047504882681478972L;
+
+       private int maxSize;
+
+       TaskList(int maxSize) {
+               this.maxSize = maxSize;
+       }
+
+       boolean shouldSchedule() {
+               return size() == maxSize;
+       }
+
+       void reset() {
+               clear();
+               maxSize = 1;
+       }
+
+}
\ No newline at end of file
index 517ce761ed4d7d8686ae501ae942090f5854fc61..6ad6315b989c8b0704c78f53519131864fa53fc2 100644 (file)
@@ -27,41 +27,43 @@ import org.simantics.scl.runtime.function.FunctionImpl3;
  */
 public abstract class ContextualRelatedValue implements ConverterComputationalValue {
 
-    @SuppressWarnings("unchecked")
-    @Override
-    public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException {
-        return (T) new FunctionImpl3<ReadGraph, Resource, Object, Object>() {
-            @Override
-            public Object apply(ReadGraph graph, Resource converter, Object context) {
-                SCLContext sclContext = SCLContext.getCurrent();
-                Object oldGraph = sclContext.get("graph");
-                try {
-                    if (context instanceof Variable) {
-                        Variable variable = (Variable)context;
-                        try {
-                            Function1<Object,Object> fn = getFunction(graph, variable.getParent(graph).getRepresents(graph), variable.getRepresents(graph), variable.getPredicateResource(graph));
-                            sclContext.put("graph", graph);
-                            return fn.apply(variable);
-                        } catch (DatabaseException e) {
-                            throw new RuntimeDatabaseException(e);
-                        }
-                    } if (context instanceof Resource) {
-                        Resource resource = (Resource)context;
-                        try {
-                            // Here converter is the object and context is the subject
-                            Function1<Object,Object> fn = getFunction(graph, resource, converter, null);
-                            return fn.apply(resource);
-                        } catch (DatabaseException e) {
-                            throw new RuntimeDatabaseException(e);
-                        }
-                    } else {
-                        throw new IllegalStateException("Unknown context " + context);
+    private final FunctionImpl3<ReadGraph, Resource, Object, Object> function = new FunctionImpl3<ReadGraph, Resource, Object, Object>() {
+        @Override
+        public Object apply(ReadGraph graph, Resource converter, Object context) {
+            SCLContext sclContext = SCLContext.getCurrent();
+            Object oldGraph = sclContext.get("graph");
+            try {
+                if (context instanceof Variable) {
+                    Variable variable = (Variable)context;
+                    try {
+                        Function1<Object,Object> fn = getFunction(graph, variable.getParent(graph).getRepresents(graph), variable.getRepresents(graph), variable.getPredicateResource(graph));
+                        sclContext.put("graph", graph);
+                        return fn.apply(variable);
+                    } catch (DatabaseException e) {
+                        throw new RuntimeDatabaseException(e);
+                    }
+                } if (context instanceof Resource) {
+                    Resource resource = (Resource)context;
+                    try {
+                        // Here converter is the object and context is the subject
+                        Function1<Object,Object> fn = getFunction(graph, resource, converter, null);
+                        return fn.apply(resource);
+                    } catch (DatabaseException e) {
+                        throw new RuntimeDatabaseException(e);
                     }
-                } finally {
-                    sclContext.put("graph", oldGraph);
+                } else {
+                    throw new IllegalStateException("Unknown context " + context);
                 }
+            } finally {
+                sclContext.put("graph", oldGraph);
             }
-        };
+        }
+    };
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getValue(ReadGraph graph, Resource resource) throws DatabaseException {
+        return (T) function;
     }
 
 }
index 4e775e08a22e12597044218f138aef3cfcaf6637..671810d8e40853938414353d82fdc7440ccb37bd 100644 (file)
@@ -36,7 +36,6 @@ import org.simantics.db.common.uri.UnescapedChildMapOfResource;
 import org.simantics.db.common.utils.CommonDBUtils;
 import org.simantics.db.common.utils.Functions;
 import org.simantics.db.common.utils.ListUtils;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.common.utils.NearestOwnerFinder;
 import org.simantics.db.common.validation.L0Validations;
@@ -92,15 +91,19 @@ import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.utils.Development;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.strings.StringInputValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.THashMap;
 import gnu.trove.set.hash.THashSet;
 
 public class All {
 
-       public static Object standardGetValue1(ReadGraph graph, Variable context) throws DatabaseException {
+    private static final Logger LOGGER = LoggerFactory.getLogger(All.class);
 
-               StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+    public static Object standardGetValue1(ReadGraph graph, Variable context) throws DatabaseException {
+
+        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
 
         // First from node
         if(variable.node != null) {
@@ -108,59 +111,61 @@ public class All {
             if(Variables.PENDING_NODE_VALUE == value) throw new PendingVariableException("");
             return value.getValue();
         }
-               
-               try {
+
+        try {
 
             if(variable.property.hasEnumerationRange) {
-                       Resource object = variable.getRepresents(graph);
-                               if(graph.sync(new IsEnumeratedValue(object))) {
-                           Layer0 L0 = Layer0.getInstance(graph);
-                                       if(graph.isInstanceOf(object, L0.Literal)) {
-                                               return graph.getValue(object);
-                                       } else {
-                                               String label = graph.getPossibleRelatedValue2(variable.getRepresents(graph), L0.HasLabel, Bindings.STRING);
-                                               if(label == null) label = graph.getPossibleRelatedValue(variable.getRepresents(graph), L0.HasName, Bindings.STRING);
-                                               if(label == null) label = "<no label>";
-                                               return label;
-                                       }
-                               }
+                Resource object = variable.getRepresents(graph);
+                if(graph.sync(new IsEnumeratedValue(object))) {
+                    Layer0 L0 = Layer0.getInstance(graph);
+                    if(graph.isInstanceOf(object, L0.Literal)) {
+                        return graph.getValue(object);
+                    } else {
+                        String label = graph.getPossibleRelatedValue2(variable.getRepresents(graph), L0.HasLabel, Bindings.STRING);
+                        if(label == null) label = graph.getPossibleRelatedValue(variable.getRepresents(graph), L0.HasName, Bindings.STRING);
+                        if(label == null) label = "<no label>";
+                        return label;
+                    }
+                }
             }
-                       
+
             if (variable.isAsserted()) {
-                               if (variable.parentResource != null) {
-                                       Map<String, Pair<PropertyInfo, Resource>> assertions = graph.syncRequest(
-                                                       new UnescapedAssertedPropertyMapOfResource(variable.parentResource),
-                                                       TransientCacheAsyncListener.instance());
-
-                                       // NOTE: This optimization assumes the property
-                                       // variable's representation is the asserted object.
-                                       Resource object = variable.getPossibleRepresents(graph);
-                                       if (object != null) {
-                                               return graph.getValue2(object, variable);
-                                       } else {
-                                               for (Pair<PropertyInfo, Resource> assertion : assertions.values()) {
-                                                       if (assertion.first.predicate.equals(variable.property.predicate)) {
-                                                               return graph.getValue2(assertion.second, variable);
-                                                       }
-                                               }
-                                       }
-                               }
+                if (variable.parentResource != null) {
+                    Map<String, Pair<PropertyInfo, Resource>> assertions = graph.syncRequest(
+                            new UnescapedAssertedPropertyMapOfResource(variable.parentResource),
+                            TransientCacheAsyncListener.instance());
+
+                    // NOTE: This optimization assumes the property
+                    // variable's representation is the asserted object.
+                    Resource object = variable.getPossibleRepresents(graph);
+                    if (object != null) {
+                        return graph.getValue2(object, variable);
+                    } else {
+                        for (Pair<PropertyInfo, Resource> assertion : assertions.values()) {
+                            if (assertion.first.predicate.equals(variable.getPossiblePredicateResource(graph))) {
+                                return graph.getValue2(assertion.second, variable);
+                            }
+                        }
+                    }
+                }
             }
-                
-                       return graph.getValue2(variable.getRepresents(graph), variable);
-                       
-               } catch (NoSingleResultException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               } catch (DoesNotContainValueException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               } catch (DatabaseException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               }
-
-       }
-       
-       public static Object standardGetValue2(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {           
-               StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+
+            return graph.getValue2(variable.getRepresents(graph), variable);
+
+        } catch (PendingVariableException e) {
+            throw e;
+        } catch (NoSingleResultException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        } catch (DoesNotContainValueException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        } catch (DatabaseException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        }
+
+    }
+
+    public static Object standardGetValue2(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {              
+        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
 
         // First from node
         if(variable.node != null) {
@@ -173,61 +178,61 @@ public class All {
                 throw new AdaptionException("Could not get value for " + context.getURI(graph), e);
             }
         }
-               
-       try {
-                       
-               if(variable.property.hasEnumerationRange) {
-               Resource object = variable.getRepresents(graph);
-               if(graph.sync(new IsEnumeratedValue(object))) {
-                       Layer0 L0 = Layer0.getInstance(graph);
-                       if(graph.isInstanceOf(object, L0.Literal)) {
-                               return graph.getValue(object, binding);
-                       } else {
-                               return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
-                       }
-               }
+
+        try {
+
+            if(variable.property.hasEnumerationRange) {
+                Resource object = variable.getRepresents(graph);
+                if(graph.sync(new IsEnumeratedValue(object))) {
+                    Layer0 L0 = Layer0.getInstance(graph);
+                    if(graph.isInstanceOf(object, L0.Literal)) {
+                        return graph.getValue(object, binding);
+                    } else {
+                        return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
+                    }
+                }
             }
-                       
-               if (variable.isAsserted()) {
-                       if (variable.parentResource != null) {
-                                       Map<String, Pair<PropertyInfo, Resource>> assertions = graph.syncRequest(
-                                                       new UnescapedAssertedPropertyMapOfResource(variable.parentResource),
-                                                       TransientCacheAsyncListener.instance());
-
-                                       // NOTE: This optimization assumes the property
-                                       // variable's representation is the asserted object.
-                                       Resource object = variable.getPossibleRepresents(graph);
-                                       if (object != null) {
-                                               return graph.getValue2(object, variable, binding);
-                                       } else {
-                                               for (Pair<PropertyInfo, Resource> assertion : assertions.values()) {
-                                                       if (assertion.first.predicate.equals(variable.property.predicate)) {
-                                                               return graph.getValue2(assertion.second, variable, binding);
-                                                       }
-                                               }
-                                       }
-                       }
-               }
-                       
-                       return graph.getValue2(variable.getRepresents(graph), context, binding);
-                       
-               } catch (NoSingleResultException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph));
-               } catch (DoesNotContainValueException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph));
-               } catch (DatabaseException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               }
-
-       }
-
-       public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException {
-               
-           if(context instanceof StandardGraphPropertyVariable) {
-
-               final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; 
-               
-               // First from node
+
+            if (variable.isAsserted()) {
+                if (variable.parentResource != null) {
+                    Map<String, Pair<PropertyInfo, Resource>> assertions = graph.syncRequest(
+                            new UnescapedAssertedPropertyMapOfResource(variable.parentResource),
+                            TransientCacheAsyncListener.instance());
+
+                    // NOTE: This optimization assumes the property
+                    // variable's representation is the asserted object.
+                    Resource object = variable.getPossibleRepresents(graph);
+                    if (object != null) {
+                        return graph.getValue2(object, variable, binding);
+                    } else {
+                        for (Pair<PropertyInfo, Resource> assertion : assertions.values()) {
+                            if (assertion.first.predicate.equals(variable.getPossiblePredicateResource(graph))) {
+                                return graph.getValue2(assertion.second, variable, binding);
+                            }
+                        }
+                    }
+                }
+            }
+
+            return graph.getValue2(variable.getRepresents(graph), context, binding);
+
+        } catch (NoSingleResultException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph));
+        } catch (DoesNotContainValueException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph));
+        } catch (DatabaseException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        }
+
+    }
+
+    public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException {
+
+        if(context instanceof StandardGraphPropertyVariable) {
+
+            final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; 
+
+            // First from node
             if(variable.node != null) {
 
                 final Binding binding = Layer0Utils.getDefaultBinding(graph, variable);
@@ -243,8 +248,8 @@ public class All {
                             } catch (NodeManagerException e) {
                                 throw new RuntimeException(e);
                             } catch (BindingException e) {
-                                   throw new RuntimeException(e);
-                               }
+                                throw new RuntimeException(e);
+                            }
                         }
                     });
                 } catch(RuntimeException e) {
@@ -262,31 +267,31 @@ public class All {
 
                 return;
             }
-               
-           }
-           
-               Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
-               if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
-               try {
-                       modifier.apply(graph, context, value, Bindings.getBinding(value.getClass()));
-               } catch (BindingConstructionException e) {
-                       throw new org.simantics.db.exception.BindingException("",e);
-               }
 
-       }
+        }
+
+        Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
+        if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
+        try {
+            modifier.apply(graph, context, value, Bindings.getBinding(value.getClass()));
+        } catch (BindingConstructionException e) {
+            throw new org.simantics.db.exception.BindingException("",e);
+        }
+
+    }
 
-       public static void standardSetValue3(final WriteGraph graph, Variable context, final Object value, final Binding binding) throws DatabaseException {
+    public static void standardSetValue3(final WriteGraph graph, Variable context, final Object value, final Binding binding) throws DatabaseException {
 
         // First from node
         if(context instanceof StandardGraphPropertyVariable) {
 
             final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; 
-            
+
             // First from node
             if(variable.node != null) {
-                
+
                 try {
-                    
+
                     variable.node.support.manager.getRealm().syncExec(new Runnable() {
 
                         @Override
@@ -297,42 +302,42 @@ public class All {
                                 ExternalSetValue ext = new ExternalSetValue(variable.node.support.manager, variable.node.node, oldValue, value, binding);
                                 graph.getService(UndoRedoSupport.class).addExternalOperation(graph, ext);
                             } catch (NodeManagerException | BindingException e) {
-                                Logger.defaultLogError(e);
+                                LOGGER.error("Error setting value", e);
                             }
                         }
 
-                        
+
                     });
-                    
+
                     return;
-                    
+
                 } catch (InterruptedException e) {
                     throw new DatabaseException(e);
                 }
-                
+
             }
-            
+
         }
-           
-               Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
-               if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
-               modifier.apply(graph, context, value, binding);
-
-       }
-
-       public static Datatype getDatatypeFromValue(ReadGraph graph, Variable context) throws DatabaseException {
-               if (context instanceof AbstractVariable) {
-                       Binding defaultBinding = ((AbstractVariable)context).getPossibleDefaultBinding(graph);
-                       if (defaultBinding != null)
-                               return defaultBinding.type();
-               }
-                       
-       Variant value = context.getVariantValue(graph);
-       if (value.getBinding() == null)
-               throw new DatabaseException("No value binding for " + context.getURI(graph));
-       
-       return value.getBinding().type();
-       }
+
+        Function4<WriteGraph, Variable, Object, Object, String> modifier = context.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
+        if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
+        modifier.apply(graph, context, value, binding);
+
+    }
+
+    public static Datatype getDatatypeFromValue(ReadGraph graph, Variable context) throws DatabaseException {
+        if (context instanceof AbstractVariable) {
+            Binding defaultBinding = ((AbstractVariable)context).getPossibleDefaultBinding(graph);
+            if (defaultBinding != null)
+                return defaultBinding.type();
+        }
+
+        Variant value = context.getVariantValue(graph);
+        if (value.getBinding() == null)
+            throw new DatabaseException("No value binding for " + context.getURI(graph));
+
+        return value.getBinding().type();
+    }
 
     @SuppressWarnings("rawtypes")
     private static class DatatypeGetter implements VariableNodeReadRunnable {
@@ -360,25 +365,25 @@ public class All {
     }
 
     public static Datatype standardGetDatatype(ReadGraph graph, Variable context) throws DatabaseException {
-       if (context instanceof AbstractVariable) {
-               final AbstractVariable variable = (AbstractVariable)context;
-               if (variable.node != null) {
-                       try {
-                               DatatypeGetter request = new DatatypeGetter(variable.node);
-                               
-                                       variable.node.support.manager.getRealm().syncExec(request);
-                                       
-                                       if (request.exception != null)
-                                               throw new DatabaseException(request.exception);
-                                       
-                                       return request.type;
-                               } catch (InterruptedException e) {
-                               }
-               }
-       }
-       
-       return getDatatypeFromValue(graph, context);
-       }
+        if (context instanceof AbstractVariable) {
+            final AbstractVariable variable = (AbstractVariable)context;
+            if (variable.node != null) {
+                try {
+                    DatatypeGetter request = new DatatypeGetter(variable.node);
+
+                    variable.node.support.manager.getRealm().syncExec(request);
+
+                    if (request.exception != null)
+                        throw new DatabaseException(request.exception);
+
+                    return request.type;
+                } catch (InterruptedException e) {
+                }
+            }
+        }
+
+        return getDatatypeFromValue(graph, context);
+    }
 
 //     @SCLValue(type = "ValueAccessor")
 //     public static ValueAccessor standardValueAccessor = new ValueAccessor() {
@@ -409,54 +414,54 @@ public class All {
 //             }
 //             
 //     };
-       
-       @SCLValue(type = "ValueAccessor")
-       public static ValueAccessor standardValueAccessor = new ValueAccessor() {
-
-               @Override
-               public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
-                       ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
-                       if(accessor != null) return accessor.getValue(graph, context);
-                       else 
-                               return standardGetValue1(graph, context);
-               }
-
-               @Override
-               public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
-                       ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
-                       if(accessor != null) return accessor.getValue(graph, context, binding);
-                       else 
-                               return standardGetValue2(graph, context, binding);
-               }
-
-               @Override
-               public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
-                       ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
-                       if(accessor != null) accessor.setValue(graph, context, value);
-                       else 
-                               standardSetValue2(graph, context, value);
-               }
-
-               @Override
-               public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
-                       ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
-                       if(accessor != null) accessor.setValue(graph, context, value, binding);
-                       else 
-                               standardSetValue3(graph, context, value, binding);
-               }
-
-               @Override
-               public Datatype getDatatype(ReadGraph graph, Variable context)
-                               throws DatabaseException {
-                       ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
-                       if(accessor != null) return accessor.getDatatype(graph, context);
-                       else 
-                               return standardGetDatatype(graph, context);
-               }
-               
-       };
-
-       public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+
+    @SCLValue(type = "ValueAccessor")
+    public static ValueAccessor standardValueAccessor = new ValueAccessor() {
+
+        @Override
+        public Object getValue(ReadGraph graph, Variable context) throws DatabaseException {
+            ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
+            if(accessor != null) return accessor.getValue(graph, context);
+            else 
+                return standardGetValue1(graph, context);
+        }
+
+        @Override
+        public Object getValue(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
+            ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
+            if(accessor != null) return accessor.getValue(graph, context, binding);
+            else 
+                return standardGetValue2(graph, context, binding);
+        }
+
+        @Override
+        public void setValue(WriteGraph graph, Variable context, Object value) throws DatabaseException {
+            ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
+            if(accessor != null) accessor.setValue(graph, context, value);
+            else 
+                standardSetValue2(graph, context, value);
+        }
+
+        @Override
+        public void setValue(WriteGraph graph, Variable context, Object value, Binding binding) throws DatabaseException {
+            ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
+            if(accessor != null) accessor.setValue(graph, context, value, binding);
+            else 
+                standardSetValue3(graph, context, value, binding);
+        }
+
+        @Override
+        public Datatype getDatatype(ReadGraph graph, Variable context)
+                throws DatabaseException {
+            ValueAccessor accessor = getPossibleValueValueAccessor(graph, context);
+            if(accessor != null) return accessor.getDatatype(graph, context);
+            else 
+                return standardGetDatatype(graph, context);
+        }
+
+    };
+
+    public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
         StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
         PropertyInfo graphProperty = getPossiblePropertyInfoFromContext(graph, variable, variable.resource, name);
         return getStandardChildDomainPropertyVariable(graph, context, graphProperty, name);
@@ -471,7 +476,7 @@ public class All {
         return null;
     }
 
-       public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, PropertyInfo graphProperty, String name) throws DatabaseException {
+    public static Variable getStandardChildDomainPropertyVariable(ReadGraph graph, Variable context, PropertyInfo graphProperty, String name) throws DatabaseException {
         StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
         Object propertyNode = getPossibleNodeProperty(graph, variable, name, true);
         if(graphProperty != null && graphProperty.builder != null)
@@ -511,41 +516,41 @@ public class All {
     }
 
     public static Map<String, Variable> getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-       // Get properties with null identification
+        // Get properties with null identification
         return getStandardChildDomainPropertyVariables(graph, context, null, map);
     }
 
     public static Map<String, Variable> getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
-       
+
         StandardGraphChildVariable variable = (StandardGraphChildVariable)context;
-        
+
         Collection<Object> nodeProperties = getPossibleNodeProperties(graph, variable);
         if(!nodeProperties.isEmpty()) {
 
             // Get variables for properties read from the graph
             Map<String,PropertyInfo> graphProperties = collectPropertyInfosFromContext(graph, variable, variable.resource);
-            
+
             Set<String> used = new THashSet<String>(nodeProperties.size());
-            
+
             map = ensureVariableMap(map, graphProperties.size() + nodeProperties.size());
-            
+
             // Process NodeManager property nodes
             for(Object nodeProperty : nodeProperties) {
-               String name = getNodeName(variable, nodeProperty);
+                String name = getNodeName(variable, nodeProperty);
                 used.add(name);
-                
+
                 PropertyInfo graphProperty = graphProperties.get(name); 
                 if(graphProperty != null && graphProperty.builder != null) {
                     if (classification != null && !graphProperty.hasClassification(classification)) continue;
-                    
+
                     // Combine with identically named graph property
                     map.put(name, buildPropertyVariable(graph, variable, variable.resource, graphProperty, nodeProperty));
                     continue;
                 }
-                
+
                 map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty));
             }
-            
+
             // Process graph properties
             for(PropertyInfo info : graphProperties.values()) {
                 String name = info.name;
@@ -556,249 +561,249 @@ public class All {
                 }
             }
             return map;
-               
+
         } else {
 
-               if(variable.resource == null) return map;
+            if(variable.resource == null) return map;
+
+            // Only graph properties
+            Collection<Resource> predicates = graph.getPredicates(variable.resource);
+            if(predicates.isEmpty()) return map;
+
+            map = ensureVariableMap(map, predicates.size());
 
-               // Only graph properties
-               Collection<Resource> predicates = graph.getPredicates(variable.resource);
-               if(predicates.isEmpty()) return map;
-               
-               map = ensureVariableMap(map, predicates.size());
-               
             // Process graph properties
             for(Resource predicate : predicates) {
-               
-                       PropertyInfo info = //graph.isImmutable(predicate) ?
-                                       graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance());// :
-                                               //graph.syncRequest(new PropertyInfoRequest(predicate));
 
-                       if(!info.isHasProperty) continue;
-                                       
+                PropertyInfo info = //graph.isImmutable(predicate) ?
+                        graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance());// :
+                //graph.syncRequest(new PropertyInfoRequest(predicate));
+
+                if(!info.isHasProperty) continue;
+
                 if (classification != null && !info.hasClassification(classification)) continue;
                 if (info.builder != null) {
                     map.put(info.name, buildPropertyVariable(graph, variable, variable.resource, info, null));
                 }
-                
+
             }
-            
+
             return map;
-               
+
         }
-        
-     }
-       
+
+    }
+
     @SCLValue(type = "VariableMap")
-       public static VariableMap standardChildDomainProperties = new VariableMapImpl() {
-       
-               @Override
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-               return getStandardChildDomainPropertyVariable(graph, context, name);
-               }
-
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-                   return getStandardChildDomainPropertyVariables(graph, context, map);
-               }
-               
-       };
-       
+    public static VariableMap standardChildDomainProperties = new VariableMapImpl() {
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            return getStandardChildDomainPropertyVariable(graph, context, name);
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+            return getStandardChildDomainPropertyVariables(graph, context, map);
+        }
+
+    };
+
     @SCLValue(type = "VariableMap")
-       public static VariableMap methodsPropertyDomainProperties = new VariableMapImpl() {
-       
-               @Override
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-                       Variable parent = context.getParent(graph);
-                       Resource container = parent.getPossibleRepresents(graph);
-                       if(container == null)
-                               return null;
-                       Map<String,Resource> methods = graph.syncRequest(new UnescapedMethodMapOfResource(container));
-                       Resource predicate = methods.get(name);
-                       if(predicate != null) {
-                               Layer0 L0 = Layer0.getInstance(graph);
-                               PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method));
-                               Resource value = graph.getSingleObject(container, predicate);
-                               return new StandardGraphPropertyVariable(context, null, container, info, value);
-                       }
-                       return null;
-               }
-
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-                       Variable parent = context.getParent(graph);
-                       Resource container = parent.getPossibleRepresents(graph);
-                       if(container == null)
-                               return Collections.emptyMap();
-                       Map<String,Resource> methods = graph.syncRequest(new UnescapedMethodMapOfResource(container));
-                       for(Map.Entry<String, Resource> entry : methods.entrySet()) {
-                               String name = entry.getKey();
-                               Resource predicate = entry.getValue();
-                               Layer0 L0 = Layer0.getInstance(graph);
-                               PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method));
-                               Resource value = graph.getSingleObject(container, predicate);
-                               if(map == null) map = new HashMap<>();
-                               map.put(name, new StandardGraphPropertyVariable(context, null, container, info, value));
-                       }
-                       return map;
-               }
-               
-       };
-
-       public static Variable getStandardPropertyDomainPropertyVariableFromValue(ReadGraph graph, Variable context, String name) throws DatabaseException {
-
-               if(context instanceof StandardGraphPropertyVariable) {
-               StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-               Resource literal = variable.getPossibleRepresents(graph);
-               Object propertyNode = getPossibleNodeProperty(graph, variable, name, false);
-
-               if(literal != null) {
-                       Variable result = getPossiblePropertyFromContext(graph, variable, literal, name, propertyNode);
-                       if(result != null) return result;
-               }
-               
-               Variable result = getPossibleSubliteralPropertyFromContext(graph, variable, name);
-               if(result != null) return result;
-               result = getPossiblePropertyFromContext(graph, variable, variable.property.predicate, name, propertyNode);
-               if (result != null) return result;
-               
-               // Get possible property from NodeManager
-               if (propertyNode != null)
-                       return createStandardGraphPropertyVariable(graph, variable, propertyNode);
-               return null;
-               } else if (context instanceof StandardGraphChildVariable) {
-                       return standardChildDomainProperties.getVariable(graph, context, name);
-               } else {
-                       throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
-               }                       
-               
-       }
-       
-       public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-
-               if(context instanceof StandardGraphPropertyVariable) {
-                       StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-                       map = collectPropertiesFromContext(graph, variable, variable.property.predicate, map);
-                       if (variable.parentResource != null) {
-                               Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
-                               if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, map);
-                               map=collectSubliteralProperties(graph, variable, map);
-                       }
-
-                       // Get properties from VariableNode
-                       map = getStandardNodePropertyVariables(graph, context, map);
-                       return map;
-               } else if (context instanceof StandardGraphChildVariable) {
-                       return standardChildDomainProperties.getVariables(graph, context, map);
-               } else {
-                       throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
-               }
-               
-       }
-       
-       public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
-
-               if(context instanceof StandardGraphPropertyVariable) {
-                       StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-                       map = collectPropertiesFromContext(graph, variable, variable.property.predicate, classification, map);
-                       if (variable.parentResource != null) {
-                               Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
-                               if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, classification, map);
-                       }
-                       
-                       // Get properties from VariableNode
-                       map = getStandardNodePropertyVariables(graph, context, map);
-                       return map;
-               } else if (context instanceof StandardGraphChildVariable) {
-                       return standardChildDomainProperties.getVariables(graph, context, map);
-               } else {
-                       throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
-               }       
-               
-       }       
-       
+    public static VariableMap methodsPropertyDomainProperties = new VariableMapImpl() {
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            Variable parent = context.getParent(graph);
+            Resource container = parent.getPossibleRepresents(graph);
+            if(container == null)
+                return null;
+            Map<String,Resource> methods = graph.syncRequest(new UnescapedMethodMapOfResource(container));
+            Resource predicate = methods.get(name);
+            if(predicate != null) {
+                Layer0 L0 = Layer0.getInstance(graph);
+                PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method));
+                Resource value = graph.getSingleObject(container, predicate);
+                return new StandardGraphPropertyVariable(context, null, container, info, value);
+            }
+            return null;
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+            Variable parent = context.getParent(graph);
+            Resource container = parent.getPossibleRepresents(graph);
+            if(container == null)
+                return Collections.emptyMap();
+            Map<String,Resource> methods = graph.syncRequest(new UnescapedMethodMapOfResource(container));
+            for(Map.Entry<String, Resource> entry : methods.entrySet()) {
+                String name = entry.getKey();
+                Resource predicate = entry.getValue();
+                Layer0 L0 = Layer0.getInstance(graph);
+                PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(L0.Entity_method));
+                Resource value = graph.getSingleObject(container, predicate);
+                if(map == null) map = new HashMap<>();
+                map.put(name, new StandardGraphPropertyVariable(context, null, container, info, value));
+            }
+            return map;
+        }
+
+    };
+
+    public static Variable getStandardPropertyDomainPropertyVariableFromValue(ReadGraph graph, Variable context, String name) throws DatabaseException {
+
+        if(context instanceof StandardGraphPropertyVariable) {
+            StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+            Resource literal = variable.getPossibleRepresents(graph);
+            Object propertyNode = getPossibleNodeProperty(graph, variable, name, false);
+
+            if(literal != null) {
+                Variable result = getPossiblePropertyFromContext(graph, variable, literal, name, propertyNode);
+                if(result != null) return result;
+            }
+
+            Variable result = getPossibleSubliteralPropertyFromContext(graph, variable, name);
+            if(result != null) return result;
+            result = getPossiblePropertyFromContext(graph, variable, variable.property.predicate, name, propertyNode);
+            if (result != null) return result;
+
+            // Get possible property from NodeManager
+            if (propertyNode != null)
+                return createStandardGraphPropertyVariable(graph, variable, propertyNode);
+            return null;
+        } else if (context instanceof StandardGraphChildVariable) {
+            return standardChildDomainProperties.getVariable(graph, context, name);
+        } else {
+            throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
+        }                      
+
+    }
+
+    public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+
+        if(context instanceof StandardGraphPropertyVariable) {
+            StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+            map = collectPropertiesFromContext(graph, variable, variable.property.predicate, map);
+            if (variable.parentResource != null) {
+                Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
+                if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, map);
+                map=collectSubliteralProperties(graph, variable, map);
+            }
+
+            // Get properties from VariableNode
+            map = getStandardNodePropertyVariables(graph, context, map);
+            return map;
+        } else if (context instanceof StandardGraphChildVariable) {
+            return standardChildDomainProperties.getVariables(graph, context, map);
+        } else {
+            throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
+        }
+
+    }
+
+    public static Map<String, Variable> getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
+
+        if(context instanceof StandardGraphPropertyVariable) {
+            StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+            map = collectPropertiesFromContext(graph, variable, variable.property.predicate, classification, map);
+            if (variable.parentResource != null) {
+                Resource literal = graph.getPossibleObject(variable.parentResource, variable.property.predicate);
+                if(literal != null) map=collectPropertiesFromContext(graph, variable, literal, classification, map);
+            }
+
+            // Get properties from VariableNode
+            map = getStandardNodePropertyVariables(graph, context, map);
+            return map;
+        } else if (context instanceof StandardGraphChildVariable) {
+            return standardChildDomainProperties.getVariables(graph, context, map);
+        } else {
+            throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
+        }      
+
+    }  
+
     @SCLValue(type = "VariableMap")
-       public static VariableMap standardPropertyDomainProperties = new VariableMapImpl() {
-
-       VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
-               Resource represents = context.getPossibleRepresents(graph);
-               if(represents == null) return null;
-               
-               VariableMap map = graph.isImmutable(represents) ?
-                               graph.syncRequest(new PropertyVariableMapRequest(represents), TransientCacheListener.<VariableMap>instance()) :
-                                       (VariableMap)graph.getPossibleRelatedValue2(represents, Layer0.getInstance(graph).domainProperties, represents);
-               
-               if(map == standardPropertyDomainProperties) return null;
-               else return map;
-               
-       }
-       
-               @Override
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-                       VariableMap valueMap = getValueVariableMap(graph, context);
-                       if(valueMap != null) return valueMap.getVariable(graph, context, name);
-                       return getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
-               }
-
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-                       VariableMap valueMap = getValueVariableMap(graph, context);
-                       if(valueMap != null) return valueMap.getVariables(graph, context, map);
-                       else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, map);
-               }
-               
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
-                       VariableMap valueMap = getValueVariableMap(graph, context);
-                       if(valueMap != null) return valueMap.getVariables(graph, context, classification, map);
-                       else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, classification, map);
-               }
-               
-       };
+    public static VariableMap standardPropertyDomainProperties = new VariableMapImpl() {
+
+        VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
+            Resource represents = context.getPossibleRepresents(graph);
+            if(represents == null) return null;
+
+            VariableMap map = graph.isImmutable(represents) ?
+                    graph.syncRequest(new PropertyVariableMapRequest(represents), TransientCacheListener.<VariableMap>instance()) :
+                        (VariableMap)graph.getPossibleRelatedValue2(represents, Layer0.getInstance(graph).domainProperties, represents);
+
+                    if(map == standardPropertyDomainProperties) return null;
+                    else return map;
+
+        }
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            VariableMap valueMap = getValueVariableMap(graph, context);
+            if(valueMap != null) return valueMap.getVariable(graph, context, name);
+            return getStandardPropertyDomainPropertyVariableFromValue(graph, context, name);
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+            VariableMap valueMap = getValueVariableMap(graph, context);
+            if(valueMap != null) return valueMap.getVariables(graph, context, map);
+            else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, map);
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, String classification, Map<String, Variable> map) throws DatabaseException {
+            VariableMap valueMap = getValueVariableMap(graph, context);
+            if(valueMap != null) return valueMap.getVariables(graph, context, classification, map);
+            else return getStandardPropertyDomainPropertyVariablesFromValue(graph, context, classification, map);
+        }
+
+    };
 
     public static Resource getPossibleGraphChild(ReadGraph graph, Variable variable, String name) throws DatabaseException {
-       Resource resource = variable.getPossibleRepresents(graph);
+        Resource resource = variable.getPossibleRepresents(graph);
         if(resource == null) return null;
         Map<String, Resource> graphChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource));
         return graphChildren.get(name);
     }
 
     public static Map<String,Resource> getPossibleGraphChildren(ReadGraph graph, Variable variable) throws DatabaseException {
-       Resource resource = variable.getPossibleRepresents(graph);
+        Resource resource = variable.getPossibleRepresents(graph);
         if(resource == null) return Collections.emptyMap();
         return graph.syncRequest(new UnescapedChildMapOfResource(resource));
     }
 
     public static Object getPossibleNodeChild(ReadGraph graph, Variable variable, String name) throws DatabaseException {
-       if (!(variable instanceof AbstractVariable)) return null;
-       VariableNode<?> node = ((AbstractVariable)variable).node;
+        if (!(variable instanceof AbstractVariable)) return null;
+        VariableNode<?> node = ((AbstractVariable)variable).node;
         if(node == null) return null;
         NodeStructure structure = Variables.requestNodeStructure(graph, node);
         if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
         return structure.children.get(name);
-       }
-       
+    }
+
     public static Collection<Object> getPossibleNodeChildren(ReadGraph graph, Variable variable) throws DatabaseException {
-       if (!(variable instanceof AbstractVariable)) return null;
-       VariableNode<?> node = ((AbstractVariable)variable).node;
+        if (!(variable instanceof AbstractVariable)) return null;
+        VariableNode<?> node = ((AbstractVariable)variable).node;
         if(node == null) return Collections.emptyList();
         NodeStructure structure = Variables.requestNodeStructure(graph, node);
         if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
         return structure.children.values();
     }
-    
+
     public static Object getPossibleNodeProperty(ReadGraph graph, Variable variable, String name, boolean throwPending) throws DatabaseException {
-       if (!(variable instanceof AbstractVariable)) return null;
-       VariableNode<?> node = ((AbstractVariable)variable).node;
+        if (!(variable instanceof AbstractVariable)) return null;
+        VariableNode<?> node = ((AbstractVariable)variable).node;
         if(node == null) return null;
         NodeStructure structure = Variables.requestNodeStructure(graph, node);
         if(throwPending && Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
         return structure.properties.get(name);
     }
-    
+
     public static Collection<Object> getPossibleNodeProperties(ReadGraph graph, Variable variable) throws DatabaseException {
-       if (!(variable instanceof AbstractVariable)) return null;
-       VariableNode<?> node = ((AbstractVariable)variable).node;
+        if (!(variable instanceof AbstractVariable)) return null;
+        VariableNode<?> node = ((AbstractVariable)variable).node;
         if(node == null) return Collections.emptyList();
         NodeStructure structure = Variables.requestNodeStructure(graph, node);
         if(Variables.PENDING_NODE_STRUCTURE == structure) throw new PendingVariableException("");
@@ -813,24 +818,24 @@ public class All {
 
     @Deprecated
     public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-       return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
+        return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
     }
 
     @Deprecated
     public static Variable getStandardChildDomainChildVariable(ReadGraph graph, Variable context, Resource graphChild, String name) throws DatabaseException {
-       return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, graphChild, name);
+        return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, graphChild, name);
     }
-       
+
     @Deprecated
     public static Map<String, Variable> getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-       return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
+        return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
     }
 
     @Deprecated
     public static Map<String, Variable> getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map<String,Resource> graphChildren, Map<String, Variable> map) throws DatabaseException {
-       return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, graphChildren, map);
+        return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, graphChildren, map);
     }
-    
+
     /**
      * Get a map of child Variables from a node manager-based Variable, combined with the existing variables in #map.
      * @param graph  The read graph.
@@ -840,18 +845,18 @@ public class All {
      * @throws DatabaseException
      */
     public static Map<String, Variable> getStandardNodeChildVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-       AbstractVariable variable = (AbstractVariable)context;
-       if (variable.node == null) return map;
-        
+        AbstractVariable variable = (AbstractVariable)context;
+        if (variable.node == null) return map;
+
         Collection<Object> nodeChildren = getPossibleNodeChildren(graph, variable);
         if (nodeChildren.isEmpty()) return map;
-        
+
         map = ensureVariableMap(map, nodeChildren.size());
 
         for(Object nodeChild : nodeChildren) {
             String name = getNodeName(variable, nodeChild);
             if (!map.containsKey(name))
-               map.put(name, createStandardGraphChildVariable(variable, nodeChild));
+                map.put(name, createStandardGraphChildVariable(variable, nodeChild));
         }
 
         return map;
@@ -866,368 +871,371 @@ public class All {
      * @throws DatabaseException
      */
     public static Map<String, Variable> getStandardNodePropertyVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-       AbstractVariable variable = (AbstractVariable)context;
-       if (variable.node == null) return map;
-        
+        AbstractVariable variable = (AbstractVariable)context;
+        if (variable.node == null) return map;
+
         Collection<Object> nodeProperties = getPossibleNodeProperties(graph, variable);
         if (nodeProperties.isEmpty()) return map;
-        
+
         map = ensureVariableMap(map, nodeProperties.size());
 
         for(Object nodeProperty : nodeProperties) {
             String name = getNodeName(variable, nodeProperty);
             if (!map.containsKey(name)) {
-               map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty));
+                map.put(name, createStandardGraphPropertyVariable(graph, variable, nodeProperty));
             }
         }
 
         return map;
     }    
 
-       @SCLValue(type = "VariableMap")
-       public static VariableMap standardChildDomainChildren = new VariableMapImpl() {
+    @SCLValue(type = "VariableMap")
+    public static VariableMap standardChildDomainChildren = new VariableMapImpl() {
 
-               @Override
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-                       return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
-               }
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            return StandardChildDomainChildren.getStandardChildDomainChildVariable(graph, context, name);
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+            return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
+        }
 
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-                   return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map);
-               }
-               
-       };
+    };
 
     @SCLValue(type = "VariableMap")
-       public static VariableMap standardPropertyDomainChildren = new VariableMapImpl() {
-
-       /**
-        * Get a possible non-standard VariableMap defined in the graph.
-        * @param graph  The graph
-        * @param context  The context node
-        * @return  A non-standard VariableMap instance for the context node,
-        *          or null, if not defined or defined as this instance.
-        * @throws DatabaseException
-        */
-       VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
-               Resource represents = context.getPossibleRepresents(graph);
-               if(represents == null) return null;
-                       VariableMap map = graph.syncRequest(new ChildVariableMapRequest(represents));
-               if(map == standardPropertyDomainChildren) return null;
-               else return map;
-       }
-       
-               @Override
-               public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
-                       // Delegate call to a non-standard variable map?
-                       VariableMap valueMap = getValueVariableMap(graph, context);
-                       if(valueMap != null) return valueMap.getVariable(graph, context, name);
-                       
-                       if(context instanceof StandardGraphPropertyVariable) {
-                               StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-                               Datatype dt = variable.getDatatype(graph);
-                               if (dt instanceof ArrayType) {
-                                       ChildReference ref = getPossibleIndexReference(name);
-                                       if (ref != null)
-                                               return new SubliteralPropertyVariableDeprecated(variable, ref);
-                               }
-                               
-                               // Check for a child node provided by the NodeManager
-                               if (variable.node != null) {
-                                       Object childNode = getPossibleNodeChild(graph, variable, name);
-                                       if (childNode != null)
-                                               return createStandardGraphChildVariable(variable, childNode);
-                               }
-                               return standardChildDomainChildren.getVariable(graph, context, name);
-                       } else if (context instanceof StandardGraphChildVariable) {
-                               return standardChildDomainChildren.getVariable(graph, context, name);
-                       } else {
-                               throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
-                       }
-               }
-
-               @Override
-               public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
-                       // Delegate call to a non-standard variable map?
-                       VariableMap valueMap = getValueVariableMap(graph, context);
-                       if(valueMap != null) return valueMap.getVariables(graph, context, map);
-                       
-                       if(context instanceof StandardGraphPropertyVariable) {
-                               // Get child variables provided by the NodeManager
-                               Map<String, Variable> result = getStandardNodeChildVariables(graph, context, map); 
-                               return standardChildDomainChildren.getVariables(graph, context, result);
-                       } else if (context instanceof StandardGraphChildVariable) {
-                               return standardChildDomainChildren.getVariables(graph, context, map);
-                       } else {
-                               throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
-                       }       
-               }
-               
-       };
-       
-       protected static ChildReference getPossibleIndexReference(String name) {
-               if (name.startsWith("i-")) {
-                   try {
-                       int index = Integer.parseInt(name.substring(2));
-                       return new IndexReference(index);
-                   } catch (NumberFormatException e) {}
-               }
-               return null;
-       }
-
-       protected static ValueAccessor getPossiblePropertyValueAccessor(ReadGraph graph, StandardGraphPropertyVariable variable) throws DatabaseException {
-           if(variable.property == null) return null;
-           return variable.property.valueAccessor;
+    public static VariableMap standardPropertyDomainChildren = new VariableMapImpl() {
+
+        /**
+         * Get a possible non-standard VariableMap defined in the graph.
+         * @param graph  The graph
+         * @param context  The context node
+         * @return  A non-standard VariableMap instance for the context node,
+         *          or null, if not defined or defined as this instance.
+         * @throws DatabaseException
+         */
+        VariableMap getValueVariableMap(ReadGraph graph, Variable context) throws DatabaseException {
+            Resource represents = context.getPossibleRepresents(graph);
+            if(represents == null) return null;
+            VariableMap map = graph.syncRequest(new ChildVariableMapRequest(represents));
+            if(map == standardPropertyDomainChildren) return null;
+            else return map;
+        }
+
+        @Override
+        public Variable getVariable(ReadGraph graph, Variable context, String name) throws DatabaseException {
+            // Delegate call to a non-standard variable map?
+            VariableMap valueMap = getValueVariableMap(graph, context);
+            if(valueMap != null) return valueMap.getVariable(graph, context, name);
+
+            if(context instanceof StandardGraphPropertyVariable) {
+                StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+                Datatype dt = variable.getDatatype(graph);
+                if (dt instanceof ArrayType) {
+                    ChildReference ref = getPossibleIndexReference(name);
+                    if (ref != null)
+                        return new SubliteralPropertyVariableDeprecated(variable, ref);
+                }
+
+                // Check for a child node provided by the NodeManager
+                if (variable.node != null) {
+                    Object childNode = getPossibleNodeChild(graph, variable, name);
+                    if (childNode != null)
+                        return createStandardGraphChildVariable(variable, childNode);
+                }
+                return standardChildDomainChildren.getVariable(graph, context, name);
+            } else if (context instanceof StandardGraphChildVariable) {
+                return standardChildDomainChildren.getVariable(graph, context, name);
+            } else {
+                throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
+            }
+        }
+
+        @Override
+        public Map<String, Variable> getVariables(ReadGraph graph, Variable context, Map<String, Variable> map) throws DatabaseException {
+            // Delegate call to a non-standard variable map?
+            VariableMap valueMap = getValueVariableMap(graph, context);
+            if(valueMap != null) return valueMap.getVariables(graph, context, map);
+
+            if(context instanceof StandardGraphPropertyVariable) {
+                // Get child variables provided by the NodeManager
+                Map<String, Variable> result = getStandardNodeChildVariables(graph, context, map); 
+                return standardChildDomainChildren.getVariables(graph, context, result);
+            } else if (context instanceof StandardGraphChildVariable) {
+                return standardChildDomainChildren.getVariables(graph, context, map);
+            } else {
+                throw new DatabaseException("Unknown variable implementation " + context.getClass().getCanonicalName());
+            }  
+        }
+
+    };
+
+    protected static ChildReference getPossibleIndexReference(String name) {
+        if (name.startsWith("i-")) {
+            try {
+                int index = Integer.parseInt(name.substring(2));
+                return new IndexReference(index);
+            } catch (NumberFormatException e) {}
+        }
+        return null;
+    }
+
+    protected static ValueAccessor getPossiblePropertyValueAccessor(ReadGraph graph, StandardGraphPropertyVariable variable) throws DatabaseException {
+        if(variable.property == null) return null;
+        return variable.property.valueAccessor;
 //        return graph.syncRequest(new PropertyValueAccessorRequest(variable.property), TransientCacheAsyncListener.<ValueAccessor>instance());
 //             return graph.syncRequest(new PossibleRelatedValueImplied2<ValueAccessor>(variable.property, Layer0.getInstance(graph).valueAccessor));
-       }
-
-       public static ValueAccessor getPossibleValueValueAccessor(ReadGraph graph, Variable variable) throws DatabaseException {
-           Resource value = variable.getPossibleRepresents(graph);
-           if(value == null) return null;
-           //return graph.syncRequest(new PropertyValueAccessorRequest(value));
-               return graph.syncRequest(new PossibleRelatedValueImplied2<ValueAccessor>(value, Layer0.getInstance(graph).valueAccessor));      
-       }
-       
-       public static PropertyInfo getPossiblePropertyInfoFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
-           if(context == null) return null;
-               Map<String, PropertyInfo> predicates = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheListener.instance());
-               return predicates.get(name);
-       }
+    }
+
+    public static ValueAccessor getPossibleValueValueAccessor(ReadGraph graph, Variable variable) throws DatabaseException {
+        Resource value = variable.getPossibleRepresents(graph);
+        if(value == null) return null;
+        //return graph.syncRequest(new PropertyValueAccessorRequest(value));
+        return graph.syncRequest(new PossibleRelatedValueImplied2<ValueAccessor>(value, Layer0.getInstance(graph).valueAccessor));     
+    }
+
+    public static PropertyInfo getPossiblePropertyInfoFromContext(ReadGraph graph, Variable variable, Resource context, String name) throws DatabaseException {
+        if(context == null) return null;
+        Map<String, PropertyInfo> predicates = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheListener.instance());
+        return predicates.get(name);
+    }
 
     public static Variable getPossiblePropertyFromContext(ReadGraph graph, Variable variable, Resource context, String name, Object propertyNode) throws DatabaseException {
         PropertyInfo info = getPossiblePropertyInfoFromContext(graph, variable, context, name);
         if(info == null || info.builder == null) return null;
         return buildPropertyVariable(graph, variable, context, info, propertyNode);
     }
-    
+
     public static Variable getPossibleSubliteralPropertyFromContext(ReadGraph graph, StandardGraphPropertyVariable variable, String name) throws DatabaseException {
-       
-               Resource predicate = variable.property.predicate;
-               if(predicate == null) return null;
 
-       PropertyInfo info = getPropertyInfo(graph, predicate);
-       Pair<Resource, ChildReference> p = info.subliteralPredicates.get(name);
-       if(p == null) return null;
-       
-               return new SubliteralPropertyVariable(graph, variable, p.first, p.second);
-       
+        Resource predicate = variable.property.predicate;
+        if(predicate == null) return null;
+
+        PropertyInfo info = getPropertyInfo(graph, predicate);
+        Pair<Resource, ChildReference> p = info.subliteralPredicates.get(name);
+        if(p == null) return null;
+
+        return new SubliteralPropertyVariable(graph, variable, p.first, p.second);
+
     }
 
     public static Map<String, PropertyInfo> collectPropertyInfosFromContext(ReadGraph graph, Variable variable, Resource context) throws DatabaseException {
         if(context == null) return Collections.emptyMap();
-               return graph.isImmutable(context) ?
-                               graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
-                               graph.syncRequest(new UnescapedPropertyMapOfResource(context));
-    }
-
-       public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map<String, Variable> map) throws DatabaseException {
-
-               Map<String,PropertyInfo> properties = graph.isImmutable(context) ?
-                               graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
-                               graph.syncRequest(new UnescapedPropertyMapOfResource(context));
-                               
-               if(properties.isEmpty()) return map;
-               
-               map = ensureVariableMap(map, properties.size());
-               
-               for(PropertyInfo info : properties.values()) {
-                       String name = info.name;
-                       if (info.builder != null) {
-                               Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
-                               map.put(name, v);
-                       }
-               }
-               
-               return map;
-               
-       }
-
-       public static Map<String, Variable> collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map<String, Variable> map) throws DatabaseException {
-
-               Resource predicate = variable.property.predicate;
-               if(predicate == null) return map;
-               
-               PropertyInfo info = getPropertyInfo(graph, predicate);
-               if(info.subliteralPredicates.isEmpty()) return map;
-               
-               map = ensureVariableMap(map, info.subliteralPredicates.size());
-               
-               for(Map.Entry<String, Pair<Resource, ChildReference>> entry : info.subliteralPredicates.entrySet()) {
-                       String key = entry.getKey();
-                       Pair<Resource, ChildReference> p = entry.getValue();
-                       if(map == null) map = new THashMap<String,Variable>();
-                       map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second));
-               }
-       
-       return map;
-               
-       }
-
-       public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map<String, Variable> map) throws DatabaseException {
-
-               if(graph.isImmutable(context)) {
-
-                       Map<String,PropertyInfo> properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
-                       for(PropertyInfo info : properties.values()) {
-
-                               if(info.classifications.contains(classification) && info.builder != null) {
-                                       String name = info.name;
-                                       Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
-                                       if(map == null) map = new THashMap<String,Variable>();
-                                       map.put(name, v);
-                               }
-
-                       }
-
-               } else {
-                               
-                       Collection<Resource> predicates = graph.getPredicates(context);
-                                       
-                       if(predicates.isEmpty()) return map;
-                       
-                       map = ensureVariableMap(map, predicates.size());
-               
-                       for(Resource predicate : predicates) {
-                               
-                               PropertyInfo info = graph.isImmutable(predicate) ?
-                                               graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
-                                                       graph.syncRequest(new PropertyInfoRequest(predicate));
-                                               
-                               if(!info.isHasProperty) continue;
-       
-                               if(info.classifications.contains(classification) && info.builder != null) {
-                                       String name = info.name;
-                                       Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
-                                       if(map == null) map = new THashMap<String,Variable>();
-                                       map.put(name, v);
-                               }
-                               
-                       }
-                       
-               }
-               
-               return map;
-               
-       }       
-       
+        return graph.isImmutable(context) ?
+                graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
+                    graph.syncRequest(new UnescapedPropertyMapOfResource(context));
+    }
+
+    public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map<String, Variable> map) throws DatabaseException {
+
+        Map<String,PropertyInfo> properties = graph.isImmutable(context) ?
+                graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance()) :
+                    graph.syncRequest(new UnescapedPropertyMapOfResource(context));
+
+                if(properties.isEmpty()) return map;
+
+                map = ensureVariableMap(map, properties.size());
+
+                for(PropertyInfo info : properties.values()) {
+                    String name = info.name;
+                    if (info.builder != null) {
+                        Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
+                        map.put(name, v);
+                    }
+                }
+
+                return map;
+
+    }
+
+    public static Map<String, Variable> collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map<String, Variable> map) throws DatabaseException {
+
+        Resource predicate = variable.property.predicate;
+        if(predicate == null) return map;
+
+        PropertyInfo info = getPropertyInfo(graph, predicate);
+        if(info.subliteralPredicates.isEmpty()) return map;
+
+        map = ensureVariableMap(map, info.subliteralPredicates.size());
+
+        for(Map.Entry<String, Pair<Resource, ChildReference>> entry : info.subliteralPredicates.entrySet()) {
+            String key = entry.getKey();
+            Pair<Resource, ChildReference> p = entry.getValue();
+            if(map == null) map = new THashMap<String,Variable>();
+            map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second));
+        }
+
+        return map;
+
+    }
+
+    public static Map<String, Variable> collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map<String, Variable> map) throws DatabaseException {
+
+        if(graph.isImmutable(context)) {
+
+            Map<String,PropertyInfo> properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.<Map<String,PropertyInfo>>instance());
+            for(PropertyInfo info : properties.values()) {
+
+                if(info.classifications.contains(classification) && info.builder != null) {
+                    String name = info.name;
+                    Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
+                    if(map == null) map = new THashMap<String,Variable>();
+                    map.put(name, v);
+                }
+
+            }
+
+        } else {
+
+            Collection<Resource> predicates = graph.getPredicates(context);
+
+            if(predicates.isEmpty()) return map;
+
+            map = ensureVariableMap(map, predicates.size());
+
+            for(Resource predicate : predicates) {
+
+                PropertyInfo info = graph.isImmutable(predicate) ?
+                        graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.<PropertyInfo>instance()) :
+                            graph.syncRequest(new PropertyInfoRequest(predicate));
+
+                        if(!info.isHasProperty) continue;
+
+                        if(info.classifications.contains(classification) && info.builder != null) {
+                            String name = info.name;
+                            Variable v = info.builder.buildProperty(graph, variable, null, context, info.predicate);
+                            if(map == null) map = new THashMap<String,Variable>();
+                            map.put(name, v);
+                        }
+
+            }
+
+        }
+
+        return map;
+
+    }  
+
     @SCLValue(type = "ReadGraph -> Resource -> a -> String")
     public static String entityLabel(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       if(context instanceof Resource) {
-               return NameUtils.getSafeLabel(graph, ((Resource)context));      
-       } else if (context instanceof Variable) {
-               Variable parent = ((Variable)context).getParent(graph);
-               Resource represents = parent.getRepresents(graph);
-               return NameUtils.getSafeLabel(graph, represents);
-       } else {
-               throw new DatabaseException("Unknown context " + context);
-       }
+        if(context instanceof Resource) {
+            return NameUtils.getSafeLabel(graph, ((Resource)context)); 
+        } else if (context instanceof Variable) {
+            Variable parent = ((Variable)context).getParent(graph);
+            Resource represents = parent.getRepresents(graph);
+            return NameUtils.getSafeLabel(graph, represents);
+        } else {
+            throw new DatabaseException("Unknown context " + context);
+        }
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object listResources(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return ListUtils.toList(graph, resource);
+        return ListUtils.toList(graph, resource);
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> [String]")
     public static List<String> standardClassifications(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
-       ArrayList<String> result = new ArrayList<String>();
-       Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph);
-       if(predicate != null) {
-               for(Resource type : graph.getTypes(predicate)) {
-                       String uri = graph.getPossibleURI(type);
-                       if(uri != null) result.add(uri);
-               }
-       }
-       return result;
+        ArrayList<String> result = new ArrayList<String>();
+        Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph);
+        if(predicate != null) {
+            for(Resource type : graph.getTypes(predicate)) {
+                String uri = graph.getPossibleURI(type);
+                if(uri != null) result.add(uri);
+            }
+        }
+        return result;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
     public static Boolean standardValidValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return Boolean.TRUE;
+        return Boolean.TRUE;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> StringInputValidator")
     public static StringInputValidator standardValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return StringInputValidator.PASS;
+        return StringInputValidator.PASS;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
     public static Boolean standardRequiredValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return Boolean.FALSE;
+        return Boolean.FALSE;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean")
     public static Boolean standardDefaultValue(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
-       Variable property = context.getParent(graph);
-       if(property instanceof StandardGraphPropertyVariable) {
-               StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property;
-               if (variable.parentResource != null) {
-                       Statement stm = graph.getPossibleStatement(variable.parentResource, variable.property.predicate);
-                       return stm != null && stm.isAsserted(variable.parentResource);
-                       }
-       }
-       return Boolean.FALSE;
+        Variable property = context.getParent(graph);
+        if(property instanceof StandardGraphPropertyVariable) {
+            StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property;
+            if (variable.parentResource != null) {
+                Resource predicate = variable.getPossiblePredicateResource(graph);
+                if (predicate != null) {
+                    Statement stm = graph.getPossibleStatement(variable.parentResource, predicate);
+                    return stm != null && stm.isAsserted(variable.parentResource);
+                }
+            }
+        }
+        return Boolean.FALSE;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean")
     public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return Boolean.FALSE;
+        return Boolean.FALSE;
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return resource;
+        return resource;
     }
-    
+
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-       return Functions.exec(graph, resource, graph, resource, context);
+        return Functions.exec(graph, resource, graph, resource, context);
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
-       if(context instanceof Variable) {
+        if(context instanceof Variable) {
             return CompileValueRequest.compileAndEvaluate(graph, (Variable)context);
-       } if (context instanceof Resource) {
+        } if (context instanceof Resource) {
             return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter);
-       } else {
-               throw new IllegalStateException("Unknown context " + context);
-       }
+        } else {
+            throw new IllegalStateException("Unknown context " + context);
+        }
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException {
-       if(context instanceof Variable) {
-               return new StandardComposedProperty();
-       } if (context instanceof Resource) {
-               return new StandardComposedProperty();
-       } else {
-               throw new IllegalStateException("Unknown context " + context);
-       }
-    }
-    
+        if(context instanceof Variable) {
+            return new StandardComposedProperty();
+        } if (context instanceof Resource) {
+            return new StandardComposedProperty();
+        } else {
+            throw new IllegalStateException("Unknown context " + context);
+        }
+    }
+
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-        
+
         class Validator extends FunctionImpl1<String, String> {
 
             private final Datatype datatype;
-            
+
             public Validator(Datatype datatype) {
                 this.datatype = datatype;
             }
-            
+
             @Override
             public String apply(String input) {
-                
+
                 if(datatype == null) return null;
-                
+
                 try {
 
                     if(datatype instanceof NumberType) {
-                        
+
                         Number number = (Number)PrimitiveValueParser.parse(input, datatype);
                         NumberType nt = (NumberType)datatype;
                         Range r = nt.getRange();
@@ -1236,129 +1244,130 @@ public class All {
                         }
                     }
                     return null;
-                    
+
                 } catch (NumberFormatException e) {
                     return "Not a valid floating-point number";
                 } catch (IllegalArgumentException e) {
                     return "Not a valid floating-point number";
                 }
-                
+
             }
-            
+
         }
 
         if(context instanceof Variable) {
-            
+
             Variable variable = (Variable)context;
             Variable property = variable.getParent(graph);
             Datatype datatype = property.getPossibleDatatype(graph);
             return new Validator(datatype);
-            
+
         } else if (context instanceof Resource) {
 
             Layer0 L0 = Layer0.getInstance(graph);
             Resource literal = (Resource)context;
             Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class));
             return new Validator(datatype);
-            
+
         } else {
-            
+
             return new Validator(null);
-            
+
         }
-        
+
     }
-    
+
     @SCLValue(type = "ReadGraph -> Resource -> a -> b")
     public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException {
-        
+
         return new FunctionImpl1<String, String>() {
 
             @Override
             public String apply(String input) {
-                
-               String lower = input.toLowerCase();
-               if("true".equals(lower) || "false".equals(lower)) return null;
 
-               return "Not a valid boolean: " + input;
-                
+                String lower = input.toLowerCase();
+                if("true".equals(lower) || "false".equals(lower)) return null;
+
+                return "Not a valid boolean: " + input;
+
             }
-            
+
         };
-        
+
     }
 
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource")
     public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException {
-       Variable parent = context.getParent(graph);
-       if(parent instanceof StandardGraphChildVariable) {
-               StandardGraphChildVariable variable = (StandardGraphChildVariable)parent;
-               return variable.resource;
-       }
-       return null;
+        Variable parent = context.getParent(graph);
+        if(parent instanceof StandardGraphChildVariable) {
+            StandardGraphChildVariable variable = (StandardGraphChildVariable)parent;
+            return variable.resource;
+        }
+        return null;
     }
 
 
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
-       public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
-
-       StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-               
-               if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
-                       Layer0 L0 = Layer0.getInstance(graph);
-                       return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel);
-               }
-
-               if (variable.parentResource == null)
-                       throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").");
-
-               try {
-                       return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable);
-               } catch (NoSingleResultException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               } catch (DoesNotContainValueException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               }
-               
-       }
+    public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
+
+        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+
+        if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
+            Layer0 L0 = Layer0.getInstance(graph);
+            return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel);
+        }
+
+        if (variable.parentResource == null)
+            throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").");
+
+        try {
+            return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable);
+        } catch (NoSingleResultException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        } catch (DoesNotContainValueException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        }
+
+    }
 
     @SCLValue(type = "ReadGraph -> Variable -> Binding -> a")
-       public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
-
-       StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
-               
-               if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
-                       Layer0 L0 = Layer0.getInstance(graph);
-                       return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
-               }
-
-               if (variable.parentResource == null)
-                       throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph));
-
-               try {
-                       return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable);
-               } catch (NoSingleResultException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               } catch (DoesNotContainValueException e) {
-                       throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
-               }
-               
-       }
+    public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException {
+
+        StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context;
+
+        if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) {
+            Layer0 L0 = Layer0.getInstance(graph);
+            return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding);
+        }
+
+        if (variable.parentResource == null)
+            throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph));
+
+
+        try {
+            return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable);
+        } catch (NoSingleResultException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        } catch (DoesNotContainValueException e) {
+            throw new MissingVariableValueException(variable.getPossibleURI(graph), e);
+        }
+
+    }
 
     @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b")
-       public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException {
-               
-               Function4<WriteGraph, Variable, Object, Object, String> modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
-               if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
-               modifier.apply(graph, variable, value, binding);
-               return null;
-               
-       }
-    
+    public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException {
+
+        Function4<WriteGraph, Variable, Object, Object, String> modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER);
+        if(modifier == null) modifier = VariableUtils.defaultInputModifier; 
+        modifier.apply(graph, variable, value, binding);
+        return null;
+
+    }
+
     static class L0Issue extends StandardIssue {
-        
+
         private final String description;
-        
+
         public L0Issue(String description, Resource type, Resource ... contexts) {
             super(type, contexts);
             this.description = description;
@@ -1373,63 +1382,63 @@ public class All {
             graph.addLiteral(issue, L0.HasDescription, L0.HasDescription_Inverse, description, Bindings.STRING);
             return issue;
         }
-        
-    }
-    
-       private static List<Issue> reportInconsistency(ReadGraph graph, Resource subject, String description, List<Issue> issues) throws DatabaseException {
-           if(issues == null) issues = new ArrayList<Issue>();
-               System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description);
-               IssueResource IR = IssueResource.getInstance(graph);
-               issues.add(new L0Issue(description, IR.Issue, subject));
-               return issues;
-       }
-    
+
+    }
+
+    private static List<Issue> reportInconsistency(ReadGraph graph, Resource subject, String description, List<Issue> issues) throws DatabaseException {
+        if(issues == null) issues = new ArrayList<Issue>();
+        System.err.println("Change set validation reports the following issue: " + NameUtils.getSafeName(graph, subject, true) + ": " + description);
+        IssueResource IR = IssueResource.getInstance(graph);
+        issues.add(new L0Issue(description, IR.Issue, subject));
+        return issues;
+    }
+
     @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
     public static List<Issue> relationValidator(ReadGraph graph, Resource resource) throws DatabaseException {
 
-       Layer0 L0 = Layer0.getInstance(graph);
-
-       List<Issue> issues = null;
-       
-       for(Statement stm : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) {
-               Resource predicate = stm.getPredicate();
-               Resource object = stm.getObject();
-               if(!isRelation(graph, L0, predicate)) {
-                       issues = reportInconsistency(graph, resource, "The predicate of a statement must be a relation: " + NameUtils.toString(graph, stm), issues);
-               }
-               if(graph.isInstanceOf(predicate, L0.FunctionalRelation)) {
-                       if(graph.getObjects(resource, predicate).size() > 1)
-                               issues = reportInconsistency(graph, resource, 
-                                               "Relation " +
-                                                               NameUtils.getSafeName(graph, predicate)
-                                                               + " is functional.", issues);
-               }
-               {
-                       Collection<Resource> domain = graph.getObjects(predicate, L0.HasDomain);
-                       if (!isInstanceOfAny(graph, resource, domain, true)) {
-                               StringBuilder sb = new StringBuilder()
-                               .append("The domain of ")
-                               .append(NameUtils.getSafeName(graph, predicate))
-                               .append(" relation is ");
-                               orString(graph, sb, domain).append(".");
-                               issues = reportInconsistency(graph, resource, sb.toString(), issues);
-                       }
-               }
-               {
-                       Collection<Resource> range = graph.getObjects(predicate, L0.HasRange);
-                       if (!isInstanceOfAny(graph, object, range, true) && !graph.isInstanceOf(object, L0.SCLValue)) {
-                               StringBuilder sb = new StringBuilder()
-                               .append("The range of ")
-                               .append(NameUtils.getSafeName(graph, predicate))
-                               .append(" relation is ");
-                               orString(graph, sb, range).append(" but current object is ")
-                               .append(NameUtils.getSafeName(graph, object)).append(".");
-                               issues = reportInconsistency(graph, resource, sb.toString(), issues);
-                       }
-               }               
-       }
-               
-               return issues != null ? issues : Collections.<Issue>emptyList();
+        Layer0 L0 = Layer0.getInstance(graph);
+
+        List<Issue> issues = null;
+
+        for(Statement stm : graph.getStatements(resource, L0.IsWeaklyRelatedTo)) {
+            Resource predicate = stm.getPredicate();
+            Resource object = stm.getObject();
+            if(!isRelation(graph, L0, predicate)) {
+                issues = reportInconsistency(graph, resource, "The predicate of a statement must be a relation: " + NameUtils.toString(graph, stm), issues);
+            }
+            if(graph.isInstanceOf(predicate, L0.FunctionalRelation)) {
+                if(graph.getObjects(resource, predicate).size() > 1)
+                    issues = reportInconsistency(graph, resource, 
+                            "Relation " +
+                                    NameUtils.getSafeName(graph, predicate)
+                            + " is functional.", issues);
+            }
+            {
+                Collection<Resource> domain = graph.getObjects(predicate, L0.HasDomain);
+                if (!isInstanceOfAny(graph, resource, domain, true)) {
+                    StringBuilder sb = new StringBuilder()
+                            .append("The domain of ")
+                            .append(NameUtils.getSafeName(graph, predicate))
+                            .append(" relation is ");
+                    orString(graph, sb, domain).append(".");
+                    issues = reportInconsistency(graph, resource, sb.toString(), issues);
+                }
+            }
+            {
+                Collection<Resource> range = graph.getObjects(predicate, L0.HasRange);
+                if (!isInstanceOfAny(graph, object, range, true) && !graph.isInstanceOf(object, L0.SCLValue)) {
+                    StringBuilder sb = new StringBuilder()
+                            .append("The range of ")
+                            .append(NameUtils.getSafeName(graph, predicate))
+                            .append(" relation is ");
+                    orString(graph, sb, range).append(" but current object is ")
+                    .append(NameUtils.getSafeName(graph, object)).append(".");
+                    issues = reportInconsistency(graph, resource, sb.toString(), issues);
+                }
+            }                  
+        }
+
+        return issues != null ? issues : Collections.<Issue>emptyList();
 
     }
 
@@ -1439,197 +1448,197 @@ public class All {
         List<Issue> issues = null;
 
         Layer0 L0 = Layer0.getInstance(graph);
-       for(Statement stm : graph.getStatements(resource, L0.HasProperty)) {
-               Resource subject = stm.getSubject();
-               Resource predicate = stm.getPredicate();
-               String error = L0Validations.checkValueType(graph, subject, predicate);
-               if(error != null) issues = reportInconsistency(graph, subject, error, issues);
-       }
-               
+        for(Statement stm : graph.getStatements(resource, L0.HasProperty)) {
+            Resource subject = stm.getSubject();
+            Resource predicate = stm.getPredicate();
+            String error = L0Validations.checkValueType(graph, subject, predicate);
+            if(error != null) issues = reportInconsistency(graph, subject, error, issues);
+        }
+
         return issues != null ? issues : Collections.<Issue>emptyList();
 
     }
-    
-    
+
+
     @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
     public static List<Issue> valueValidator(ReadGraph graph, Resource resource) throws DatabaseException {
 
         List<Issue> issues = null;
 
         Layer0 L0 = Layer0.getInstance(graph);
-       if(graph.hasValue(resource)) {
-               if(!graph.isInstanceOf(resource, L0.Literal)) {
-                       issues = reportInconsistency(graph, resource, 
-                                       "Resource has a value but it is not a literal.", issues);
-               }
-               else {
-                       // TODO check that the value is valid for the data type
-               }
-       }
-       else {
-               if(graph.isInstanceOf(resource, L0.Literal)) {
-                       issues = reportInconsistency(graph, resource, 
-                                       "Resource is a literal but it does not have a value.", issues);
-               }
-       }
-       
+        if(graph.hasValue(resource)) {
+            if(!graph.isInstanceOf(resource, L0.Literal)) {
+                issues = reportInconsistency(graph, resource, 
+                        "Resource has a value but it is not a literal.", issues);
+            }
+            else {
+                // TODO check that the value is valid for the data type
+            }
+        }
+        else {
+            if(graph.isInstanceOf(resource, L0.Literal)) {
+                issues = reportInconsistency(graph, resource, 
+                        "Resource is a literal but it does not have a value.", issues);
+            }
+        }
+
         return issues != null ? issues : Collections.<Issue>emptyList();
-       
+
     }
 
-    
+
     @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
     public static List<Issue> uriValidator(ReadGraph graph, Resource resource) throws DatabaseException {
-       
+
         List<Issue> issues = null;
 
         Layer0 L0 = Layer0.getInstance(graph);
         Resource parent = graph.getPossibleObject(resource, L0.PartOf);
-       if(parent != null) {
-           String parentURI = graph.syncRequest(new PossibleURI(parent));
-           if(parentURI != null) {
-                       String name = graph.getPossibleRelatedValue(resource, L0.HasName);
-                       if(name == null) {
-                               issues = reportInconsistency(graph, resource, "Resource has a parent with URI but has no valid HasName.", issues);
-                       }
-           }
-       }
+        if(parent != null) {
+            String parentURI = graph.syncRequest(new PossibleURI(parent));
+            if(parentURI != null) {
+                String name = graph.getPossibleRelatedValue(resource, L0.HasName);
+                if(name == null) {
+                    issues = reportInconsistency(graph, resource, "Resource has a parent with URI but has no valid HasName.", issues);
+                }
+            }
+        }
 
         return issues != null ? issues : Collections.<Issue>emptyList();
-       
+
     }
-    
+
     private static Resource getPossibleNearestClusterSet(ReadGraph graph, Resource base, Resource resource) throws DatabaseException {
 
         ClusteringSupport cs = graph.getService(ClusteringSupport.class);
         if(cs.isClusterSet(resource) && !base.equals(resource)) return resource;
-        
+
         Resource nearest = NearestOwnerFinder.getNearestOwner(graph, resource);
         if(nearest == null) return null;
-        
+
         return getPossibleNearestClusterSet(graph, base, nearest);
 
     }
 
     private static boolean quirks(ReadGraph graph, Resource resource) throws DatabaseException {
 
-       if(!resource.isPersistent()) return true;
-       if(graph.isImmutable(resource)) return true;
-       if(resource.getResourceId() < 0x2000) return true;
+        if(!resource.isPersistent()) return true;
+        if(graph.isImmutable(resource)) return true;
+        if(resource.getResourceId() < 0x2000) return true;
+
+        return false;
 
-       return false;
-       
     }
-    
+
     @SCLValue(type = "ReadGraph -> Resource -> [Issue]")
     public static List<Issue> clusterValidator(ReadGraph graph, Resource resource) throws DatabaseException {
 
-       if(!Development.DEVELOPMENT) return Collections.<Issue>emptyList();
-       
-       if(quirks(graph, resource)) return Collections.<Issue>emptyList();
-       
+        if(!Development.DEVELOPMENT) return Collections.<Issue>emptyList();
+
+        if(quirks(graph, resource)) return Collections.<Issue>emptyList();
+
         List<Issue> issues = null;
 
         ClusteringSupport cs = graph.getService(ClusteringSupport.class);
         Resource set = cs.getClusterSetOfCluster(resource);
-        
+
         if(set == null) return reportInconsistency(graph, resource, "Resource cluster is not part of any cluster set", issues);
-        
+
         Resource nearestSet = getPossibleNearestClusterSet(graph, resource, resource);
         if(nearestSet == null) {
-               // This means that there is no owner since RootLibrary is a cluster set
-               return Collections.<Issue>emptyList();
+            // This means that there is no owner since RootLibrary is a cluster set
+            return Collections.<Issue>emptyList();
         }
-        
+
         if(!set.equals(nearestSet)) return reportInconsistency(graph, resource, "The cluster set of a resource is not the nearest owner set", issues);
 
         return Collections.<Issue>emptyList();
-       
+
     }
 
     private static boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection<Resource> types, boolean ifEmpty) throws DatabaseException {
-               if (types.isEmpty())
-                       return ifEmpty;
-               for (Resource type : types) {
-                       if (graph.isInstanceOf(r, type)) {
-                               return true;
-                       }
-               }
-               return false;
-       }
-
-       private static StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection<Resource> rs) throws DatabaseException {
-               sb.append("(");
-               boolean first = true;
-               for (Resource r : rs) {
-                       if (!first)
-                               sb.append(" | ");
-                       first = false;
-                       sb.append(NameUtils.getSafeName(graph, r));
-               }
-               sb.append(")");
-               return sb;
-       }
+        if (types.isEmpty())
+            return ifEmpty;
+        for (Resource type : types) {
+            if (graph.isInstanceOf(r, type)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static StringBuilder orString(ReadGraph graph, StringBuilder sb, Collection<Resource> rs) throws DatabaseException {
+        sb.append("(");
+        boolean first = true;
+        for (Resource r : rs) {
+            if (!first)
+                sb.append(" | ");
+            first = false;
+            sb.append(NameUtils.getSafeName(graph, r));
+        }
+        sb.append(")");
+        return sb;
+    }
 
     public static boolean isRelation(ReadGraph g, Layer0 l0, Resource relation) throws DatabaseException {
-               return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo;
-       }
-       
-       public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException {
-               return g.hasStatement(type, l0.Inherits) || type == l0.Entity;
-       }
-       
+        return g.hasStatement(relation, l0.SubrelationOf) || relation == l0.IsWeaklyRelatedTo;
+    }
+
+    public static boolean isType(ReadGraph g, Layer0 l0, Resource type) throws DatabaseException {
+        return g.hasStatement(type, l0.Inherits) || type == l0.Entity;
+    }
+
     public static Variable buildChildVariable(ReadGraph graph, Variable context, Resource graphChild, Object nodeChild) throws DatabaseException {
         VariableBuilder builder = graph.adapt(graphChild, VariableBuilder.class);
-       return builder.buildChild(graph, context, build(((AbstractVariable)context).node, nodeChild), graphChild);
-       }
-
-       private static Variable buildPropertyVariable(ReadGraph graph, Variable variable, Resource parentResource, PropertyInfo graphProperty, Object propertyNode) throws DatabaseException {
-               VariableNode<?> node = variable instanceof AbstractVariable ? build(((AbstractVariable)variable).node, propertyNode) : null;
-               return graphProperty.builder.buildProperty(graph, variable, node, parentResource, graphProperty.predicate);
-       }
-       
-       static StandardGraphChildVariable createStandardGraphChildVariable(
-                       AbstractVariable parent, Object child) {
-               return new StandardGraphChildVariable(parent, build(parent.node, child), null);
-       }
-
-       private static StandardGraphPropertyVariable createStandardGraphPropertyVariable(
-                       ReadGraph graph, AbstractVariable variable, Object nodeProperty) throws DatabaseException {
+        return builder.buildChild(graph, context, build(((AbstractVariable)context).node, nodeChild), graphChild);
+    }
+
+    private static Variable buildPropertyVariable(ReadGraph graph, Variable variable, Resource parentResource, PropertyInfo graphProperty, Object propertyNode) throws DatabaseException {
+        VariableNode<?> node = variable instanceof AbstractVariable ? build(((AbstractVariable)variable).node, propertyNode) : null;
+        return graphProperty.builder.buildProperty(graph, variable, node, parentResource, graphProperty.predicate);
+    }
+
+    static StandardGraphChildVariable createStandardGraphChildVariable(
+            AbstractVariable parent, Object child) {
+        return new StandardGraphChildVariable(parent, build(parent.node, child), null);
+    }
+
+    private static StandardGraphPropertyVariable createStandardGraphPropertyVariable(
+            ReadGraph graph, AbstractVariable variable, Object nodeProperty) throws DatabaseException {
         Resource propertyResource = getPossiblePropertyResource(graph, variable, nodeProperty);
         return new StandardGraphPropertyVariable(graph, variable, build(variable.node, nodeProperty), null, propertyResource);
-       }
-        
-       static Map<String, Variable> ensureVariableMap(
-                       Map<String, Variable> map, int size) {
-               if(map == null) map = new THashMap<String,Variable>(size);
-               return map;
-       }
-
-       private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource predicate) throws DatabaseException {
-               return graph.syncRequest(new PropertyInfoRequest(predicate));
-       }
-
-       @SuppressWarnings("unchecked")
-       static String getNodeName(AbstractVariable parent, Object child) {
-               return parent.node.support.manager.getName(child);
-       }
-
-       @SuppressWarnings("unchecked")
-       private static Object getNodeValue(final AbstractVariable variable, final Binding binding) throws NodeManagerException, BindingException {
-               return variable.node.support.manager.getValue(variable.node.node, binding);
-       }
-
-       @SuppressWarnings("unchecked")
-       private static void setNodeValue(final AbstractVariable variable, final Object value, final Binding binding) throws NodeManagerException, BindingException {
-               variable.node.support.manager.setValue(variable.node.node, value, binding);
-       }
-       
-       @SuppressWarnings("unchecked")
-       private static String getPossiblePropertyURI(AbstractVariable parent, Object node) {
-               return parent.node.support.manager.getPropertyURI(parent.node.node, node);
-       }
-    
+    }
+
+    static Map<String, Variable> ensureVariableMap(
+            Map<String, Variable> map, int size) {
+        if(map == null) map = new THashMap<String,Variable>(size);
+        return map;
+    }
+
+    private static PropertyInfo getPropertyInfo(ReadGraph graph, Resource predicate) throws DatabaseException {
+        return graph.syncRequest(new PropertyInfoRequest(predicate));
+    }
+
+    @SuppressWarnings("unchecked")
+    static String getNodeName(AbstractVariable parent, Object child) {
+        return parent.node.support.manager.getName(child);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static Object getNodeValue(final AbstractVariable variable, final Binding binding) throws NodeManagerException, BindingException {
+        return variable.node.support.manager.getValue(variable.node.node, binding);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static void setNodeValue(final AbstractVariable variable, final Object value, final Binding binding) throws NodeManagerException, BindingException {
+        variable.node.support.manager.setValue(variable.node.node, value, binding);
+    }
+
+    @SuppressWarnings("unchecked")
+    private static String getPossiblePropertyURI(AbstractVariable parent, Object node) {
+        return parent.node.support.manager.getPropertyURI(parent.node.node, node);
+    }
+
 
     @SCLValue(type = "ReadGraph -> Resource -> Variable -> a")
     public static Object defaultInstantiateUnder(ReadGraph graph, Resource converter, Variable context) throws DatabaseException {
index 0aa36390b6030ed4068ed99ed9c5160640feeb73..83837a960a6950888baf3180b664be0fadfb4fbb 100644 (file)
@@ -13,13 +13,14 @@ package org.simantics.db.layer0.genericrelation;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
-import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.GenericRelationIndex;
 import org.simantics.db.service.QueryControl;
 import org.simantics.operation.Layer0X;
 import org.simantics.scl.runtime.function.FunctionImpl4;
 import org.simantics.scl.runtime.function.UnsaturatedFunction2;
+import org.slf4j.LoggerFactory;
 
 /**
  * dependencies:
@@ -30,6 +31,8 @@ import org.simantics.scl.runtime.function.UnsaturatedFunction2;
  */
 public class Dependencies extends FunctionImpl4<ReadGraph, Resource, String, Integer, Object> {
 
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Dependencies.class);
+
     public static final String FIELD_MODEL    = "Model";
     public static final String FIELD_PARENT   = "Parent";
     public static final String FIELD_RESOURCE = "Resource";
@@ -71,10 +74,15 @@ public class Dependencies extends FunctionImpl4<ReadGraph, Resource, String, Int
             final int maxResults = _maxResults != null ? _maxResults : Integer.MAX_VALUE;
             
             QueryControl qc = graph.getService(QueryControl.class);
-            return index.query(qc.getIndependentGraph(graph), query, getBindingPattern(), new Object[] { model }, maxResults);
+            return qc.syncRequestIndependent(graph, new UniqueRead<Object>() {
+                @Override
+                public Object perform(ReadGraph graph) throws DatabaseException {
+                    return index.query(graph, query, getBindingPattern(), new Object[] { model }, maxResults);
+                }
+            });
             
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("Error while performing index query", e);
             return null;
         }
     }
index 1702af0f38e6182832673997ab7b55588ae5f335..a2059a6ad27264b02381a3b4400d18f7ed5a5401 100644 (file)
@@ -13,13 +13,14 @@ package org.simantics.db.layer0.genericrelation;
 
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
-import org.simantics.db.common.utils.Logger;
+import org.simantics.db.common.request.UniqueRead;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.adapter.GenericRelationIndex;
 import org.simantics.db.service.QueryControl;
 import org.simantics.operation.Layer0X;
 import org.simantics.scl.runtime.function.FunctionImpl4;
 import org.simantics.scl.runtime.function.UnsaturatedFunction2;
+import org.slf4j.LoggerFactory;
 
 /**
  * dependencyResources:
@@ -30,6 +31,8 @@ import org.simantics.scl.runtime.function.UnsaturatedFunction2;
  */
 public class DependencyResources extends FunctionImpl4<ReadGraph, Resource, String, Integer, Object> {
 
+    private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DependencyResources.class);
+
     protected Resource getIndexRelation(ReadGraph graph) {
         return Layer0X.getInstance(graph).DependenciesRelation;
     }
@@ -61,10 +64,15 @@ public class DependencyResources extends FunctionImpl4<ReadGraph, Resource, Stri
             final int maxResults = _maxResults != null ? _maxResults : Integer.MAX_VALUE;
             
             QueryControl qc = graph.getService(QueryControl.class);
-            return index.queryResources(qc.getIndependentGraph(graph), query, getBindingPattern(), new Object[] { model }, maxResults);
+            return qc.syncRequestIndependent(graph, new UniqueRead<Object>() {
+                @Override
+                public Object perform(ReadGraph graph) throws DatabaseException {
+                    return index.queryResources(graph, query, getBindingPattern(), new Object[] { model }, maxResults);
+                }
+            });
             
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("Error while performing index query", e);
             return null;
         }
     }
diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java
new file mode 100644 (file)
index 0000000..a1b7463
--- /dev/null
@@ -0,0 +1,34 @@
+package org.simantics.db.layer0.variable;
+
+import org.simantics.db.Resource;
+import org.simantics.db.exception.AssumptionException;
+
+public class NoPredicateResourceException extends AssumptionException {
+
+       private static final long serialVersionUID = -374051341908276908L;
+
+       public NoPredicateResourceException(Throwable cause) {
+               super(cause);
+       }
+
+       public NoPredicateResourceException(String message, Throwable cause, Resource... rs) {
+               super(message, cause, rs);
+       }
+
+       public NoPredicateResourceException(String message, Resource... resources) {
+               super(message, resources);
+       }
+
+       public NoPredicateResourceException(String message, Throwable cause) {
+               super(message, cause);
+       }
+
+       public NoPredicateResourceException(String message, int... args) {
+               super(message, args);
+       }
+
+       public NoPredicateResourceException(String message) {
+               super(message);
+       }
+
+}
index 2bd089d1e8ed1589ecadb76f6f18662169b405ef..140ee8fa0841648805803c027686ac2b6efb2441 100644 (file)
@@ -6,44 +6,48 @@ import org.simantics.databoard.binding.mutable.Variant;
 import org.simantics.databoard.util.ObjectUtils;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.common.request.ParametrizedPrimitiveRead;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.procedure.Listener;
+import org.simantics.simulator.variable.NodeManager;
 import org.simantics.simulator.variable.exceptions.NodeIsNotValidAnymoreException;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @SuppressWarnings("rawtypes")
 class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Binding>, Variant> implements VariableNodeReadRunnable {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(NodeValueRequest.class);
+
     private Listener<Variant> listener = null;
     private Variant value = Variables.PENDING_NODE_VALUE;
     private boolean wasRun = false;
 
     static class Probe implements Runnable {
 
-       private Pair<VariableNode,Binding> parameter;
-               public Variant result;
-       
-       public Probe(Pair<VariableNode,Binding> parameter) {
-               this.parameter = parameter;
-       }
-       
-               @SuppressWarnings("unchecked")
-               @Override
-               public void run() {
-                       try {
-                               result = NodeValueRequest.get(parameter);
-                               parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L);
-                       } catch (NodeManagerException e) {
-                               e.printStackTrace();
-                       } catch (BindingException e) {
-                               e.printStackTrace();
-                       }
-               }
-       
+        private Pair<VariableNode,Binding> parameter;
+        public Variant result;
+
+        public Probe(Pair<VariableNode,Binding> parameter) {
+            this.parameter = parameter;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public void run() {
+            try {
+                result = NodeValueRequest.get(parameter);
+                parameter.first.support.valueCache.put(parameter.first.node, result, 1000000000L);
+            } catch (NodeManagerException e) {
+                e.printStackTrace();
+            } catch (BindingException e) {
+                e.printStackTrace();
+            }
+        }
+
     }
-    
+
     public NodeValueRequest(VariableNode node) {
         super(Pair.<VariableNode, Binding>make(node, null));
     }
@@ -55,18 +59,18 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
     @SuppressWarnings("unchecked")
     @Override
     public void register(ReadGraph graph, final Listener<Variant> procedure) {
-       
-       VariableNode node = parameter.first;
+
+        VariableNode node = parameter.first;
 
         if(procedure.isDisposed()) {
-               
-               // We are not listening
-               Variant result = (Variant)node.support.valueCache.get(node.node);
 
-               if(result != null) {
-                       // Return cached value immediately
-                       procedure.execute(result);
-               } else {
+            // We are not listening
+            Variant result = (Variant)node.support.valueCache.get(node.node);
+
+            if(result != null) {
+                // Return cached value immediately
+                procedure.execute(result);
+            } else {
 
 //             
 //            listener = procedure;
@@ -87,37 +91,37 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
 //                }
 //            }
 //            return;
-            
-                       NodeValueRequest.Probe probe = new Probe(parameter);
-                       node.support.manager.getRealm().asyncExec(probe);
-                       if(probe.result != null) {
-                               procedure.execute(probe.result);
-                       } else {
-                               procedure.execute(Variables.PENDING_NODE_VALUE);
-                       }
-
-               }
-
-               return;            
+
+                NodeValueRequest.Probe probe = new Probe(parameter);
+                node.support.manager.getRealm().asyncExec(probe);
+                if(probe.result != null) {
+                    procedure.execute(probe.result);
+                } else {
+                    procedure.execute(Variables.PENDING_NODE_VALUE);
+                }
+
+            }
+
+            return;            
         }
-        
-       // We need to listen
+
+        // We need to listen
         listener = procedure;
-               // Register listening
-               node.support.manager.addNodeListener(node.node, this);
-               synchronized(this) {
-                       if(wasRun) {
-                               procedure.execute(value);
-                       } else {
-                               Variant result = (Variant)node.support.valueCache.get(node.node);
-                               if(result != null) {
-                                       procedure.execute(result);
-                               } else {
-                       procedure.execute(Variables.PENDING_NODE_VALUE);
-                               }
-                       }
-               }
-        
+        // Register listening
+        node.support.manager.addNodeListener(node.node, this);
+        synchronized(this) {
+            if(wasRun) {
+                procedure.execute(value);
+            } else {
+                Variant result = (Variant)node.support.valueCache.get(node.node);
+                if(result != null) {
+                    procedure.execute(result);
+                } else {
+                    procedure.execute(Variables.PENDING_NODE_VALUE);
+                }
+            }
+        }
+
 //        if(listener != null) {
 //            throw new UnsupportedOperationException();
 //        }
@@ -145,61 +149,64 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
 //            parameter.support.manager.addNodeListener(parameter.node, this);
 //            if(value == Variables.PENDING_NODE_VALUE) procedure.execute(Variables.PENDING_NODE_VALUE);
 //        }
-               
+
     }
-    
+
     static class NodeListener implements VariableNodeReadRunnable {
-       
-       private VariableNode node;
-       private NodeValueRequest request;
-       
-       public NodeListener(VariableNode node, NodeValueRequest request) {
-               this.node = node;
-               this.request = request;
-       }
-
-       @SuppressWarnings("unchecked")
-       @Override
-       public void run() {
+
+        private VariableNode node;
+        private NodeValueRequest request;
+
+        public NodeListener(VariableNode node, NodeValueRequest request) {
+            this.node = node;
+            this.request = request;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public void run() {
             node.support.manager.addNodeListener(node.node, request);
-       }
-       
+        }
+
     }
 
 
     @SuppressWarnings("unchecked")
     @Override
     public void unregistered() {
-       VariableNode node = parameter.first;
-       node.support.manager.removeNodeListener(node.node, this);
+        VariableNode node = parameter.first;
+        node.support.manager.removeNodeListener(node.node, this);
         node.support.valueCache.removeListening(node.node);
         listener = null;
     }
-    
+
     @SuppressWarnings("unchecked")
     public static Variant get(Pair<VariableNode,Binding> parameter) throws NodeManagerException, BindingException {
 
-       VariableNode node = parameter.first;
-       Binding binding = parameter.second;
-       
-       if (binding != null) {
-               Object raw = node.support.manager.getValue(node.node, binding);
-               if(raw == null) return null;
-               else return new Variant(binding, raw);
-       } else {
-               return node.support.manager.getValue(node.node);
-       }
-       
+        VariableNode node = parameter.first;
+        Binding binding = parameter.second;
+
+        if (binding != null) {
+            Object raw = node.support.manager.getValue(node.node, binding);
+            if(raw == null)
+                return null;
+            else if(NodeManager.PENDING_NODE_VALUE == raw)
+                return NodeManager.PENDING_NODE_VALUE;
+            else return new Variant(binding, raw);
+        } else {
+            return node.support.manager.getValue(node.node);
+        }
+
     }
-    
+
     @SuppressWarnings("unchecked")
     @Override
     public synchronized void run() {
-       
-       VariableNode node = parameter.first;
-       
+
+        VariableNode node = parameter.first;
+
         try {
-               Variant newValue = get(parameter);
+            Variant newValue = get(parameter);
             if (wasRun && ObjectUtils.objectEquals(value, newValue)) {
                 //System.out.println("CACHE VALUE MATCH (" + newValue + ") for " + node.node);
                 return;
@@ -209,7 +216,7 @@ class NodeValueRequest extends ParametrizedPrimitiveRead<Pair<VariableNode,Bindi
         } catch (Throwable e) {
             // Must catch everything to prevent DB client from getting stuck.
             if(!(e instanceof NodeIsNotValidAnymoreException))
-               Logger.defaultLogError(e);
+                LOGGER.error("Error while computing node value", e);
             // Invoke the exception method of the listener
             Listener<Variant> listener = this.listener;
             if (listener != null) listener.exception(new DatabaseException("External data access error", e));
index b7eaf075edea1c1e051981662954629f70673cf1..c9214e398c69577da69642536c8b932e67e5bc69 100644 (file)
@@ -21,6 +21,7 @@ import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.DatatypeNotFoundException;
 import org.simantics.db.exception.ValidationException;
 import org.simantics.db.layer0.exception.InvalidVariableException;
+import org.simantics.db.layer0.exception.MissingVariableException;
 import org.simantics.db.layer0.exception.MissingVariableValueException;
 import org.simantics.db.layer0.exception.PendingVariableException;
 import org.simantics.db.layer0.function.All;
@@ -100,11 +101,15 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
 
        @Override
        public String getPossibleLabel(ReadGraph graph) throws DatabaseException {
+               if (property.predicate == null)
+                       return null;
                return graph.getPossibleRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
        }
 
        @Override
        public String getLabel(ReadGraph graph) throws DatabaseException {
+               if (property.predicate == null)
+                       throw new NoPredicateResourceException("No predicate resource for property " + getName(graph));
                return graph.getRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING);
        }
 
@@ -124,10 +129,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
                
                if(Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
-                               String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
-                               if(error != null) {
-                                   LOGGER.error(error);
-                                       throw new ValidationException(error);
+                               if (property.predicate != null) {
+                                       String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
+                                       if(error != null) {
+                                           LOGGER.error(error);
+                                               throw new ValidationException(error);
+                                       }
                                }
                        }
                }
@@ -145,10 +152,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
 
                if(Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
-                               String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
-                               if(error != null) {
-                                       LOGGER.error(error);
-                                       throw new ValidationException(error);
+                               if (property.predicate != null) {
+                                       String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
+                                       if(error != null) {
+                                               LOGGER.error(error);
+                                               throw new ValidationException(error);
+                                       }
                                }
                        }
                }
@@ -183,10 +192,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
                
                if(Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
-                               String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
-                               if(error != null) {
-                                       LOGGER.error(error);
-                                       throw new ValidationException(error);
+                               if (property.predicate != null) {
+                                       String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
+                                       if(error != null) {
+                                               LOGGER.error(error);
+                                               throw new ValidationException(error);
+                                       }
                                }
                        }
                }
@@ -200,10 +211,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
                
                if(Development.DEVELOPMENT) {
                        if(Development.<Boolean>getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) {
-                               String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
-                               if(error != null) {
-                                       LOGGER.error(error);
-                                       throw new ValidationException(error);
+                               if (property.predicate != null) {
+                                       String error = L0Validations.checkValueType(graph, parentResource, property.predicate);
+                                       if(error != null) {
+                                               LOGGER.error(error);
+                                               throw new ValidationException(error);
+                                       }
                                }
                        }
                }
@@ -324,11 +337,15 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable {
        
        @Override
        public Variable getPredicate(ReadGraph graph) throws DatabaseException {
+               if (property.predicate == null)
+                       throw new MissingVariableException("No predicate for property " + getName(graph));
                return Variables.getVariable(graph, graph.getURI(property.predicate));
        }
        
        @Override
        public Resource getPredicateResource(ReadGraph graph) throws DatabaseException {
+               if (property.predicate == null)
+                       throw new NoPredicateResourceException("No predicate for property " + getName(graph));
                return property.predicate;
        }
        
index 341a496a4ff2778a3e9972cb2c0c998dbe9f6114..218a268a464097916f666d44cf3c20f91115a166 100644 (file)
@@ -32,7 +32,6 @@ import org.simantics.db.WriteGraph;
 import org.simantics.db.common.request.PossibleIndexRoot;
 import org.simantics.db.common.request.TernaryRead;
 import org.simantics.db.common.utils.CommonDBUtils;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.exception.InvalidVariableException;
 import org.simantics.db.layer0.exception.MissingVariableException;
@@ -53,14 +52,19 @@ import org.simantics.scl.runtime.function.Function1;
 import org.simantics.scl.runtime.function.Function2;
 import org.simantics.scl.runtime.function.Function3;
 import org.simantics.simulation.ontology.SimulationResource;
+import org.simantics.simulator.variable.NodeManager;
 import org.simantics.simulator.variable.exceptions.NodeManagerException;
 import org.simantics.utils.datastructures.Pair;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import gnu.trove.map.hash.TObjectIntHashMap;
 
 final public class Variables {
 
-    public static final Variant PENDING_NODE_VALUE = new Variant();
+    private static final Logger LOGGER = LoggerFactory.getLogger(Variables.class);
+
+    public static final Variant PENDING_NODE_VALUE = NodeManager.PENDING_NODE_VALUE;
 
     public static final NodeStructure PENDING_NODE_STRUCTURE = new NodeStructure(Collections.emptyMap(), Collections.emptyMap()) {
         public boolean equals(Object object) {
@@ -154,8 +158,8 @@ final public class Variables {
 
     @Deprecated
     public final static String[] builtins = {
-        TYPE, RESOURCE, URI
-        //, SERIALISED
+            TYPE, RESOURCE, URI
+            //, SERIALISED
     };
 
     public static Variable getPossibleVariable(ReadGraph graph, Resource resource) throws DatabaseException {
@@ -309,15 +313,15 @@ final public class Variables {
     public static Variable getRootVariable(ReadGraph graph) throws DatabaseException {
         return graph.adapt(graph.getRootLibrary(), Variable.class);
     }
-    
+
     public static Resource getPossibleIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
-       return graph.syncRequest(new PossibleVariableIndexRoot(variable));
+        return graph.syncRequest(new PossibleVariableIndexRoot(variable));
     }
-    
+
     public static Resource getIndexRoot(ReadGraph graph, Variable variable) throws DatabaseException {
-       return graph.syncRequest(new VariableIndexRoot(variable));
+        return graph.syncRequest(new VariableIndexRoot(variable));
     }
-    
+
     public static Resource getModel(ReadGraph graph, Variable variable) throws DatabaseException {
         String URI = variable.getURI(graph);
         return VariablesImpl.getFirst(graph, SimulationResource.getInstance(graph).Model, URI, 8);
@@ -382,7 +386,7 @@ final public class Variables {
         Variable context = getConfigurationContext(graph, resource);
         return context.browse(graph, RVI);
     }
-    
+
     public static Variable getConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
         Variable context = getConfigurationContext(graph, variable);
         RVI rvi = variable.getRVI(graph);
@@ -546,12 +550,12 @@ final public class Variables {
     }
 
     public static Variable toPossibleConfigurationVariable(ReadGraph graph, Variable variable) throws DatabaseException {
-       
+
         Resource represents = variable.getPossibleRepresents(graph);
         if(represents == null) return null;
         Resource config = getPossibleConfigurationContextResource(graph, represents);
         if(config == null) return null;
-       return switchPossibleContext(graph, variable, config);
+        return switchPossibleContext(graph, variable, config);
 
     }
 
@@ -641,25 +645,26 @@ final public class Variables {
     }
 
     public static Variant requestNodeValue(ReadGraph graph, VariableNode<?> node, final Binding binding) throws DatabaseException {
-       Variant value = graph.syncRequest(new NodeValueRequest(node, binding));
-       if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {
-               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
-               
-                       ValueGetter getter = new ValueGetter(node, binding);
-                       try {
-                               node.support.manager.getRealm().syncExec(getter);
-                       } catch (InterruptedException e) {
-                               Logger.defaultLogError(e);
-                       }
-                       
-                       if (getter.exception != null)
-                               throw new MissingVariableValueException("No value for node " + node, getter.exception);
-                       
-                       return getter.result;
-       }
+        Variant value = graph.syncRequest(new NodeValueRequest(node, binding));
+        if(PENDING_NODE_VALUE == value && graph.getSynchronous()) {
+            // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
+
+            ValueGetter getter = new ValueGetter(node, binding);
+            try {
+                node.support.manager.getRealm().syncExec(getter);
+            } catch (InterruptedException e) {
+                LOGGER.error("Error while getting node value", e);
+                throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
+            }
+
+            if (getter.exception != null)
+                throw new MissingVariableValueException("No value for node " + node, getter.exception);
+
+            return getter.result;
+        }
         return value; 
     }
-    
+
     public static class NodeStructure {
         // Immutable but wrapped with Collections.unmodifiableMap as an optimization
         public final Map<String,Object> children;
@@ -699,51 +704,51 @@ final public class Variables {
         NodeStructure value = graph.syncRequest(new NodeStructureRequest(node));
         if (value == null)
             throw new InvalidVariableException("External data access error " + String.valueOf(node));
-       if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {
-               // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
-               
-                       StructureGetter getter = new StructureGetter(node);
-                       try {
-                               node.support.manager.getRealm().syncExec(getter);
-                       } catch (InterruptedException e) {
-                               Logger.defaultLogError(e);
-                               throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
-                       }
-                       
-                       if (getter.exception != null)
-                               throw new InvalidVariableException("External data access error " + String.valueOf(node), getter.exception);
-                       if (getter.result == null)
-                               throw new InvalidVariableException("External data access error " + String.valueOf(node));
-                       
-                       return getter.result;
-               
-       }
+        if(PENDING_NODE_STRUCTURE == value && graph.getSynchronous()) {
+            // In this case a PENDING value was previously cached but now the value needs to be obtained for real.
+
+            StructureGetter getter = new StructureGetter(node);
+            try {
+                node.support.manager.getRealm().syncExec(getter);
+            } catch (InterruptedException e) {
+                LOGGER.error("Error while getting node structure", e);
+                throw new InvalidVariableException("External data access error " + String.valueOf(node), e);
+            }
+
+            if (getter.exception != null)
+                throw new InvalidVariableException("External data access error " + String.valueOf(node), getter.exception);
+            if (getter.result == null)
+                throw new InvalidVariableException("External data access error " + String.valueOf(node));
+
+            return getter.result;
+
+        }
         return value; 
 
     }
-    
+
     public static String getPossibleUnit(ReadGraph graph, Variable variable) throws DatabaseException {
-       
-       try {
-               
-               Resource predicate = variable.getPossiblePredicateResource(graph);
-               if(predicate != null) {
-                       PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
-                       if(info.definedUnit != null) return info.definedUnit;
-               }
-               
-               Variant variant = variable.getVariantValue(graph);
-               Binding binding = variant.getBinding();
-               if(binding == null) return null;
-               Datatype dt = binding.type();
-               if(!(dt instanceof NumberType)) return null;
-               NumberType nt = (NumberType)dt;
-               return nt.getUnit();
-               
-       } catch (DatabaseException e) {
-               return null;
-       }
-       
+
+        try {
+
+            Resource predicate = variable.getPossiblePredicateResource(graph);
+            if(predicate != null) {
+                PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(predicate));
+                if(info.definedUnit != null) return info.definedUnit;
+            }
+
+            Variant variant = variable.getVariantValue(graph);
+            Binding binding = variant.getBinding();
+            if(binding == null) return null;
+            Datatype dt = binding.type();
+            if(!(dt instanceof NumberType)) return null;
+            NumberType nt = (NumberType)dt;
+            return nt.getUnit();
+
+        } catch (DatabaseException e) {
+            return null;
+        }
+
     }
 
     /**
@@ -790,8 +795,10 @@ final public class Variables {
                     result = new Variant(binding, n.support.manager.getValue(n.node, binding));
                 else
                     result = n.support.manager.getValue(n.node);
+            } catch (NodeManagerException e) {
+                exception = e;
             } catch (Exception e) {
-                Logger.defaultLogError(e);
+                LOGGER.error("Error while getting node value", e);
                 exception = e;
             }
         }
@@ -814,10 +821,9 @@ final public class Variables {
             try {
                 result = NodeStructureRequest.get(n);
             } catch (NodeManagerException e) {
-                Logger.defaultLogError(e);
                 exception = e;
             }
-        }
+         }
 
     };
 
@@ -825,12 +831,12 @@ final public class Variables {
         Variable v = Variables.getPossibleVariable(graph, entity);
         return v != null ? v.getPossibleProperty(graph, property) : null;
     }
-    
-       public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,
-                       Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,
-                       Function1<Variable, Datatype> getDatatype) {
-               return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);
-       }
+
+    public static ValueAccessor createValueAccessor(Function1<Variable, Object> getValue1, Function2<Variable, Binding, Object> getValue2,
+            Function2<Variable, Object, Object> setValue2, Function3<Variable, Object, Binding, Object> setValue3,
+            Function1<Variable, Datatype> getDatatype) {
+        return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype);
+    }
 
     public static void setRVIProperty(WriteGraph graph, Variable variable, RVI rvi) throws DatabaseException {
         Layer0 L0 = Layer0.getInstance(graph);
index 53a3dc1ad0b955c57547e70b450fbf55c6cd8907..f5e55deaae4d8a3b45b434c50c84c76577943836 100644 (file)
@@ -13,6 +13,7 @@ import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.procedure.AsyncContextMultiProcedure;
 import org.simantics.db.procedure.AsyncMultiProcedure;
 import org.simantics.db.request.ExternalRead;
+import org.simantics.db.request.Read;
 import org.simantics.db.service.QueryControl;
 import org.simantics.utils.DataContainer;
 import org.slf4j.Logger;
@@ -145,6 +146,17 @@ public class QueryControlImpl implements QueryControl {
                ReadGraphImpl impl = (ReadGraphImpl)graph;
                return impl.withParent(null, null, false);
        }
+       
+    @Override
+    public <T> T syncRequestIndependent(ReadGraph graph, Read<T> request) throws DatabaseException {
+        ReadGraphImpl independent = ((ReadGraphImpl)graph).withParent(null, null, false);
+        independent.asyncBarrier.inc();
+        try {
+            return independent.syncRequest(request);
+        } finally {
+            independent.asyncBarrier.dec();
+        }
+    }
 
        @Override
        public boolean hasParentRequest(ReadGraph graph) {
index 92c5e9dda255a93b19ffeb21954a2c4153c7c674..0178e805fd29d09b99cce3ecc5ff7d8a4b3e8fec 100644 (file)
@@ -18,7 +18,6 @@ import org.simantics.db.SessionManager;
 import org.simantics.db.SessionReference;
 import org.simantics.db.VirtualGraph;
 import org.simantics.db.authentication.UserAuthenticationAgent;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.InvalidAuthenticationException;
 import org.simantics.db.exception.InvalidUserException;
@@ -30,9 +29,13 @@ import org.simantics.db.impl.graph.WriteSupport;
 import org.simantics.db.impl.query.QueryProcessor;
 import org.simantics.db.impl.query.QuerySupport;
 import org.simantics.db.service.ServerInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 final public class SessionImplDb extends SessionImplSocket {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(SessionImplDb.class);
+
     /**
      * Cached ServerInformation structure fetched from the server at connection
      * time. It should never change during a single session and therefore it
@@ -58,7 +61,7 @@ final public class SessionImplDb extends SessionImplSocket {
         try {
             newId = cluster.createResource(clusterTranslator);
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("createResource failed", e);
             return null;
         }
         return new ResourceImpl(resourceSupport, newId);
@@ -114,8 +117,7 @@ final public class SessionImplDb extends SessionImplSocket {
 //            clusterTable.dispose(); clusterTable = null;
 //            throw e;
         } catch (Throwable e) {
-            e.printStackTrace();
-            Logger.defaultLogError("Unhandled error. See exception for details.", e);
+            LOGGER.error("Unhandled error. See exception for details.", e);
             graphSession = null;
             clusterTable.dispose(); clusterTable = null;
             throw new Exception(e);
index 22d0f316545762d4937b384bea9fd648e8bdd441..29c70445bd208dd190c9796b60f2e31f46408dca 100644 (file)
@@ -328,7 +328,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
         try {
             getClusterTable().refresh(csid, this, clusterUID);
         } catch (Throwable t) {
-            Logger.defaultLogError("Refesh failed.", t);
+            LOGGER.error("refresh({}, {}) failed", thread, csid, t);
         }
     }
 
@@ -461,17 +461,17 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                     });
 
                     assert (null != writer);
-//                    writer.state.barrier.inc();
+                    writer.asyncBarrier.inc();
 
                     try {
                         request.perform(writer);
                         assert (null != writer);
                     } catch (Throwable t) {
                         if (!(t instanceof CancelTransactionException))
-                            Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", t);
+                            LOGGER.error("Write transaction caused an unexpected error, see exception.", t);
                         writeState.except(t);
                     } finally {
-//                        writer.state.barrier.dec();
+                        writer.asyncBarrier.dec();
 //                        writer.waitAsync(request);
                     }
 
@@ -482,7 +482,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
 
                     // Log it first, just to be safe that the error is always logged.
                     if (!(e instanceof CancelTransactionException))
-                    Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e);
+                        LOGGER.error("Write transaction caused an unexpected error, see exception.", e);
 
 //                    writeState.getGraph().state.barrier.dec();
 //                    writeState.getGraph().waitAsync(request);
@@ -571,52 +571,21 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                 VirtualGraph vg = getProvider(request.getProvider());
                 WriteGraphImpl writer = WriteGraphImpl.create(getQueryProvider2(), writeSupport, vg);
 
-                try {
-                    WriteState<T> writeStateT = new WriteState<T>(writer, request, notify, procedure);
-                    writeState = writeStateT;
+                WriteState<T> writeStateT = new WriteState<T>(writer, request, notify, procedure);
+                writeState = writeStateT;
+                assert (null != writer);
 
-                    assert (null != writer);
-//                    writer.state.barrier.inc();
+                try {
+                    writer.asyncBarrier.inc();
                     writeStateT.setResult(request.perform(writer));
                     assert (null != writer);
-
-//                    writer.state.barrier.dec();
-//                    writer.waitAsync(null);
-
                 } catch (Throwable e) {
-
-//                    writer.state.barrier.dec();
-//                    writer.waitAsync(null);
-
                     writeState.except(e);
-
-//                  state.stopWriteTransaction(clusterStream);
-//
-//              } catch (Throwable e) {
-//                  // Log it first, just to be safe that the error is always logged.
-//                  Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e);
-//
-//                  try {
-//                      // Callback is client code, we have to be prepared for it to throw unexpected exceptions.
-//                      // All we can do here is to log those, can't really pass them anywhere.
-//                      if (procedure != null) {
-//                          if(e instanceof DatabaseException) procedure.exception((DatabaseException)e);
-//                          else procedure.exception(new DatabaseException(e));
-//                      }
-//                  } catch (Throwable e2) {
-//                      Logger.defaultLogError("Write request callback caused an unexpected error, see exception.", e2);
-//                  }
-//
-//                  clientChanges = new ClientChangesImpl(SessionImplSocket.this);
-//
-//                  state.stopWriteTransaction(clusterStream);
-
                 } finally {
+                    writer.asyncBarrier.dec();
                     fireSessionVariableChange(SessionVariables.QUEUED_WRITES);
                 }
 
-//              if(notify != null) notify.release();
-
                 task.finish();
 
             }
@@ -657,7 +626,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                             if (t instanceof DatabaseException) callback.accept((DatabaseException) t);
                             else callback.accept(new DatabaseException(t));
                         } else
-                            Logger.defaultLogError("Unhandled exception", t);
+                            LOGGER.error("Unhandled exception", t);
                     }
                 };
 
@@ -1355,7 +1324,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                 callback.exception(new DatabaseException(e));
 
             state.stopWriteTransaction(clusterStream);
-            Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e);
+            LOGGER.error("Write transaction caused an unexpected error, see exception.", e);
 
         } finally  {
 
@@ -1561,7 +1530,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                                 if(throwable != null) {
                                     throwable.set(th);
                                 } else {
-                                    Logger.defaultLogError("Unhandled exception", th);
+                                    LOGGER.error("Unhandled exception", th);
                                 }
 
                             }
@@ -1574,7 +1543,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                             if(throwable != null) {
                                 throwable.set(t);
                             } else {
-                                Logger.defaultLogError("Unhandled exception", t);
+                                LOGGER.error("Unhandled exception", t);
                             }
 
                             try {
@@ -1586,7 +1555,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                                 if(throwable != null) {
                                     throwable.set(t2);
                                 } else {
-                                    Logger.defaultLogError("Unhandled exception", t2);
+                                    LOGGER.error("Unhandled exception", t2);
                                 }
 
                             }
@@ -1626,6 +1595,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                 ITask task = ThreadLogger.task(request);
 
                 final ReadGraphImpl newGraph = ReadGraphImpl.create(getQueryProvider2());
+                newGraph.asyncBarrier.inc();
 
                 try {
 
@@ -1663,6 +1633,8 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
 
                 } finally {
 
+                    newGraph.asyncBarrier.dec();
+
                     fireSessionVariableChange(SessionVariables.QUEUED_READS);
 
                 }
@@ -2479,6 +2451,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
                 return;
 
             WriteGraphImpl reactionGraph = WriteGraphImpl.create(graph.processor, writeSupport, null);
+            reactionGraph.asyncBarrier.inc();
 
             try {
 
@@ -2493,6 +2466,8 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
 
             } finally {
 
+                reactionGraph.asyncBarrier.dec();
+
             }
 
         } catch (Throwable t) {
@@ -2536,39 +2511,41 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
      */
     @SuppressWarnings("unchecked")
     @Override
-    public synchronized <T> T peekService(Class<T> api) {
-
-               if(serviceKey1 == api) {
-                       return (T)service1;
-               } else if (serviceKey2 == api) {
-                       // Promote this key
-                       Object result = service2;
-                       service2 = service1;
-                       serviceKey2 = serviceKey1;
-                       service1 = result;
-                       serviceKey1 = api;
-                       return (T)result;
-               }
+    public <T> T peekService(Class<T> api) {
+        if (Layer0.class == api)
+            return (T) L0;
 
-       if (Layer0.class == api)
-               return (T) L0;
-        if (ServerInformation.class == api)
-            return (T) getCachedServerInformation();
-        else if (WriteGraphImpl.class == api)
-            return (T) writeState.getGraph();
-        else if (ClusterBuilder.class == api)
-            return (T)new ClusterBuilderImpl(this, (WriteOnlySupport)writeState.getGraph().writeSupport);
-        else if (ClusterBuilderFactory.class == api)
-            return (T)new ClusterBuilderFactoryImpl(this);
+        synchronized (this) {
+            if (serviceKey1 == api) {
+                return (T) service1;
+            }
+            if (serviceKey2 == api) {
+                // Promote this key
+                Object result = service2;
+                service2 = service1;
+                serviceKey2 = serviceKey1;
+                service1 = result;
+                serviceKey1 = api;
+                return (T)result;
+            }
 
-               service2 = service1;
-               serviceKey2 = serviceKey1;
+            if (ServerInformation.class == api)
+                return (T) getCachedServerInformation();
+            else if (WriteGraphImpl.class == api)
+                return (T) writeState.getGraph();
+            else if (ClusterBuilder.class == api)
+                return (T)new ClusterBuilderImpl(this, (WriteOnlySupport)writeState.getGraph().writeSupport);
+            else if (ClusterBuilderFactory.class == api)
+                return (T)new ClusterBuilderFactoryImpl(this);
 
-        service1 = serviceLocator.peekService(api);
-        serviceKey1 = api;
+            service2 = service1;
+            serviceKey2 = serviceKey1;
 
-        return (T)service1;
+            service1 = serviceLocator.peekService(api);
+            serviceKey1 = api;
 
+            return (T)service1;
+        }
     }
 
     /*
@@ -2615,9 +2592,9 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
             try {
                 h.valuesChanged(ctx);
             } catch (Exception e) {
-                Logger.defaultLogError("monitor handler notification produced the following exception", e);
+                LOGGER.error("monitor handler notification produced the following exception", e);
             } catch (LinkageError e) {
-                Logger.defaultLogError("monitor handler notification produced a linkage error", e);
+                LOGGER.error("monitor handler notification produced a linkage error", e);
             }
         }
     }
@@ -3604,4 +3581,10 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule
         state.setCombine(false);
     }
 
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T l0() {
+        return (T) L0;
+    }
+
 }
index 50184528e6f7641719c2f0e3da3caf8e7212bf10..d90f2c3a530a06b6d9fb47bca020005c7c2e5bb4 100644 (file)
@@ -16,7 +16,6 @@ import java.io.IOException;
 import org.simantics.db.ServerI;
 import org.simantics.db.VirtualGraph;
 import org.simantics.db.authentication.UserAuthenticationAgent;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.InvalidAuthenticationException;
 import org.simantics.db.exception.InvalidUserException;
@@ -24,6 +23,8 @@ import org.simantics.db.impl.ResourceImpl;
 import org.simantics.db.impl.VirtualGraphImpl;
 import org.simantics.db.impl.query.QueryProcessor;
 import org.simantics.db.service.ServerInformation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import fi.vtt.simantics.procore.BackdoorAuthenticator;
 import fi.vtt.simantics.procore.ProCoreServerReference;
@@ -31,6 +32,9 @@ import fi.vtt.simantics.procore.ProCoreSessionReference;
 import fi.vtt.simantics.procore.SessionManagerSource;
 
 public class SessionImplVirtual extends SessionImplSocket {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SessionImplVirtual.class);
+
     protected VirtualGraphImpl virtualGraphImpl;
     public SessionImplVirtual(UserAuthenticationAgent authAgent)
     throws DatabaseException {
@@ -75,12 +79,11 @@ public class SessionImplVirtual extends SessionImplSocket {
         } catch (InvalidUserException e) {
             throw e;
         } catch (IOException e) {
-               Logger.defaultLogError("I/O error. See exception for details.", e);
+            LOGGER.error("I/O error. See exception for details.", e);
             graphSession = null;
             throw new DatabaseException(e);
         } catch (Throwable e) {
-            e.printStackTrace();
-            Logger.defaultLogError("Unhandled error. See exception for details.", e);
+            LOGGER.error("Unhandled error. See exception for details.", e);
             graphSession = null;
             throw new DatabaseException(e);
         }
@@ -108,7 +111,7 @@ public class SessionImplVirtual extends SessionImplSocket {
         try {
             return gs.getServerInformation();
         } catch (DatabaseException e) {
-            Logger.defaultLogError("Failed to get server info.", e);
+            LOGGER.error("Failed to get server info.", e);
             return null;
         }
     }
index 4c6e77b1a94729c0274078ef5318ffcf30a51f36..1e468f2c3f25e2e3e50cc6487fc02e57d3a7017e 100644 (file)
@@ -24,6 +24,7 @@ import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.InternalException;
 import org.simantics.db.exception.RuntimeDatabaseException;
+import org.simantics.db.impl.graph.ReadGraphImpl;
 import org.simantics.db.impl.graph.WriteGraphImpl;
 import org.simantics.db.impl.query.QueryProcessor;
 import org.simantics.db.request.WriteOnly;
@@ -340,7 +341,10 @@ class State {
 
 //                start = System.nanoTime();
                 queryProvider.propagateChangesInQueryCache(graph);
-                queryProvider.listening.fireListeners(graph);
+                ReadGraphImpl listenerGraph = graph.forRecompute(null);
+                listenerGraph.asyncBarrier.inc();
+                queryProvider.listening.fireListeners(listenerGraph);
+                listenerGraph.asyncBarrier.dec();
 //                duration = System.nanoTime() - start;
 //                System.out.println("performScheduledUpdates " + 1e-9*duration + "s. ");
 
index ea4319ace00c464095ab59547d93f6ce2da11ba7..247df4645c5b207c13f2e19dbb94d84af31bc850 100644 (file)
@@ -8,7 +8,6 @@ import org.simantics.db.VirtualGraph;
 import org.simantics.db.WriteGraph;
 import org.simantics.db.common.MetadataUtils;
 import org.simantics.db.common.exception.DebugException;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.exception.ImmutableException;
 import org.simantics.db.exception.ServiceException;
@@ -28,9 +27,13 @@ import org.simantics.db.request.WriteOnly;
 import org.simantics.db.request.WriteResult;
 import org.simantics.db.request.WriteTraits;
 import org.simantics.db.service.ByteReader;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class WriteSupportImpl implements WriteSupport {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(WriteSupportImpl.class);
+
     final private SessionImplSocket session;
     final private QueryProcessor queryProcessor;
     final private State state;
@@ -122,7 +125,7 @@ public class WriteSupportImpl implements WriteSupport {
                 try {
                     addSetValue(((ResourceImpl) resource).id, value, value.length);
                 } catch (DatabaseException e) {
-                    Logger.defaultLogError(e);
+                    LOGGER.error("writeOnly setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e);
                 }
             }
         } else {
@@ -134,7 +137,7 @@ public class WriteSupportImpl implements WriteSupport {
                 try {
                     addSetValue(((ResourceImpl) resource).id, value, value.length);
                 } catch (DatabaseException e) {
-                    Logger.defaultLogError(e);
+                    LOGGER.error("setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e);
                 }
             }
             queryProcessor.releaseWrite(session.writeState.getGraph());
@@ -199,7 +202,7 @@ public class WriteSupportImpl implements WriteSupport {
             try { 
                 cluster.removeValue(key, session.clusterTranslator);
             } catch (DatabaseException e) {
-                Logger.defaultLogError(e);
+                LOGGER.error("denyValue({}, {}) failed", provider, resource, e);
                 return;
             }
             queryProcessor.updateValue(key);
@@ -460,7 +463,7 @@ public class WriteSupportImpl implements WriteSupport {
             if (null != c && c != cluster)
                 session.clusterTable.replaceCluster(c);
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("claimImpl({}, {}, {}) failed", subject, predicate, object, e);
             throw new RuntimeException(e);
         }
         queryProcessor.updateStatements(subject, predicate);
@@ -480,7 +483,7 @@ public class WriteSupportImpl implements WriteSupport {
             if (null != c && c != cluster)
                 session.clusterTable.replaceCluster(c);
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("claimImpl2({}, {}, {}) failed", subject, predicate, object, e);
         }
         if (cluster.isWriteOnly())
             return;
@@ -504,7 +507,7 @@ public class WriteSupportImpl implements WriteSupport {
         try {
             cluster.denyRelation(subject, predicate, object, session.clusterTranslator);
         } catch (DatabaseException e) {
-            Logger.defaultLogError(e);
+            LOGGER.error("removeStatement({}, {}, {}) failed", subject, predicate, object, e);
             return false;
         }
         queryProcessor.updateStatements(subject, predicate);
index 5e818cb995c32408a9f04377c0b0885767d95513..924ccffb02ec855e492230e6a21e9d47bdad2b3f 100644 (file)
@@ -62,7 +62,7 @@ import org.simantics.db.request.WriteInterface;
  * @see MergingGraphRequestProcessor
  * @see AsyncRequestProcessor
  */
-public interface RequestProcessor extends RequestProcessorSpecific, ServiceLocator {
+public interface RequestProcessor extends RequestProcessorSpecific, ServiceLocator, ResourceLocator {
 
     Resource getRootLibrary();
 
diff --git a/bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java b/bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java
new file mode 100644 (file)
index 0000000..8a8b0fa
--- /dev/null
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.43.0
+ */
+public interface ResourceLocator {
+
+    /**
+     * Layer0 is an integral part of Simantics database modelling and for performance
+     * reasons deserves simplest possible access to its resource class.
+     * 
+     * @return returns the internally cached
+     *         <code>org.simantics.layer0.Layer0</code> instance
+     */
+    public <T> T l0();
+
+}
index 3da3c5aa3baa8f71e50bb1615939dcc8ef8a7fae..a8c7286437aa4b1d08c619926a05b8d986eec5b0 100644 (file)
@@ -17,9 +17,11 @@ import org.simantics.db.AsyncReadGraph;
 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.procedure.AsyncContextMultiProcedure;
 import org.simantics.db.procedure.AsyncMultiProcedure;
 import org.simantics.db.request.ExternalRead;
+import org.simantics.db.request.Read;
 
 
 /**
@@ -87,12 +89,25 @@ public interface QueryControl {
      * performed with the specified ReadGraph. DB listeners are therefore not
      * triggered by anything that is performed with the returned ReadGraph.
      * 
+     * @Deprecated In favor of syncRequestIndependent 
      * @param graph read transaction handle to clone for listener-independent
      *        use
      * @return read transaction handle that is independent of the requests
      *         performed with the parameter
      */
     ReadGraph getIndependentGraph(ReadGraph graph);
+    
+    /**
+     * Performs the given request without accumulating query dependencies.
+     * DB listeners are therefore not triggered by anything that is performed within the request.
+     * 
+     * @param graph read transaction handle to clone for listener-independent
+     *        use
+     * @param request the request to perform
+     * @return the result of the request evaluation
+     */
+    <T> T syncRequestIndependent(ReadGraph graph, Read<T> request) throws DatabaseException;
+    
     boolean hasParentRequest(ReadGraph graph);
 
 }
index b984365f40d85a93433ea14337e4587b7e79e96d..2b4ec84d2c1386780af560eedd54afb4d9a10821 100644 (file)
          id="tspan6235"
          x="4.0821486"
          y="291.79337"
-         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.6444446px;font-family:'Cascadia Code';-inkscape-font-specification:'Cascadia Code, Normal';fill:#ffffff;fill-opacity:1;stroke-width:0.26458335px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">1.43.0</tspan></text>
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.6444446px;font-family:'Cascadia Code';-inkscape-font-specification:'Cascadia Code, Normal';fill:#ffffff;fill-opacity:1;stroke-width:0.26458335px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">1.44.0</tspan></text>
     <circle
        style="opacity:0.92900002;fill:#5d6b91;fill-opacity:1;stroke:none;stroke-width:1.27400005;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;filter:url(#filter6809)"
        id="path6231"
          id="tspan6894-5">DESKTOP</tspan></text>
     <circle
        style="opacity:1;fill:#215c9a;fill-opacity:1;stroke:#8b9de6;stroke-width:0.172755;stroke-miterlimit:4;stroke-dasharray:0.0863775, 0.0863775;stroke-dashoffset:1.26999998;stroke-opacity:0.96208532"
-       id="path6231-43-0"
+       id="path6231.44.0"
        cx="93.574448"
        cy="279.01871"
        r="1.4401269" />
index fe93717662b2220c840ca38d2be848ed2c542d3b..6357e537ac5c5d356b89803c25ad2ea3166c8706 100644 (file)
@@ -277,6 +277,12 @@ public class RouteGraph implements Serializable {
         transientLines.clear();
     }
     
+    protected void removeRouteTerminalsFromRouteLines() {
+        for(RouteLine line : lines) {
+            line.removeRouteTerminals();
+        }
+    }
+
     /**
      * Rotates given terminal clockwise by given amount
      * (also negative numbers are allowed). 
@@ -311,6 +317,7 @@ public class RouteGraph implements Serializable {
     public void update() {
         needsUpdate = false;
         removeTransientRouteLines();
+        removeRouteTerminalsFromRouteLines();
 
         //print();
         
index a6a4f22d2ff1b5ba0be0add013fe7d9c412ff29a..2011bfa28f153afec115d4c8b3aab2baf9a1dde9 100644 (file)
@@ -188,6 +188,10 @@ public class RouteLine implements RouteNode, Serializable {
        return lines;
     }
 
+    public void removeRouteTerminals() {
+        points.removeIf(p -> p instanceof RouteTerminal);
+    }
+
     public RouteTerminal getTerminal() {
         return terminal;
     }
index dd660d4aaa659df5bce98302794586549e423c04..3d6bd182f664b9146c5686155ac8d4f541e6f8cf 100644 (file)
@@ -164,18 +164,31 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
             boolean routeLineDoesNotIntersectTerminal;
             double linePosition = line.position;
             if(line.isHorizontal) { 
+                if (linePosition == y) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < y ? 3 : 1;
                 routeLineDoesNotIntersectTerminal = linePosition <= minY || linePosition >= maxY 
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
             else {
+                if (linePosition == x) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < x ? 2 : 0;
                 routeLineDoesNotIntersectTerminal = linePosition <= minX || linePosition >= maxX
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
                     
             // We can route the connection directly to the right direction
-            if(routeLineDoesNotIntersectTerminal && 
+            if((routeLineDoesNotIntersectTerminal ||
+                    (line.isHorizontal && (x == minX || x == maxX)) || // already on the top/bottom edge
+                    (!line.isHorizontal && (y == minY || y == maxY)) // already on the left/right edge
+                    ) && 
                     Directions.isAllowed(allowedDirections, lineDir)) {           
                 RouteLine line0 = createLine0(lineDir);
                 new RouteLink(line0, line);
index 0628573d0576962d7efff9efa3da0ebef159a44e..f36417b48d2c7cca4a19bd7709c307bfa7e44fe7 100644 (file)
@@ -145,7 +145,7 @@ public class SimpleConnectionUtility {
         return MORE_BENDS_BBS_DONT_INTERSECT;
     }
     
-    private static int simpleConnectionCaseRouteToBounds(RouteTerminal a,
+    public static int simpleConnectionCaseRouteToBounds(RouteTerminal a,
             RouteTerminal b) {
         double aX = 0.5*(a.getMinX() + a.getMaxX());
         double aY = 0.5*(a.getMinY() + a.getMaxY());
index 539e284611daef9388b578bafb82054e09d4df2a..32df540eec5a10ea41da8062652b30d16002d4dd 100644 (file)
@@ -315,8 +315,8 @@ public class MouseScaleMode extends AbstractMode {
                     System.out.println("Lp: " + p);
 
                 localAt.setTransform(
-                        localAt.getScaleX(), localAt.getShearX(),
-                        localAt.getShearY(), localAt.getScaleY(),
+                        localAt.getScaleX(), localAt.getShearY(),
+                        localAt.getShearX(), localAt.getScaleY(),
                         p.getX(), p.getY());
 
                 if (DEBUG)
index fb3666e0b275fbc8f982ef9a92be347646249064..1d04653b5720fd0ab8bcead8c522ec3b14961680 100644 (file)
@@ -37,6 +37,10 @@ public class GroupProxySymbolItem implements ISymbolItem {
         this.group = group;
     }
 
+    public ISymbolItem getSubject() {
+        return proxy;
+    }
+
     @Override
     public String getName() {
         return proxy.getName();
index b0146cc21bf7ad2b7be6b6b7e3a9bb0516e00aeb..e0d757417dc83250ba9f62702499bdf8334d9090 100644 (file)
@@ -55,9 +55,7 @@ public class ElementReorder extends ModificationAdapter {
         List<Resource> graphOrder = OrderedSetUtils.toList(g, l);
         Set<Resource> graphContents = new HashSet<Resource>(graphOrder);
 
-        List<Resource> diagramOrder = new ArrayList<Resource>(order.size());
-        Map<Resource, Integer> diagramOrderIndex = new HashMap<Resource, Integer>(order.size());
-        int i = 0;
+        List<Resource> newGraphOrder = new ArrayList<>();
         for (IElement e : order) {
             Object obj = ElementUtils.getObject(e);
             if (obj instanceof Resource) {
@@ -66,41 +64,22 @@ public class ElementReorder extends ModificationAdapter {
                 // This prevents errors in situations where #order contains
                 // elements that no longer exist in the diagram.
                 if (graphContents.contains(r)) {
-                    diagramOrder.add(r);
-                    diagramOrderIndex.put(r, Integer.valueOf(i));
-                    ++i;
+                       newGraphOrder.add(r);
                 }
             }
         }
 
-        // Reorder the backend list according to diagramOrder
-        i = 0;
-        for (Resource r : graphOrder) {
-            Integer di = diagramOrderIndex.get(r);
-            if (di != null) {
-                int targetIndex = di;
-                int graphIndex = i++;
-                if (graphIndex != targetIndex) {
-                    // Check if the predecessor of r is already correct.
-                    // If it is, we don't have to do anything for r.
-                    Resource graphPrev = OrderedSetUtils.prev(g, l, r);
-                    Resource after = null;
-                    if (targetIndex == 0) {
-                        after = l;
-                        if (l.equals(graphPrev))
-                            continue;
-                    } else {
-                        after = diagramOrder.get(targetIndex - 1);
-                        if (after.equals(graphPrev))
-                            continue;
-                    }
-
-                    // r needs to be repositioned.
-                    OrderedSetUtils.remove(g, l, r);
-                    OrderedSetUtils.addAfter(g, l, after, r);
+        // Safety measure for possible missing elements
+        if (graphOrder.size() != newGraphOrder.size()) {
+            Set<Resource> added = new HashSet<Resource>(newGraphOrder);
+            for (Resource r : graphOrder) {
+                if (!added.contains(r)) {
+                    newGraphOrder.add(r);
                 }
             }
         }
+
+        OrderedSetUtils.reorder(g, l, newGraphOrder);
     }
 
 }
index 7896e52a716a608b7ee307425f295156dc42cc32..9134c1729ac161c7ec4d9bcb927880da9612b8dd 100644 (file)
@@ -1033,6 +1033,17 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
         return result;
     }
 
+    
+    /**
+     * We need to have separate class for SelectionNode, so that SCLSceneGraph can handle this properly.
+     * 
+     */
+    public static class SelectionShapeNode extends ShapeNode {
+
+               private static final long serialVersionUID = -5393630944240940166L;
+       
+    }
+    
     public void paintSelectionFrame(int selectionId, G2DParentNode elementNode, G2DParentNode selectionNode, final IElement e, Color color) {
         // The element node already has the correct transform.
         AffineTransform selectionTransform = ElementUtils.getTransform(e);// no it doesnt ... new AffineTransform();
@@ -1054,7 +1065,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
                 Outline outline = (Outline) es.getAdapter(Outline.class);
                 if (outline == null || outline.getElementShape(e) == null)
                        continue;
-                ShapeNode shapenode = shapeholder.getOrCreateNode(getNodeId("outline", e, es), ShapeNode.class);
+                ShapeNode shapenode = shapeholder.getOrCreateNode(getNodeId("outline", e, es), SelectionShapeNode.class);
 //                shapenode.setShape(es.getSelectionShape(e));
 //                shapenode.setStroke(SELECTION_STROKE);
 //                shapenode.setScaleStroke(true);
@@ -1090,7 +1101,7 @@ public class ElementPainter extends AbstractDiagramParticipant implements Compos
             G2DParentNode shapeholder = selectionNode.getOrCreateNode(getNodeId("outlines", e), G2DParentNode.class);
 
             for (SelectionOutline es : shapeHandlers) {
-                ShapeNode shapenode = shapeholder.getOrCreateNode(getNodeId("outline", e, es), ShapeNode.class);
+                ShapeNode shapenode = shapeholder.getOrCreateNode(getNodeId("outline", e, es), SelectionShapeNode.class);
 //                shapenode.setShape(es.getSelectionShape(e));
 //                shapenode.setStroke(SELECTION_STROKE);
 //                shapenode.setScaleStroke(true);
index 007d039f23715e4ec65446739c8cc941cbe80cd5..8b893a2b1e7f0730fac80482cd67feb7ae1e115d 100644 (file)
@@ -86,8 +86,8 @@ public class ZOrderHandler extends AbstractDiagramParticipant {
                         int index = elements.indexOf(e);
                         if (index != -1 && selectedElements.contains(e)) {
                             changed |= diagram.moveTo(e, nextPos);
-                            nextPos = index;
                         }
+                        nextPos = index;
                     }
                     if (changed) {
                         notifyZOrderListeners(diagram);
@@ -121,8 +121,8 @@ public class ZOrderHandler extends AbstractDiagramParticipant {
                         int index = elements.indexOf(e);
                         if (index != -1 && selectedElements.contains(e)) {
                             changed |= diagram.moveTo(e, nextPos);
-                            nextPos = index;
                         }
+                        nextPos = index;
                     }
                     if (changed) {
                         notifyZOrderListeners(diagram);
index 2d270fb111599cc9a0714dc399166f9c7a57bfbf..3622652c999ebd8b4e67a36567e40e5cce9627d3 100644 (file)
@@ -18,7 +18,7 @@
        <!-- common settings for all modules -->
        <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-               <tycho-version>1.5.0</tycho-version>
+               <tycho-version>1.6.0</tycho-version>
        </properties>
 
        <build>
index f2321dce9515b2819af7c51ddc146f324c5b4b1a..9873f8f1eef88ce338129a110e5e1e61d2ab2a9d 100644 (file)
@@ -156,25 +156,27 @@ public class TransferableGraphUtils {
         }
         Identity consistsOf = findExternal(tg, "http://www.simantics.org/Layer0-1.1/ConsistsOf");
         Identity hasName = findExternal(tg, "http://www.simantics.org/Layer0-1.1/HasName");
-        for (int i = 0; i < tg.statements.length; i += 4) {
-            if (tg.statements[i] == parentResource) {
-                if (tg.statements[i + 1] == consistsOf.resource) {
-                    Identity identity = getIdentity(tg, tg.statements[i + 3]);
-                    if (identity != null) {
-                        if (identity.definition instanceof Internal) {
-                            Internal internal = (Internal) identity.definition;
-                            result.put(internal.name, identity);
-                        }
-                    } else {
-                        int possibleNameResource = getPossibleObject2(tg, tg.statements[i + 3], hasName);
-                        if (possibleNameResource != NOT_FOUND) {
-                            Value value = findValue(tg, possibleNameResource);
-                            if (value != null) {
-                                try {
-                                    String name = (String) value.value.getValue(Bindings.STRING);
-                                    result.put(name, new Identity(tg.statements[i + 3], new Internal(tg.statements[i], name)));
-                                } catch (AdaptException e) {
-                                    e.printStackTrace();
+        if(consistsOf != null && hasName != null) {
+            for (int i = 0; i < tg.statements.length; i += 4) {
+                if (tg.statements[i] == parentResource) {
+                    if (tg.statements[i + 1] == consistsOf.resource) {
+                        Identity identity = getIdentity(tg, tg.statements[i + 3]);
+                        if (identity != null) {
+                            if (identity.definition instanceof Internal) {
+                                Internal internal = (Internal) identity.definition;
+                                result.put(internal.name, identity);
+                            }
+                        } else {
+                            int possibleNameResource = getPossibleObject2(tg, tg.statements[i + 3], hasName);
+                            if (possibleNameResource != NOT_FOUND) {
+                                Value value = findValue(tg, possibleNameResource);
+                                if (value != null) {
+                                    try {
+                                        String name = (String) value.value.getValue(Bindings.STRING);
+                                        result.put(name, new Identity(tg.statements[i + 3], new Internal(tg.statements[i], name)));
+                                    } catch (AdaptException e) {
+                                        e.printStackTrace();
+                                    }
                                 }
                             }
                         }
index 4e405e2acafff0ba2c81d06cb6a48d382a17d778..6cc7a2a6f09a9bf50e1c7f27eeb74651180e1df2 100644 (file)
@@ -308,7 +308,7 @@ public class CSVFormatter {
                                // Sampling based on given startTime and timeStep
                                if(timeStep > 0) {
 
-                                       // Find the first sample time that contains data 
+                                       // Find the first sample time that contains data if startTime < _from 
                                        double n = Math.max(0, Math.ceil((_from-startTime) / timeStep));
                                        time = startTime + n*timeStep;
 
@@ -587,7 +587,7 @@ public class CSVFormatter {
     private Formatter evaluateFormatter(Format format, DecimalSeparator target) {
         // Probe decimal separator
         String onePointTwo = format.format(1.2);
-        System.out.println("formatted zeroPointOne: " + onePointTwo);
+        //System.out.println("formatted zeroPointOne: " + onePointTwo);
 
         DecimalSeparator formatSeparator;
         if (onePointTwo.indexOf('.') != -1) {
index 3f4ccc20bfbe2bcc253f4f18ec81a2265432a3d3..9101700d0c2dea734ab4f0022f07657c78f5fe7a 100644 (file)
 package org.simantics.modeling.ui.expression;
 
-import java.util.Stack;
-
-import org.simantics.basicexpression.analysis.DepthFirstAdapter;
-import org.simantics.basicexpression.node.AConstantValue;
-import org.simantics.basicexpression.node.ADivMultiplicative;
-import org.simantics.basicexpression.node.AMultMultiplicative;
-import org.simantics.basicexpression.node.APlusExpression;
 import org.simantics.basicexpression.node.AStringValue;
+import org.simantics.modeling.InvertBasicExpressionVisitorBase;
 import org.simantics.utils.datastructures.Triple;
 
-public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
-
-       Stack<Object> stack = new Stack<Object>();
-
-       public Object getResult() {
-               return stack.pop();
-       }
-
-       public void outAConstantValue(AConstantValue node) {
-               stack.push(Double.valueOf(node.toString()));
-       }
+public class InvertBasicExpressionVisitor extends InvertBasicExpressionVisitorBase {
 
+       @Override
        public void outAStringValue(AStringValue node) {
                String value = node.toString();
                stack.push(Triple.make(1.0, 0.0, value.substring(1, value.length() - 2).trim()));
        }
 
-       @SuppressWarnings("unchecked")
-    public void outAPlusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 + (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMinusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third ));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second - (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 - (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMultMultiplicative(AMultMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 * (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outADivMultiplicative(ADivMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       stack.push(Double.NaN);
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double,Double, String>)o1;
-                       stack.push(Triple.make(p.first / (Double)o2, p.second / (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 / (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-       
 }
index aadd9395ab2867faf1a4a3f3168558fb14d4146a..7a2e7a6eb3a1fb57b84a619190adf8d2a1b7cc2d 100644 (file)
@@ -23,8 +23,10 @@ import org.eclipse.jface.preference.IntegerFieldEditor;
 import org.eclipse.jface.preference.StringFieldEditor;
 import org.eclipse.jface.util.PropertyChangeEvent;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Color;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchPreferencePage;
 import org.eclipse.ui.preferences.ScopedPreferenceStore;
@@ -110,7 +112,8 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
            fExtensionEditor = new StringFieldEditor(CSVPreferences.P_CSV_FILE_EXTENSION, "File extension", getFieldEditorParent());
            addField(fExtensionEditor);
            
-           fResamplingEditor = new BooleanFieldEditor(CSVPreferences.P_CSV_RESAMPLE, "Resampling", getFieldEditorParent());
+           fResamplingEditor = new BooleanFieldEditor(CSVPreferences.P_CSV_RESAMPLE, "&Resample", getFieldEditorParent());
+           fResamplingEditor.getDescriptionControl(getFieldEditorParent()).setToolTipText("Resample exported data from raw data");
            addField(fResamplingEditor);
 
            fSamplingModeEditor = new ComboFieldEditor(CSVPreferences.P_CSV_SAMPLING_MODE, "Sampling mode",
@@ -127,8 +130,9 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
                        return true;
                    }
                    try {
+                       @SuppressWarnings("unused")
                        double number = Double.parseDouble(text);
-                       return number>0;
+                       return true;
                    } catch (NumberFormatException e1) {
                        return false;
                    }
@@ -136,6 +140,8 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
            };
            fStartEditor.setEmptyStringAllowed(true);
            fStartEditor.setErrorMessage("Enter valid start time value (s)");
+           fStartEditor.getTextControl(getFieldEditorParent()).setToolTipText("Time to start resampling from");
+           addField(fStartEditor);
 
            fStepEditor = new StringFieldEditor(CSVPreferences.P_CSV_TIME_STEP, "Step size (s)", getFieldEditorParent()) {
                protected boolean doCheckState() {
@@ -153,6 +159,7 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
            };
            fStepEditor.setEmptyStringAllowed(true);
            fStepEditor.setErrorMessage("Enter valid time step value (s)");
+           fStepEditor.getTextControl(getFieldEditorParent()).setToolTipText("Time step to use when resampling");
            addField(fStepEditor);
 
            Group significantDigitsGroup = new Group(getFieldEditorParent(), SWT.NONE);
@@ -171,6 +178,8 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
            addField(fDoubleDigitsEditor);
 
            GridLayoutFactory.swtDefaults().numColumns(2).applyTo(significantDigitsGroup);
+
+           updateSampling(getPreferenceStore().getBoolean(CSVPreferences.P_CSV_RESAMPLE));
        }
 
     /**
@@ -187,6 +196,8 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
             } else if (source == fColumnSeparatorEditor) {
                 columnSeparatorValue = (String) event.getNewValue();
                 validate = true;
+            } else if (source == fResamplingEditor) {
+                updateSampling();
             }
             if (validate) {
                 if (decimalSeparatorValue.equals(columnSeparatorValue)) {
@@ -201,4 +212,16 @@ public class CSVPreferencePage extends FieldEditorPreferencePage implements IWor
         super.propertyChange(event);
     }
 
+    private void updateSampling() {
+        updateSampling(fResamplingEditor.getBooleanValue());
+    }
+
+    private void updateSampling(boolean resample) {
+        Label fStartLabel = fStartEditor.getLabelControl(getFieldEditorParent());
+        Label fStepLabel = fStepEditor.getLabelControl(getFieldEditorParent());
+        Color gray = fStartLabel.getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);
+        fStartLabel.setForeground(resample ? null : gray);
+        fStepLabel.setForeground(resample ? null : gray);
+    }
+
 }
index d3170b9506270350f5dde298d7e1285bee0f2d1a..1db2ba151c972dccd2c52bd5f92e95d40c2a73bf 100644 (file)
@@ -348,13 +348,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi
         }
 
         try {
-
-            IModelingRules modelingRules = Simantics.getSession().syncRequest(DiagramRequests.getModelingRules(resource, null));
-            if (modelingRules != null) {
-                initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules);
-            }
-            
-            initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor());
+               fillInitialDiagramHints(initialHints);
             
             final RuntimeDiagramManager runtimeDiagramManager = RuntimeDiagramManager.create(Simantics.getSession(), resource, modelURI, RVI);
             
@@ -385,6 +379,15 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi
         return ctx.getSceneGraph();
     }
     
+    protected void fillInitialDiagramHints(IHintContext initialHints) throws DatabaseException {
+         IModelingRules modelingRules = Simantics.getSession().syncRequest(DiagramRequests.getModelingRules(resource, null));
+          if (modelingRules != null) {
+              initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules);
+          }
+          
+          initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor());
+    }
+    
     protected IElementClassProvider createElementClassProvider(ReadGraph graph) throws DatabaseException {
         DiagramResource dr = DiagramResource.getInstance(graph);
         return ElementClassProviders.mappedProvider(
index 5bcce3ee415683f32ad4c54065f61ff5ffe8f764..6293cbac9fd7d9c9fe3c6989e33ac368b5784fe5 100644 (file)
@@ -1,14 +1,6 @@
 package org.simantics.modeling;
 
-import java.util.Stack;
-
 import org.simantics.basicexpression.Expressions;
-import org.simantics.basicexpression.analysis.DepthFirstAdapter;
-import org.simantics.basicexpression.node.AConstantValue;
-import org.simantics.basicexpression.node.ADivMultiplicative;
-import org.simantics.basicexpression.node.AMultMultiplicative;
-import org.simantics.basicexpression.node.APlusExpression;
-import org.simantics.basicexpression.node.AVariablePrimary;
 import org.simantics.db.ReadGraph;
 import org.simantics.db.Resource;
 import org.simantics.db.WriteGraph;
@@ -19,110 +11,14 @@ import org.simantics.structural.stubs.StructuralResource2;
 import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.Triple;
 
-public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
-
-       Stack<Object> stack = new Stack<Object>();
-
-       public Object getResult() {
-               if(stack.size() != 1) return null; 
-               return stack.pop();
-       }
-
-       public void outAConstantValue(AConstantValue node) {
-               stack.push(Double.valueOf(node.toString()));
-       }
-
-       @Override
-       public void outAVariablePrimary(AVariablePrimary node) {
-        String value = node.toString().trim();
-        stack.push(Triple.make(1.0, 0.0, value));
-       }
-       
-       @SuppressWarnings("unchecked")
-    public void outAPlusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 + (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMinusExpression(APlusExpression node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third ));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first, p.second - (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 - (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outAMultMultiplicative(AMultMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
-                       stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
-                       stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 * (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
-
-       @SuppressWarnings("unchecked")
-    public void outADivMultiplicative(ADivMultiplicative node) {
-               
-               final Object o1 = stack.pop();
-               final Object o2 = stack.pop();
-               
-               if(o1 instanceof Double && o2 instanceof Triple) {
-                       stack.push(Double.NaN);
-               } else if (o2 instanceof Double && o1 instanceof Triple) {
-                       Triple<Double, Double, String> p = (Triple<Double,Double, String>)o1;
-                       stack.push(Triple.make(p.first / (Double)o2, p.second / (Double)o2, p.third));
-               } else if (o2 instanceof Double && o1 instanceof Double) {
-                       stack.push((Double)o1 / (Double)o2);
-               } else {
-                       stack.push(Double.NaN);
-               }
-               
-       }
+public class InvertBasicExpressionVisitor extends InvertBasicExpressionVisitorBase {
 
        private static final String MAGIC = "_111_";
-       
+
        private static String replaced(String expression) {
            return expression.replaceAll("\\.([A-Za-z])", MAGIC + "$1");
        }
-       
+
     public static void invert(WriteGraph graph, Variable base, String expression, Object value) throws DatabaseException {
         InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
         Expressions.evaluate(replaced(expression), visitor);
@@ -208,26 +104,36 @@ public class InvertBasicExpressionVisitor extends DepthFirstAdapter {
         
     }
 
-    public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+    @SuppressWarnings("unchecked")
+    private static Triple<Double, Double, String> possibleInvertibleExpression(ReadGraph graph, Variable base, String expression) throws DatabaseException {
         if (base == null || expression == null || expression.isEmpty())
             return null;
         InvertBasicExpressionVisitor visitor = new InvertBasicExpressionVisitor();
         //System.out.println("invert : " + expression + " -> " + replaced(expression) + " for " + base.getURI(graph));
         Expressions.evaluate(replaced(expression), visitor);
-        Object pair = visitor.getResult();
-        if(pair == null)
-            return null;
-        if(pair instanceof Triple) {
-            @SuppressWarnings("unchecked")
-            Triple<Double, Double, String> data = (Triple<Double, Double, String>)pair;
-            String key = data.third.replace(MAGIC,".");
-            String path = getVariablePath(graph, base, key);
-            if (path == null)
-                return null;
-            Variable targetVariable = base.browsePossible(graph, path);
-            return targetVariable;
-        }
+        Object result = visitor.getResult();
+        if (result instanceof Triple)
+            return (Triple<Double, Double, String>) result;
         return null;
     }
 
+    public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+        Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
+        if (data == null)
+            return null;
+        String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
+        return path != null ? base.browsePossible(graph, path) : null;
+    }
+
+    public static Triple<Double, Double, Variable> possibleInvertibleExpressionReferencedTransformedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException {
+        Triple<Double, Double, String> data = possibleInvertibleExpression(graph, base, expression);
+        if (data == null)
+            return null;
+        String path = getVariablePath(graph, base, data.third.replace(MAGIC, "."));
+        if (path == null)
+            return null;
+        Variable targetVariable = base.browsePossible(graph, path);
+        return targetVariable != null ? Triple.make(data.first, data.second, targetVariable) : null;
+    }
+
 }
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitorBase.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitorBase.java
new file mode 100644 (file)
index 0000000..8ccf5c2
--- /dev/null
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * Copyright (c) 2020 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.modeling;
+
+import java.util.Stack;
+
+import org.simantics.basicexpression.analysis.DepthFirstAdapter;
+import org.simantics.basicexpression.node.AConstantValue;
+import org.simantics.basicexpression.node.ADivMultiplicative;
+import org.simantics.basicexpression.node.AMinusExpression;
+import org.simantics.basicexpression.node.AMultMultiplicative;
+import org.simantics.basicexpression.node.APlusExpression;
+import org.simantics.basicexpression.node.AVariablePrimary;
+import org.simantics.utils.datastructures.Triple;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class InvertBasicExpressionVisitorBase extends DepthFirstAdapter {
+
+       protected Stack<Object> stack = new Stack<>();
+
+       public InvertBasicExpressionVisitorBase() {
+               super();
+       }
+
+       public Object getResult() {
+               if(stack.size() != 1) return null; 
+               return stack.pop();
+       }
+
+       @Override
+       public void outAConstantValue(AConstantValue node) {
+               stack.push(Double.valueOf(node.toString()));
+       }
+
+       @Override
+       public void outAVariablePrimary(AVariablePrimary node) {
+               String value = node.toString().trim();
+               stack.push(Triple.make(1.0, 0.0, value));
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void outAPlusExpression(APlusExpression node) {
+
+               final Object o1 = stack.pop();
+               final Object o2 = stack.pop();
+
+               if(o1 instanceof Double && o2 instanceof Triple) {
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+                       stack.push(Triple.make(p.first, p.second + (Double)o1, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Triple) {
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+                       stack.push(Triple.make(p.first, p.second + (Double)o2, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Double) {
+                       stack.push((Double)o1 + (Double)o2);
+               } else {
+                       stack.push(Double.NaN);
+               }
+
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void outAMinusExpression(AMinusExpression node) {
+
+               final Object o1 = stack.pop();
+               final Object o2 = stack.pop();
+
+               // o2 - o1
+               if(o1 instanceof Double && o2 instanceof Triple) {
+                       // <triple> o2 - double o1
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+                       stack.push(Triple.make(p.first, p.second - (Double)o1, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Triple) {
+                       // double o2 - <triple> o1
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+                       stack.push(Triple.make(-p.first, (Double)o2 - p.second, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Double) {
+                       stack.push((Double)o2 - (Double)o1);
+               } else {
+                       stack.push(Double.NaN);
+               }
+
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void outAMultMultiplicative(AMultMultiplicative node) {
+
+               final Object o1 = stack.pop();
+               final Object o2 = stack.pop();
+
+               if(o1 instanceof Double && o2 instanceof Triple) {
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o2;
+                       stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Triple) {
+                       Triple<Double, Double, String> p = (Triple<Double, Double, String>)o1;
+                       stack.push(Triple.make(p.first * (Double)o2, p.second * (Double)o2, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Double) {
+                       stack.push((Double)o1 * (Double)o2);
+               } else {
+                       stack.push(Double.NaN);
+               }
+
+       }
+
+       @SuppressWarnings("unchecked")
+       @Override
+       public void outADivMultiplicative(ADivMultiplicative node) {
+
+               final Object o1 = stack.pop();
+               final Object o2 = stack.pop();
+
+               // o2 / o1
+               if(o1 instanceof Double && o2 instanceof Triple) {
+                       // <triple> o2 / double o1 
+                       Triple<Double, Double, String> p = (Triple<Double,Double, String>)o2;
+                       stack.push(Triple.make(p.first / (Double)o1, p.second / (Double)o1, p.third));
+               } else if (o2 instanceof Double && o1 instanceof Triple) {
+                       // double o2 / <triple> o1 
+                       stack.push(Double.NaN);
+               } else if (o2 instanceof Double && o1 instanceof Double) {
+                       stack.push((Double)o2 / (Double)o1);
+               } else {
+                       stack.push(Double.NaN);
+               }
+
+       }
+
+}
\ No newline at end of file
index e8c54fa987537401d8b448c35652c6a7fe32ff16..6256891b82ae17a96391e7a05399b2ef9ae3f640 100644 (file)
@@ -3,6 +3,7 @@ package org.simantics.modeling;
 import gnu.trove.map.hash.THashMap;
 
 import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.layer0.request.PropertyInfo;
 import org.simantics.db.layer0.request.PropertyInfoRequest;
@@ -21,19 +22,28 @@ public class ProceduralSubstructureMapRequest extends VariableRead<THashMap<Stri
     public THashMap<String, Pair<String,Type>> perform(ReadGraph graph) throws DatabaseException {
         THashMap<String, Pair<String,Type>> propertyMap = new THashMap<String, Pair<String,Type>>();
         for(Variable child : variable.getChildren(graph)) {
-               for(Variable property : child.getProperties(graph)) {
-                   PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(property.getPredicateResource(graph)));
+            for(Variable property : child.getProperties(graph)) {
+                Resource predicate = property.getPossiblePredicateResource(graph);
+                if (predicate == null)
+                    continue;
+                
+                PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(predicate));
                 propertyMap.put(child.getName(graph) + "." + propertyInfo.name,
                         Pair.make("/" + child.getName(graph) + "#" + propertyInfo.name,
                                 SCLTypeUtils.getType(propertyInfo)));
-               }
+            }
         }
-       for(Variable property : variable.getProperties(graph)) {
-           PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(property.getPredicateResource(graph)));
+        for(Variable property : variable.getProperties(graph)) {
+            Resource predicate = property.getPossiblePredicateResource(graph);
+            if (predicate == null)
+                continue;
+            
+            PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(predicate));
             propertyMap.put(propertyInfo.name,
                     Pair.make("#" + propertyInfo.name,
                             SCLTypeUtils.getType(propertyInfo)));
-       }
+        }
+        
         return propertyMap;
     }
 
index db65b4de38c33193a1c1fe7e9492c799ab4544e2..82115ef0e0825e2c9b8b2c69793f6bffd015344b 100644 (file)
@@ -51,6 +51,7 @@ import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.diagram.DiagramHints;
 import org.simantics.g2d.diagram.IDiagram;
 import org.simantics.g2d.diagram.handler.DataElementMap;
+import org.simantics.g2d.diagram.participant.ElementPainter.SelectionShapeNode;
 import org.simantics.g2d.diagram.participant.Selection;
 import org.simantics.g2d.element.IElement;
 import org.simantics.g2d.scenegraph.ICanvasSceneGraphProvider;
@@ -964,9 +965,31 @@ public class SCLScenegraph {
                        if (!hasContent)
                            return;
                        String svg = printSVGDocument(doc);
-                       parentBuilder.append(MAIN_SECTION, "<g class=\"" +node.getSimpleClassName() +"\">");
-                       parentBuilder.append(MAIN_SECTION, svg);
-                       parentBuilder.append(MAIN_SECTION, "\n</g>");
+                       if (node instanceof SelectionShapeNode) {
+                               SingleElementNode parentSEN = (SingleElementNode)NodeUtil.getNearestParentOfType(node, SingleElementNode.class);
+                        if(parentSEN != null) {
+                                String key = getKey(parentSEN);
+                                RenderSVGContext parentBuilder2 = getParentBuilder(parentSEN);
+                                parentBuilder2.append(SELECTION_SECTION, "\n<g style=\"visibility:hidden\" class=\"selection\" id=\"" + key + "\">");
+                             parentBuilder2.append(SELECTION_SECTION, svg);
+                             parentBuilder2.append(SELECTION_SECTION, "\n</g>");
+                             
+                             parentBuilder2.append(SELECTION_MASK_SECTION, "\n<g class=\"selectionMask\" id=\"" + key /*+ "\" transform=\"" + matrixString + "\"*/+ "\">");
+                             Rectangle2D rect = node.getBounds();
+                             // NaN
+                             if(rect.getHeight() == rect.getHeight() && rect.getWidth() == rect.getWidth()) {
+                                   parentBuilder2.append(SELECTION_MASK_SECTION,"<rect style=\"fill:#fff\" opacity=\"" + OPACITY + "\"");
+                                   parentBuilder2.append(SELECTION_MASK_SECTION," x=\"" + rect.getX() + "\" y=\"" + rect.getY() + "\"");
+                                   parentBuilder2.append(SELECTION_MASK_SECTION," width=\"" + rect.getWidth() + "\" height=\"" + rect.getHeight() + "\"");
+                                   parentBuilder2.append(SELECTION_MASK_SECTION,"></rect>");
+                             }
+                             parentBuilder2.append(SELECTION_MASK_SECTION,"\n</g>");
+                        }
+                       } else {
+                               parentBuilder.append(MAIN_SECTION, "<g class=\"" +node.getSimpleClassName() +"\">");
+                               parentBuilder.append(MAIN_SECTION, svg);
+                               parentBuilder.append(MAIN_SECTION, "\n</g>");
+                       }
                } catch (Exception e) {
                        // TODO: There are nodes that do not behave well when rendered to SVG. For backwards compatibility, we don't handle the exceptions.
                }
index e032ff4170440c36fa574aa18215d44b64ae8b22..6d8c271b0a8486960ef25aab27b624ab2129f11c 100644 (file)
@@ -14,7 +14,7 @@ Require-Bundle: org.simantics.db.layer0;bundle-version="1.1.0",
  org.simantics.scenegraph;bundle-version="1.1.1",
  org.eclipse.core.runtime;bundle-version="3.6.0",
  org.simantics.diagram.ontology;bundle-version="1.1.1",
- org.simantics.db.common
+ org.slf4j.api
 Bundle-ActivationPolicy: lazy
 Bundle-Activator: org.simantics.scenegraph.profile.impl.Activator
 Import-Package: org.simantics
index 9d379c890b9bd952a3ac2b6db941b3c71acc07c6..440ee2714aada5e1effad128b3b4b03a6d10f98e 100644 (file)
@@ -23,8 +23,8 @@ import org.simantics.db.AsyncRequestProcessor;
 import org.simantics.db.Resource;
 import org.simantics.db.Session;
 import org.simantics.db.common.session.SessionEventListenerAdapter;
-import org.simantics.db.common.utils.Logger;
 import org.simantics.db.procedure.Procedure;
+import org.simantics.db.service.QueryControl;
 import org.simantics.db.service.SessionEventSupport;
 import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.g2d.G2DSceneGraph;
@@ -38,9 +38,13 @@ import org.simantics.utils.datastructures.Pair;
 import org.simantics.utils.datastructures.disposable.IDisposable;
 import org.simantics.utils.threads.IThreadWorkQueue;
 import org.simantics.utils.threads.ThreadUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class ProfileObserver implements EvaluationContext {
 
+    private static final Logger LOGGER = LoggerFactory.getLogger(ProfileObserver.class);
+
     private final Session                     session;
 
     /**
@@ -58,6 +62,7 @@ public class ProfileObserver implements EvaluationContext {
     private volatile boolean                  dirty               = true;
     private volatile boolean                  disposed            = false;
 
+    private boolean                           needSynchronizedUpdates = false;
     private List<Pair<Style, Object>>         updates             = new ArrayList<>();
     private boolean                           updateAll;
     
@@ -95,6 +100,7 @@ public class ProfileObserver implements EvaluationContext {
         this.sceneGraph = sceneGraph;
         this.constants.putAll(constants);
         this.notification = notification;
+        this.needSynchronizedUpdates = session.getService(QueryControl.class).getAmountOfQueryThreads() > 1;
 
         attachSessionListener();
 
@@ -139,8 +145,14 @@ public class ProfileObserver implements EvaluationContext {
     public void update(Style style, Object item) {
         if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE)
             System.out.println("Profile observer marked dirty.");
-        
-        updates.add(Pair.make(style, item));
+
+        if (needSynchronizedUpdates) {
+            synchronized (updates) {
+                updates.add(Pair.make(style, item));
+            }
+        } else {
+            updates.add(Pair.make(style, item));
+        }
         //updateAll = true;
         dirty = true;
     }
@@ -179,10 +191,25 @@ public class ProfileObserver implements EvaluationContext {
                                 e.apply(ProfileObserver.this);
                             }
                             updateAll = false;
-                            updates.clear();
+                            if (needSynchronizedUpdates) {
+                                synchronized (updates) {
+                                    updates.clear();
+                                }
+                            } else {
+                                updates.clear();
+                            }
                         } else {
-                            List<Pair<Style, Object>> updatesCopy = new ArrayList<>(updates);
-                            updates.clear();
+                            List<Pair<Style, Object>> updatesCopy;
+                            if (needSynchronizedUpdates) {
+                                synchronized (updates) {
+                                    updatesCopy = new ArrayList<>(updates);
+                                    updates.clear();
+                                }
+                            } else {
+                                updatesCopy = new ArrayList<>(updates);
+                                updates.clear();
+                            }
+
                             for (Pair<Style, Object> update : updatesCopy) {
                                 Style style = update.first;
                                 Object item = update.second;
@@ -221,7 +248,7 @@ public class ProfileObserver implements EvaluationContext {
 
             @Override
             public void exception(Throwable t) {
-                Logger.defaultLogError(t);
+                LOGGER.error("RuntimeProfileActiveEntries request failed", t);
             }
         });
     }
@@ -233,7 +260,7 @@ public class ProfileObserver implements EvaluationContext {
 
     @Override
     public void exception(Throwable throwable) {
-        Logger.defaultLogError(throwable);
+        LOGGER.error("Exception occurred during diagram profile observation", throwable);
     }
 
     @SuppressWarnings("unchecked")
diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java
new file mode 100644 (file)
index 0000000..2601728
--- /dev/null
@@ -0,0 +1,11 @@
+package org.simantics.scl.runtime.exceptions;
+
+public class CheckedFunctionException extends RuntimeException {
+
+    private static final long serialVersionUID = 6314226787099140449L;
+
+    public CheckedFunctionException(Exception cause) {
+        super(cause);
+    }
+    
+}
index dd71e323b0b2a500d6c67452df72dad99d4079e5..899b9e731dd7800d7447e32988abbf588120edae 100644 (file)
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.simantics.scl.ui.assist;
 
+import org.eclipse.jface.fieldassist.ContentProposalAdapter;
 import org.eclipse.jface.fieldassist.IControlContentAdapter;
 import org.eclipse.jface.fieldassist.IControlContentAdapter2;
 import org.eclipse.swt.custom.StyledText;
@@ -69,26 +70,51 @@ public class StyledTextContentAdapter implements IControlContentAdapter, IContro
        public void insertControlContents(Control control, String contents, int cursorPosition) {
                StyledText text = ((StyledText)control);
                cursorPosition = Math.min(cursorPosition, contents.length());
-               int caretEndRange = text.getCaretOffset();
+
+               int caretOffset = text.getCaretOffset();
                String currentText = text.getText();
-               
-               int offset = caretEndRange;
-        int length = currentText.length();
-        while (--offset >= 0 && (Character.isJavaIdentifierPart(currentText.charAt(offset)) && !Character.isWhitespace(currentText.charAt(offset))))
-            length--;
-               
-               int nameSpaceBeginRange = currentText.lastIndexOf(".", caretEndRange - 1); //$NON-NLS-1$
-               if (nameSpaceBeginRange > length)
-                   length = nameSpaceBeginRange;
-               int endRange = currentText.length();
-               if (caretEndRange < endRange)
-                   endRange = caretEndRange;
-               text.setSelection(length, endRange);
+               int replacementOffset = findPrefixMatchOffset(currentText, caretOffset, contents);
+
+//             System.out.println("text: " + currentText);
+//             System.out.println("proposal to fill: " + contents);
+//             System.out.format("longest match of proposed contents found from text @ offset %d: \"%s[%s]%s\"%n",
+//                             replacementOffset,
+//                             currentText.substring(0, replacementOffset),
+//                             currentText.substring(replacementOffset, caretOffset),
+//                             currentText.substring(caretOffset));
+
+               // The text between [replaceOffset, caretOffset) will be replaced with `contents`
+               text.setSelection(replacementOffset, caretOffset);
                text.insert(contents);
-               // calculate the initial count of letters that was typed when the proposal was accepted to insert the caret
-               // at the right position
-               int proposalFirstLettersCount = endRange - (length);
-               text.setCaretOffset(caretEndRange + cursorPosition - proposalFirstLettersCount);
+               text.setSelection(replacementOffset + contents.length());
+       }
+
+       /**
+        * Find offset of longest prefix match of <code>match</code> in
+        * <code>text</code> ending at offset <code>endOffset</code>.
+        * 
+        * Example:
+        * <pre>
+        * ...  res (=text)
+        * resource (=match)
+        *  resourc
+        *   resour
+        *    resou
+        *     reso
+        *      res match! return endOffset - 3
+        * </pre>
+        * 
+        * @param text the text from which to find the match
+        * @param endOffset endOffset until which to search for the longest match
+        * @param match the text to prefix-match
+        * @return
+        */
+       private static int findPrefixMatchOffset(String text, int endOffset, String match) {
+               for (int i = match.length(); i >= 0; --i) {
+                       if (text.regionMatches(true, endOffset - i, match, 0, i))
+                               return endOffset - i;
+               }
+               return 0;
        }
 
        /*
index 1ee543f4c91c6ce7d45959f3d46ead583da32b57..34fbb587d8afca2e5645f3399914abe5d5991dab 100644 (file)
@@ -19,8 +19,6 @@ import java.util.Set;
 import java.util.concurrent.Executor;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 
 import org.simantics.databoard.Bindings;
 import org.simantics.databoard.accessor.error.AccessorException;
@@ -32,6 +30,8 @@ import org.simantics.history.HistoryException;
 import org.simantics.history.util.subscription.SubscriptionItem;
 import org.simantics.simulation.data.Datasource.DatasourceListener;
 import org.simantics.utils.datastructures.Triple;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * This adapter reads data from Datasource and writes to an open Subscription.
@@ -41,7 +41,7 @@ import org.simantics.utils.datastructures.Triple;
  */
 public class DatasourceAdapter implements DatasourceListener {
 
-       protected Logger logger = Logger.getLogger( DatasourceAdapter.class.toString() );
+       protected Logger logger = LoggerFactory.getLogger( DatasourceAdapter.class );
        protected Collector session;
        protected boolean loaded = false;
        protected List<VariableHandle> handles = new ArrayList<VariableHandle>();
@@ -139,7 +139,7 @@ public class DatasourceAdapter implements DatasourceListener {
                         result.add(Triple.make(key, binding, value));
                     } catch (AccessorException e) {
                         if (failedIds.add(key))
-                            logger.log(Level.SEVERE, e.toString(), e);
+                            logger.error(e.toString(), e);
                         continue;
                     }
                 }
@@ -172,20 +172,20 @@ public class DatasourceAdapter implements DatasourceListener {
                             value = handle.getValue(source);
                         } catch (AccessorException e) {
                             if (failedIds.add(key))
-                                logger.log(Level.SEVERE, e.toString(), e);
+                                logger.error(e.toString(), e);
                             continue;
                         }
                         Binding binding = handle.binding();
                         try {
                             session.setValue( key, binding, value );
                         } catch (HistoryException e) {
-                            logger.log(Level.SEVERE, e.toString(), e);
+                            logger.error(e.toString(), e);
                         }
                     } else {
                         Binding binding = bindings.get(i);
                         if (binding != null) { 
                             session.setValue( key, binding, value );
-                        }                       
+                        }
                     }
                 }
 
@@ -193,11 +193,11 @@ public class DatasourceAdapter implements DatasourceListener {
                 try {
                     session.endStep();
                 } catch (HistoryException e) {
-                    logger.log(Level.SEVERE, e.toString(), e);
+                    logger.error(e.toString(), e);
                 }
             }
         } catch (HistoryException e) {
-            logger.log(Level.SEVERE, e.toString(), e);
+            logger.error(e.toString(), e);
         } finally {
             stepLock.unlock();
         }
@@ -207,6 +207,5 @@ public class DatasourceAdapter implements DatasourceListener {
        public Executor getExecutor() {
                return null;
        }
-       
 
 }
index 402f3884d433270d9161594224d971469f297b3c..e09b3136e6307c7750f81f2ab1271ed340e4a2b4 100644 (file)
@@ -194,7 +194,10 @@ public class StandardNodeManager<Node, Engine extends StandardNodeManagerSupport
     @Override
     public Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException {
         try {
-            return getValue(node).getValue(binding);
+            Variant value = getValue(node);
+            if(NodeManager.PENDING_NODE_VALUE == value)
+                return value;
+            return value.getValue(binding);
         } catch (AdaptException e) {
             throw new BindingException(e);
         }
@@ -296,6 +299,8 @@ public class StandardNodeManager<Node, Engine extends StandardNodeManagerSupport
         Variant variant = valueCache.get(node);
         if(variant == null) {
             Object value = realm.getEngine().getEngineValue(node);
+            if(NodeManager.PENDING_NODE_VALUE == value)
+                return (Variant)value;
             Binding binding = realm.getEngine().getEngineBinding(node);
             variant = new Variant(binding, value);
             valueCache.put(node, variant);
index 345aff81f82e88771156ff69b5f19c67901719f0..27bf8c51b4d03757db7d7e98dec8fdf66acb30a6 100644 (file)
@@ -36,112 +36,114 @@ import org.simantics.simulator.variable.exceptions.NotInRealmException;
  */
 public interface NodeManager<Node> {
 
-       // --- Do not require a realm access ---
-       
-       /**
-        * The realm of the node manager. Almost all other methods
-        * of this class must be called inside this realm.
-        */
-       Realm getRealm();
-
-       /**
-        * Returns the name of the node. This method does not require 
-        * that caller is in realm.
-        */
-       String getName(Node node);
-
-       /**
-        * Adds a listener to a certain node. The new listener is called as
-        * soon as possible (for example before simulator takes the next simulation
-        * step). After the first call, it is called always the node value 
-        * or structure may have changed. This can be called outside of the realm.
-        */
-       void addNodeListener(Node node, Runnable listener);
-       
-       /**
-        * Removes previously added listener. This can be called outside of
-        * the realm.
-        */
-       void removeNodeListener(Node node, Runnable listener);
-       
-       // --- Require a realm access ---
-       
-       /**
-        * @return {@code null} if node cannot be found, otherwise a node with the given path
-        * @throws InvalidPathException if the path is not in a valid path format
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       Node getNode(String path) throws NodeManagerException;  
-       /**
-        * @return {@code null} if node cannot be found, otherwise a child node with the given name
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       Node getChild(Node node, String name) throws NodeManagerException;
-       Node getProperty(Node node, String name) throws NodeManagerException;
-       List<String> getChildNames(Node node) throws NodeManagerException;
-       List<String> getPropertyNames(Node node) throws NodeManagerException;
-       List<Node> getChildren(Node node) throws NodeManagerException;
-       List<Node> getProperties(Node node) throws NodeManagerException;
-
-       /**
-        * @throws NoValueException if the node has no value (and therefore no datatype)
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       Datatype getDatatype(Node node) throws NodeManagerException;
-       /**
-        * @throws NoValueException if the node has no value
-        * @throws BindingException if the value can not be bound to the given binding
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException;
-       /**
-        * A variant of {@link #getValue(Object, Binding)} that uses
-        * a binding chosen by the node manager.
-        */
-       Variant getValue(Node node) throws NodeManagerException;
-       /**
-        * @throws NoSuchNodeException if the property does not exist
-        * @throws NoValueException if the property has no value
-        * @throws NotInRealmException if not synchronized to the realm
-        * @throws BindingException if the value can not be bound to the given binding
-        */
-       Object getValue(Node node, String property, Binding binding) throws NodeManagerException, BindingException;
-       /**
-        * A variant of {@link #getValue(Object, String, Binding)} that uses
-        * a binding chosen by the node manager.
-        */
-       Variant getValue(Node node, String property) throws NodeManagerException;       
-       
-       /**
-        * @throws BindingException if the value can not be bound to the given binding
-        * @throws NoValueException if the property has no value that could be assigned
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       void setValue(Node node, Object value, Binding binding) throws NodeManagerException, BindingException;
-       /**
-        * @throws BindingException if the value can not be bound to the given binding
-        * @throws NoSuchNodeException if the property does not exist
-        * @throws NoValueException if the property has no value that could be assigned
-        * @throws NotInRealmException if not synchronized to the realm
-        */
-       void setValue(Node node, String property, Object value, Binding binding) throws NodeManagerException, BindingException;
-
-       /**
-        * Asks the full URI of a property node. The parent of the property is also given as a parameter.
-        * This is an optional method, NodeManager does not have to implement it for all nodes.
-        */
+    public static final Variant PENDING_NODE_VALUE = new Variant();
+
+    // --- Do not require a realm access ---
+
+    /**
+     * The realm of the node manager. Almost all other methods
+     * of this class must be called inside this realm.
+     */
+    Realm getRealm();
+
+    /**
+     * Returns the name of the node. This method does not require 
+     * that caller is in realm.
+     */
+    String getName(Node node);
+
+    /**
+     * Adds a listener to a certain node. The new listener is called as
+     * soon as possible (for example before simulator takes the next simulation
+     * step). After the first call, it is called always the node value 
+     * or structure may have changed. This can be called outside of the realm.
+     */
+    void addNodeListener(Node node, Runnable listener);
+
+    /**
+     * Removes previously added listener. This can be called outside of
+     * the realm.
+     */
+    void removeNodeListener(Node node, Runnable listener);
+
+    // --- Require a realm access ---
+
+    /**
+     * @return {@code null} if node cannot be found, otherwise a node with the given path
+     * @throws InvalidPathException if the path is not in a valid path format
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    Node getNode(String path) throws NodeManagerException;     
+    /**
+     * @return {@code null} if node cannot be found, otherwise a child node with the given name
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    Node getChild(Node node, String name) throws NodeManagerException;
+    Node getProperty(Node node, String name) throws NodeManagerException;
+    List<String> getChildNames(Node node) throws NodeManagerException;
+    List<String> getPropertyNames(Node node) throws NodeManagerException;
+    List<Node> getChildren(Node node) throws NodeManagerException;
+    List<Node> getProperties(Node node) throws NodeManagerException;
+
+    /**
+     * @throws NoValueException if the node has no value (and therefore no datatype)
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    Datatype getDatatype(Node node) throws NodeManagerException;
+    /**
+     * @throws NoValueException if the node has no value
+     * @throws BindingException if the value can not be bound to the given binding
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException;
+    /**
+     * A variant of {@link #getValue(Object, Binding)} that uses
+     * a binding chosen by the node manager.
+     */
+    Variant getValue(Node node) throws NodeManagerException;
+    /**
+     * @throws NoSuchNodeException if the property does not exist
+     * @throws NoValueException if the property has no value
+     * @throws NotInRealmException if not synchronized to the realm
+     * @throws BindingException if the value can not be bound to the given binding
+     */
+    Object getValue(Node node, String property, Binding binding) throws NodeManagerException, BindingException;
+    /**
+     * A variant of {@link #getValue(Object, String, Binding)} that uses
+     * a binding chosen by the node manager.
+     */
+    Variant getValue(Node node, String property) throws NodeManagerException;  
+
+    /**
+     * @throws BindingException if the value can not be bound to the given binding
+     * @throws NoValueException if the property has no value that could be assigned
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    void setValue(Node node, Object value, Binding binding) throws NodeManagerException, BindingException;
+    /**
+     * @throws BindingException if the value can not be bound to the given binding
+     * @throws NoSuchNodeException if the property does not exist
+     * @throws NoValueException if the property has no value that could be assigned
+     * @throws NotInRealmException if not synchronized to the realm
+     */
+    void setValue(Node node, String property, Object value, Binding binding) throws NodeManagerException, BindingException;
+
+    /**
+     * Asks the full URI of a property node. The parent of the property is also given as a parameter.
+     * This is an optional method, NodeManager does not have to implement it for all nodes.
+     */
     String getPropertyURI(Node parent, Node property);
 
-       /**
-        * Asks for the classifications of a property node.
-        * This is an optional method, NodeManager does not have to implement it for all nodes.
-        * A default implementation should just return {@link Collections#emptySet()}.
-        * Classifications can be any strings, however a recommended interpretation is to return
-        * the URIs of the primary ontological types that this node corresponds to.
-        
-        * @param node the node to classify
-        * @return classifications of the node, empty set if the node has no classifications
-        */
-       Set<String> getClassifications(Node node) throws NodeManagerException;
+    /**
+     * Asks for the classifications of a property node.
+     * This is an optional method, NodeManager does not have to implement it for all nodes.
+     * A default implementation should just return {@link Collections#emptySet()}.
+     * Classifications can be any strings, however a recommended interpretation is to return
+     * the URIs of the primary ontological types that this node corresponds to.
+     * 
+     * @param node the node to classify
+     * @return classifications of the node, empty set if the node has no classifications
+     */
+    Set<String> getClassifications(Node node) throws NodeManagerException;
 
 }
\ No newline at end of file
index a70949d5e1e2995fd9176e7e2c19d11ae030e4a7..708a32efcde55d6022b27675264762e31050ca65 100644 (file)
@@ -284,6 +284,14 @@ public class HorizRuler extends TrendGraphicalNode {
                return (end-from) / getWidth();
        }
 
+       /**
+        * @return the current starting sample time calculated from all visible chart
+        *         items.
+        */
+       public double getItemFromTime() {
+               return iFrom;
+       }
+
        /**
         * @return the current ending sample time calculated from all visible chart
         *         items.
index 0d0bc2f072e0231669ed8825444bc6a31fe5c466..ca5692d4b4c922b2cda04f852d28eb3cae9760b9 100644 (file)
@@ -13,7 +13,7 @@
 <feature
       id="org.simantics.sdk"
       label="Simantics SDK"
-      version="1.43.0.qualifier"
+      version="1.44.0.qualifier"
       provider-name="VTT Technical Research Centre of Finland">
 
    <description url="http://www.example.com/description">
index f06dc5e4735fae7d1579f9f88080ccd1097c6da1..ad1d836da29ed4b9b75af6c0e2a78001dc332086 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
 <?pde?>
 <!-- generated with https://github.com/eclipse-cbi/targetplatform-dsl -->
-<target name="Simantics 1.43.0" sequenceNumber="1582927656">
+<target name="Simantics 1.44.0" sequenceNumber="1582927656">
   <locations>
     <location includeMode="slicer" includeAllPlatforms="true" includeSource="true" includeConfigurePhase="false" type="InstallableUnit">
       <unit id="com.google.guava" version="21.0.0.v20170206-1425"/>
index 1d7588e2646b56ca377c9298075f73ba27df56c0..8d63f70f4a3977e7c950f5ab3c41ed2f9c837ddd 100644 (file)
@@ -1,4 +1,4 @@
-target "Simantics 1.43.0"
+target "Simantics 1.44.0"
 
 with source allEnvironments
 
index c636acba4307532b65fe7b27c1adab3b082ec48b..42fd442e8846bd623c1fa923766072cf8fcecb84 100644 (file)
@@ -2,7 +2,7 @@
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <artifactId>org.simantics.sdk.repository</artifactId>
-       <version>1.43.0-SNAPSHOT</version>
+       <version>1.44.0-SNAPSHOT</version>
        <packaging>eclipse-repository</packaging>
 
        <parent>
index da8b7254d61683f2dc11d3806ceb9fe9338abb2d..527066818af67407c2e0a417391296a4c9a3685e 100644 (file)
@@ -8,8 +8,8 @@
        <packaging>pom</packaging>
 
        <properties>
-               <tycho.version>1.5.0</tycho.version>
-               <tycho.extras.version>1.5.0</tycho.extras.version>
+               <tycho.version>1.6.0</tycho.version>
+               <tycho.extras.version>1.6.0</tycho.extras.version>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>