]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
Merge "Add missing javax.servlet-api bundle requirement for jersey bundles"
authorJani Simomaa <jani.simomaa@semantum.fi>
Thu, 16 Apr 2020 08:55:47 +0000 (08:55 +0000)
committerGerrit Code Review <gerrit2@simantics>
Thu, 16 Apr 2020 08:55:47 +0000 (08:55 +0000)
63 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/utils/OrderedSetUtils.java
bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.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/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/function/All.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java
bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java [new file with mode: 0644]
bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java
bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph
bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java
bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java [new file with mode: 0644]
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.graphfile.ui.ontology/.classpath [new file with mode: 0644]
bundles/org.simantics.graphfile.ui.ontology/.project [new file with mode: 0644]
bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.graphfile.ui.ontology/build.properties [new file with mode: 0644]
bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/.classpath [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/.project [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/adapters.xml [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/build.properties [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/plugin.xml [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java [new file with mode: 0644]
bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java [new file with mode: 0644]
bundles/org.simantics.history/src/org/simantics/history/csv/CSVFormatter.java
bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.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/SCLScenegraph.java
bundles/org.simantics.modeling/src/org/simantics/modeling/utils/DumpOntologyStructure.java
bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java [new file with mode: 0644]
bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/Activator.java
bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/BindingRegistry.java
bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/Namespace.java
bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java [new file with mode: 0644]
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
bundles/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 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 61580bfdcb6ae9a96680952b070261057b9a2fe6..27336b23d32474eda7bf7b00ab368a9cb5b56e02 100644 (file)
@@ -1511,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);
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 e3bd437416af310936e66533746b270d8228aba8..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));
 
     }
 
@@ -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);
+        }
+
+    }
+
 }
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 f52148c2a6b2306d9c8d4b6c0ce9e31cb5e89efe..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.getPossiblePredicateResource(graph))) {
-                                                               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.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.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,371 +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) {
-                       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;
+        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();
@@ -1239,130 +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.getPredicateResource(graph), 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.getPredicateResource(graph), 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;
@@ -1377,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();
 
     }
 
@@ -1443,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 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 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 b2895fb342d60fc1571b7f9b1fe4424c07144203..2f218d8fab325c4c0f7e082a3f977a74fa798486 100644 (file)
@@ -126,16 +126,18 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
                     double dy1 = curY-oldY;
                     double dx2 = curX-newX;
                     double dy2 = curY-newY;
-                    double maxRadius = 0.5 * Math.min(Math.sqrt(dx1*dx1 + dy1*dy1), Math.sqrt(dx2*dx2 + dy2*dy2));
+                    double r1 = Math.sqrt(dx1*dx1 + dy1*dy1);
+                    double r2 = Math.sqrt(dx2*dx2 + dy2*dy2);
+                    double maxRadius = 0.5 * Math.min(r1, r2);
                     double radius = Math.min(rounding, maxRadius);
-                    newPath.lineTo(curX + radius*Math.signum(oldX-curX), curY + radius*Math.signum(oldY-curY));
+                    double dx1Normalized = r1 > 0 ? dx1 / r1 : 0;
+                    double dy1Normalized = r1 > 0 ? dy1 / r1 : 0;
+                    double dx2Normalized = r2 > 0 ? dx2 / r2 : 0;
+                    double dy2Normalized = r2 > 0 ? dy2 / r2 : 0;
+                    newPath.lineTo(curX - radius*dx1Normalized, curY - radius*dy1Normalized);
                     newPath.curveTo(curX, curY,
                                     curX, curY,
-                                    curX + radius*Math.signum(newX-curX), curY + radius*Math.signum(newY-curY));
-
-                    //newPath.lineTo(curX + round*Math.signum(oldX-curX), curY + round*Math.signum(oldY-curY));
-                    //newPath.lineTo(curX + round*Math.signum(newX-curX), curY + round*Math.signum(newY-curY));
-                    //newPath.lineTo(curX, curY);
+                                    curX - radius*dx2Normalized, curY - radius*dy2Normalized);
                 }
                 else
                     ++state;
@@ -216,6 +218,8 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
         result = prime * result + (int) (temp ^ (temp >>> 32));
         result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode());
         result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode());
+        temp = Double.doubleToLongBits(rounding);
+        result = prime * result + (int) (temp ^ (temp >>> 32));
         result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode());
         return result;
     }
@@ -248,6 +252,8 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
                 return false;
         } else if (!lineStroke.equals(other.lineStroke))
             return false;
+        if (Double.doubleToLongBits(rounding) != Double.doubleToLongBits(other.rounding))
+            return false;
         if (routeLineStroke == null) {
             if (other.routeLineStroke != null)
                 return false;
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java
new file mode 100644 (file)
index 0000000..3ccb492
--- /dev/null
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * 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.diagram.connection.rendering;
+
+import java.awt.geom.Arc2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ConnectionCrossings implements PathModifier {
+    public enum Type {
+        NONE,
+        GAP,
+        ARC,
+        SQUARE
+    }
+
+    private List<Segment> segments = new ArrayList<>();
+    private double width;
+    private Type type;
+
+    public void setWidth(double gapWidth) {
+        this.width = gapWidth;
+    }
+
+    public double getWidth() {
+        return width;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    static class Segment {
+        public double x1, y1, x2, y2;
+
+        public Segment(double x1, double y1, double x2, double y2) {
+            this.x1 = x1;
+            this.y1 = y1;
+            this.x2 = x2;
+            this.y2 = y2;
+        }
+    };
+
+    public void reset() {
+        segments.clear();
+    }
+
+    static Double lineLineIntersection(Segment l1, Segment l2) { 
+        double epsilon = 0.001;
+
+        double d = (l1.x1 - l1.x2) * (l2.y1 - l2.y2) - (l1.y1 - l1.y2) * (l2.x1 - l2.x2);
+        if (d == 0.0) return null;
+        double s = ((l1.x1 - l2.x1) * (l2.y1 - l2.y2) - (l1.y1 - l2.y1) * (l2.x1 - l2.x2)) / d;
+        if ((s > epsilon) && (s < 1 - epsilon)) {
+            double t = -((l1.x1 - l1.x2) * (l1.y1 - l2.y1) - (l1.y1 - l1.y2) * (l1.x1 - l2.x1)) / d;
+            if ((t > epsilon) && (t < 1 - epsilon)) {
+                return t;
+            }
+        }
+        return null; 
+    }
+
+    public Path2D modify(Path2D path) {
+        Path2D.Double path2 = new Path2D.Double();
+        PathIterator iter = path.getPathIterator(null);
+
+        while (!iter.isDone()) {
+
+            double c[] = new double[6];
+            int i = iter.currentSegment(c);
+            switch (i) {
+            case PathIterator.SEG_MOVETO:
+                path2.moveTo(c[0], c[1]);
+                break;
+            case PathIterator.SEG_LINETO:
+                Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]);
+                
+                List<Double> gaps = new ArrayList<>();
+                for (Segment old : segments) {
+                    Double t = lineLineIntersection(old, l);
+                    if (t != null) {
+                        gaps.add(t);
+                    }
+                }
+
+                if (gaps.isEmpty()) {
+                    path2.lineTo(c[0], c[1]);
+                } else {
+                    Collections.sort(gaps);
+                    double dx = l.x2 - l.x1;
+                    double dy = l.y2 - l.y1;
+
+                    double pos = 0.0;
+                    double len = Math.sqrt(dx*dx + dy*dy);
+
+                    boolean finish = true;
+                    Point2D prevGapEnd = null;
+                    for (Double gapCenter : gaps) {
+                        double pos2 = gapCenter - width / 2 / len;
+                        double pos3 = gapCenter + width / 2 / len;
+                        if (pos2 > pos) {
+                            handleGap(path2, prevGapEnd);
+                            prevGapEnd = null;
+                            path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy);
+                        }
+                        if (pos3 < 1.0) {
+                            double x = l.x1 + pos3 * dx;
+                            double y = l.y1 + pos3 * dy;
+                            prevGapEnd = new Point2D.Double(x, y);
+                        } else {
+                            finish = false;
+                        }
+                        pos = pos3;
+                    }
+                    
+                    if (finish) {
+                        handleGap(path2, prevGapEnd);
+                        path2.lineTo(l.x2, l.y2);
+                    } else {
+                        prevGapEnd = new Point2D.Double(l.x2, l.y2);
+                        handleGap(path2, prevGapEnd);
+                    }
+                }
+                segments.add(l);
+
+                break;
+            case PathIterator.SEG_QUADTO:
+                // TODO: implement gaps
+                path2.quadTo(c[0], c[1], c[2], c[3]);
+                break;
+            case PathIterator.SEG_CUBICTO:
+                // TODO: implement gaps
+                path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]);
+                break;
+            case PathIterator.SEG_CLOSE:
+                // TODO: implement gaps
+                path2.closePath();
+                break;
+            default:
+                throw new RuntimeException("Unexpected segment type " + i);
+            }
+            iter.next();
+        }
+        return path2;
+    }
+
+    private void handleGap(Path2D path, Point2D prevGapEnd) {
+        if (prevGapEnd != null) {
+            switch (type) {
+            case ARC:
+                arcTo(path, prevGapEnd.getX(), prevGapEnd.getY());
+                break;
+            case SQUARE:
+                squareTo(path, prevGapEnd.getX(), prevGapEnd.getY(), width);
+                break;
+            case GAP:
+                path.moveTo(prevGapEnd.getX(), prevGapEnd.getY());
+                break;
+            case NONE:
+                break;
+            }
+        }
+    }
+
+    private static void arcTo(Path2D path, double x2, double y2) {
+        Arc2D arc = new Arc2D.Double();
+        double x1 = path.getCurrentPoint().getX();
+        double y1 = path.getCurrentPoint().getY();
+        double dx = x2 - x1;
+        double dy = y2 - y1;
+        double r = Math.sqrt(dx * dx + dy * dy) / 2;
+        double angle = Math.atan2(dx,  dy) * 180 / Math.PI + 90;
+        double span = (angle > 225 || angle < 45) ? 180 : -180;
+        arc.setArcByCenter((x1 + x2) / 2, (y1 + y2) / 2, r, angle, span, Arc2D.OPEN);
+        path.append(arc, true);
+    }
+    
+    private static void squareTo(Path2D path, double x2, double y2, double width) {
+        double x1 = path.getCurrentPoint().getX();
+        double y1 = path.getCurrentPoint().getY();
+        double dx = x2 - x1;
+        double dy = y2 - y1;
+        double l = Math.sqrt(dx * dx + dy* dy);
+        if (l > 0) {
+            double nx = -dy / l;
+            double ny = dx / l;
+            if (nx - ny < 0) {
+                nx = -nx;
+                ny = -ny;
+            }
+            path.lineTo(x1 + nx * width / 2, y1 + ny * width / 2);
+            path.lineTo(x2 + nx * width / 2, y2 + ny * width / 2);
+            path.lineTo(x2, y2);
+        }
+    }
+
+}
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java
new file mode 100644 (file)
index 0000000..a78bec0
--- /dev/null
@@ -0,0 +1,24 @@
+/*******************************************************************************
+ * 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.diagram.connection.rendering;
+
+import java.awt.RenderingHints.Key;
+
+public final class ConnectionRenderingHints {
+
+    public static final Key KEY_PATH_MODIFIER = new Key(0) {
+        @Override
+        public boolean isCompatibleValue(Object val) {
+            return val == null || val instanceof PathModifier;
+        }
+    };
+}
\ No newline at end of file
diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java
new file mode 100644 (file)
index 0000000..50d771a
--- /dev/null
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.diagram.connection.rendering;
+
+import java.awt.geom.Path2D;
+
+public interface PathModifier {
+       public Path2D modify(Path2D source);
+}
index dd9473042152d0c3af43244d9549d63e4c649e4b..fa14474691f281ad312df693dec50e242bdb9503 100644 (file)
@@ -62,6 +62,10 @@ public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializab
 
                path.reset();
                rg.getPath2D(path);
+               PathModifier pm = (PathModifier) g.getRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER);
+               if (pm != null) {
+                       path = pm.modify(path);
+               }
                style.drawPath(g, path, false);
 
                branchPoints.clear();
index b26bfc698ee214ac9040b7228d2fe0a13c59b334..6ea207f88d754cd59825b9c2e533fadc6190cb4a 100644 (file)
@@ -68,6 +68,9 @@ DIA.IOTableRename <T L0.Entity
 DIA.Diagram <T DIA.Composite
     >-- DIA.Diagram.IOTableRenaming --> DIA.IOTableRename <T L0.DependsOn 
     @L0.optionalProperty DIA.HasModCount
+    @L0.assert DIA.ConnectionCrossingStyle ""
+    @L0.assert DIA.ConnectionCrossingStyle.Width 0.0
+    @L0.assert DIA.ConnectionCrossingStyle.HasType DIA.ConnectionCrossingStyle.Type.None
 
 DIA.HasModCount <R L0.HasProperty : L0.FunctionalRelation
     L0.HasLabel "Modification Counter"
@@ -143,4 +146,31 @@ DIA.diagramActivityCondition : L0.Template
 
 DIA.ProfileEntryContribution <T L0.Entity
   --> DIA.ProfileEntryContribution.HasEntry --> DIA.ProfileEntry <R L0.IsRelatedTo  
-                
\ No newline at end of file
+
+DIA.ConnectionCrossingStyle <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Connection Crossing Style"
+    SEL.HasDisplayValue ""
+    L0.readOnly true
+    SEL.canBeLifted false
+
+DIA.ConnectionCrossingStyle.Width <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Width"
+    L0.HasDescription "Width of connection crossings."
+    L0.HasDomain DIA.Diagram
+    L0.HasRange L0.Double
+    SEL.IsShownUnder DIA.ConnectionCrossingStyle
+
+DIA.ConnectionCrossingStyle.HasType <R L0.HasProperty : L0.FunctionalRelation : SEL.GenericParameterType
+    L0.HasLabel "Type"
+    L0.HasDescription "Type of connection crossings."
+    L0.HasDomain DIA.Diagram
+    L0.HasRange DIA.ConnectionCrossingStyle.Type
+    SEL.IsShownUnder DIA.ConnectionCrossingStyle
+
+DIA.ConnectionCrossingStyle.Type <T L0.Value
+    @L0.tag L0.Enumeration
+
+DIA.ConnectionCrossingStyle.Type.Arc : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.Square : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.Gap : DIA.ConnectionCrossingStyle.Type
+DIA.ConnectionCrossingStyle.Type.None : DIA.ConnectionCrossingStyle.Type
\ No newline at end of file
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)
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectionCrossingsParticipant.java
new file mode 100644 (file)
index 0000000..10949ca
--- /dev/null
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * 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.diagram.participant;
+
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.request.UnaryRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.procedure.Listener;
+import org.simantics.diagram.connection.rendering.ConnectionCrossings;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.SGDesignation;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGCleanup;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.scenegraph.g2d.nodes.ConnectionCrossingsNode;
+import org.simantics.utils.datastructures.Pair;
+import org.simantics.utils.ui.ErrorLogger;
+
+public class ConnectionCrossingsParticipant extends AbstractDiagramParticipant {
+    private static final String CONNECTION_CROSSINGS_NODE_KEY = "connection-crossings";
+
+    private ConnectionCrossingsNode ccNode;
+    private final ConnectionCrossings crossings = new ConnectionCrossings();
+    private ConnectionCrossingStyleListener listener;
+    private Resource diagram;
+    
+    public ConnectionCrossingsParticipant(Resource diagram) {
+        this.diagram = diagram;
+    }
+    public ConnectionCrossingsParticipant(double width, ConnectionCrossings.Type type) {
+        crossings.setWidth(width);
+        crossings.setType(type);
+    }
+
+    @SGInit(designation = SGDesignation.CONTROL)
+    public void initSG(G2DParentNode parent) {
+        ccNode = parent.addNode(CONNECTION_CROSSINGS_NODE_KEY, ConnectionCrossingsNode.class);
+        ccNode.setCrossings(crossings);
+        ccNode.setZIndex(Integer.MIN_VALUE / 4);
+    }
+
+    @SGCleanup
+    public void cleanupSG() {
+        if (ccNode != null) {
+            ccNode.remove();
+            ccNode = null;
+        }
+    }
+
+    @Override
+    public void addedToContext(ICanvasContext ctx) {
+        super.addedToContext(ctx);
+
+        if (diagram != null) {
+            listener = new ConnectionCrossingStyleListener(ctx);
+            Simantics.getSession().async(new UnaryRead<Resource, Pair<Double, ConnectionCrossings.Type>>(diagram){
+    
+                @Override
+                public Pair<Double, ConnectionCrossings.Type> perform(ReadGraph graph) throws DatabaseException {
+                    DiagramResource DIA = DiagramResource.getInstance(graph);
+                    Double gap = graph.getPossibleRelatedValue(diagram, DIA.ConnectionCrossingStyle_Width);
+                    Resource typeRes = graph.getPossibleObject(diagram, DIA.ConnectionCrossingStyle_HasType);
+                    ConnectionCrossings.Type type;
+                    if (DIA.ConnectionCrossingStyle_Type_Gap.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.GAP;
+                    } else if (DIA.ConnectionCrossingStyle_Type_Arc.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.ARC;
+                    } else if (DIA.ConnectionCrossingStyle_Type_Square.equals(typeRes)) {
+                        type = ConnectionCrossings.Type.SQUARE;
+                    } else { 
+                        type = ConnectionCrossings.Type.NONE;
+                    }
+                    return new Pair<>(gap, type);
+                }
+                
+            }, listener);
+        }
+    }
+
+    @Override
+    public void removedFromContext(ICanvasContext ctx) {
+        if (listener != null) {
+            listener.dispose();
+            listener = null;
+        }
+        super.removedFromContext(ctx);
+    }
+
+    class ConnectionCrossingStyleListener implements Listener<Pair<Double, ConnectionCrossings.Type>> {
+        ICanvasContext context;
+        public ConnectionCrossingStyleListener(ICanvasContext context) {
+            this.context = context;
+        }
+        @Override
+        public void execute(final Pair<Double, ConnectionCrossings.Type> result) {
+            context.getThreadAccess().asyncExec(new Runnable() {
+                @Override
+                public void run() {
+                    ICanvasContext ctx = context;
+                    if (ctx == null)
+                        return;
+                    if (ctx.isDisposed())
+                        return;
+                    crossings.setWidth(result.first != null ? result.first : 0.0);
+                    crossings.setType(result.second);
+                    ccNode.repaint();
+                }
+            });
+        }
+        public void dispose() {
+            context = null;
+        }
+        @Override
+        public boolean isDisposed() {
+            return context == null || context.isDisposed();
+        }
+        @Override
+        public void exception(Throwable t) {
+            ErrorLogger.defaultLogError(t);
+        }
+    }
+
+}
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();
+                                    }
                                 }
                             }
                         }
diff --git a/bundles/org.simantics.graphfile.ui.ontology/.classpath b/bundles/org.simantics.graphfile.ui.ontology/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.simantics.graphfile.ui.ontology/.project b/bundles/org.simantics.graphfile.ui.ontology/.project
new file mode 100644 (file)
index 0000000..740f3f8
--- /dev/null
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.graphfile.ui.ontology</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.simantics.graph.builder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+               <nature>org.simantics.graph.nature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF b/bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..05c3405
--- /dev/null
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: http://www.simantics.org/GraphFileUI
+Bundle-SymbolicName: org.simantics.graphfile.ui.ontology
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.simantics.graphfile.ui.ontology
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.simantics.modeling.ontology;bundle-version="1.2.0",
+ org.simantics.silk.ontology;bundle-version="1.1.0",
+ org.simantics.layer0;bundle-version="1.1.0",
+ org.simantics.viewpoint.ontology;bundle-version="1.2.0",
+ org.simantics.action.ontology;bundle-version="1.1.0",
+ org.simantics.graphfile.ontology;bundle-version="0.1.0"
diff --git a/bundles/org.simantics.graphfile.ui.ontology/build.properties b/bundles/org.simantics.graphfile.ui.ontology/build.properties
new file mode 100644 (file)
index 0000000..e85b630
--- /dev/null
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               graph.tg
diff --git a/bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph b/bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph
new file mode 100644 (file)
index 0000000..196296e
--- /dev/null
@@ -0,0 +1,48 @@
+L0 = <http://www.simantics.org/Layer0-1.1>
+MOD = <http://www.simantics.org/Modeling-1.2>
+SILK = <http://www.simantics.org/Silk-1.1>
+VP = <http://www.simantics.org/Viewpoint-1.2>
+ACT = <http://www.simantics.org/Action-1.1>
+GF = <http://www.simantics.org/GraphFile-0.1>
+
+GFUI = <http://www.simantics.org/GraphFileUI-1.0> : L0.Ontology
+    @L0.new
+    L0.HasResourceClass "org.simantics.graphfile.ui.ontology.GraphFileUIResource" : L0.String
+
+GFUI.BrowseContext : VP.BrowseContext
+
+ACTIONS = GFUI.BrowseContext.Actions : L0.Library
+
+ACTIONS.ImportFileDocument : ACT.Action
+ACTIONS.ImportDocumentFolder : ACT.Action
+ACTIONS.NewFileDocument : ACT.Action
+ACTIONS.NewDocumentFolder : ACT.Action
+ACTIONS.ExportFileDocument : ACT.Action
+ACTIONS.ExportDocumentFolder : ACT.Action
+
+GFUI.ModelingBrowseContext : VP.BrowseContext
+    VP.BrowseContext.IsIncludedIn MOD.ModelingBrowseContext
+    @VP.relationChildRule    L0.Library     L0.ConsistsOf    GF.Folder
+    @VP.relationChildRule    L0.Library     L0.ConsistsOf    GF.File
+    @VP.relationChildRule    GF.Folder      L0.ConsistsOf    GF.File
+    @VP.relationChildRule    GF.Folder      L0.ConsistsOf    GF.Folder
+
+    @VP.constantImageRule    GF.Folder      SILK.folder_page
+    @VP.constantImageRule    GF.File        SILK.page_white
+    @VP.customLabelRule      GF.File        VP.ResourceNameLabelRule
+
+GFUI.ModelingActionContext : VP.BrowseContext
+    VP.BrowseContext.IsIncludedIn MOD.ModelingActionContext
+    @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder
+    @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder
+    @VP.actionContribution "File" L0.Library SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument
+    @VP.actionContribution "File" GF.Folder SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument
+
+    @VP.actionContribution "Files" L0.Library SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument
+    @VP.actionContribution "Files" GF.Folder SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument
+
+    @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder
+    @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder
+
+    @VP.actionContribution "File" GF.File SILK.page_white VP.ExportActionCategory ACTIONS.ExportFileDocument
+    @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ExportActionCategory ACTIONS.ExportDocumentFolder
\ No newline at end of file
diff --git a/bundles/org.simantics.graphfile.ui/.classpath b/bundles/org.simantics.graphfile.ui/.classpath
new file mode 100644 (file)
index 0000000..eca7bdb
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src"/>
+       <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/bundles/org.simantics.graphfile.ui/.project b/bundles/org.simantics.graphfile.ui/.project
new file mode 100644 (file)
index 0000000..7533101
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.simantics.graphfile.ui</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF b/bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF
new file mode 100644 (file)
index 0000000..6c0a381
--- /dev/null
@@ -0,0 +1,13 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: GraphfileUI
+Bundle-SymbolicName: org.simantics.graphfile.ui;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Automatic-Module-Name: org.simantics.graphfile.ui
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Require-Bundle: org.eclipse.ui.editors,
+ org.simantics.ui,
+ org.eclipse.jface.text;bundle-version="3.12.0",
+ org.simantics.graphfile.ontology,
+ org.slf4j.api;bundle-version="1.7.25",
+ org.simantics.document.ui;bundle-version="1.0.0"
diff --git a/bundles/org.simantics.graphfile.ui/adapters.xml b/bundles/org.simantics.graphfile.ui/adapters.xml
new file mode 100644 (file)
index 0000000..6eceb37
--- /dev/null
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Copyright (c) 2013, 2014 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 THTH Simantics 
+    Division Member Component License which accompanies this 
+    distribution, and is available at
+    http://www.simantics.org/legal/sdmcl-v10.html
+    
+    Contributors:
+        Semantum Oy - initial API and implementation
+ -->
+
+<adapters>
+    <target interface="org.simantics.db.layer0.adapter.ActionFactory">
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ImportFileDocument"
+            class="org.simantics.document.ui.actions.ImportDocument">
+            <graph/>
+            <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+        </resource>
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ImportDocumentFolder"
+            class="org.simantics.document.ui.actions.ImportDocumentFolder">
+            <graph/>
+            <string>http://www.simantics.org/GraphFile-0.0/Folder</string>
+            <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+        </resource>
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/NewFileDocument"
+            class="org.simantics.document.ui.actions.NewFileDocument">
+            <graph/>
+            <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+            <string>File</string>            
+        </resource>
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/NewDocumentFolder"
+            class="org.simantics.document.ui.actions.NewDocumentFolder">
+            <graph/>
+            <string>http://www.simantics.org/GraphFile-0.0/Folder</string>
+            <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+        </resource>
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ExportFileDocument"
+            class="org.simantics.document.ui.actions.ExportDocumentFile" />
+        <resource uri="http://www.simantics.org/GraphFileUI-1.0/BrowseContext/Actions/ExportDocumentFolder"
+            class="org.simantics.document.ui.actions.ExportDocumentFolder">
+            <graph/>
+            <string>http://www.simantics.org/Layer0-0.0/ConsistsOf</string>
+            <string>false</string>
+        </resource>
+    </target>
+
+</adapters>
\ No newline at end of file
diff --git a/bundles/org.simantics.graphfile.ui/build.properties b/bundles/org.simantics.graphfile.ui/build.properties
new file mode 100644 (file)
index 0000000..2df8c94
--- /dev/null
@@ -0,0 +1,6 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+               .,\
+               plugin.xml,\
+               adapters.xml
diff --git a/bundles/org.simantics.graphfile.ui/plugin.xml b/bundles/org.simantics.graphfile.ui/plugin.xml
new file mode 100644 (file)
index 0000000..925a7f3
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+   <extension
+         point="org.eclipse.ui.editors">
+      <editor
+            default="false"
+            name="Text Editor"
+            icon="platform:/plugin/com.famfamfam.silk/icons/page_white.png"
+            class="org.simantics.graphfile.ui.editor.PlainTextEditor"
+            id="org.simantics.graphfile.ui.editor.plaintexteditor">
+      </editor>
+   </extension>
+   
+   <extension
+         point="org.simantics.ui.resourceEditorAdapter">
+      <adapter
+            label="Text Editor"
+            priority="11"
+            editorId="org.simantics.graphfile.ui.editor.plaintexteditor"
+            type_uris="http://www.simantics.org/Document-0.0/FileDocument">
+      </adapter>
+   </extension>
+</plugin>
diff --git a/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java
new file mode 100644 (file)
index 0000000..d30210f
--- /dev/null
@@ -0,0 +1,92 @@
+package org.simantics.graphfile.ui.editor;
+
+import java.util.function.Supplier;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.editors.text.TextEditor;
+import org.simantics.Simantics;
+import org.simantics.db.Session;
+import org.simantics.db.common.request.ParametrizedRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.combinations.Combinators;
+import org.simantics.ui.workbench.IResourceEditorInput;
+import org.simantics.ui.workbench.ResourceEditorSupport;
+import org.simantics.ui.workbench.TitleRequest;
+import org.simantics.ui.workbench.TitleUpdater;
+import org.simantics.ui.workbench.ToolTipRequest;
+import org.simantics.ui.workbench.editor.input.InputValidationCombinators;
+
+/**
+ * @author Antti Villberg
+ */
+public class PlainTextEditor extends TextEditor {
+
+    boolean isDisposed = false;
+
+    ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =
+            Combinators.compose(
+                    InputValidationCombinators.hasURI(),
+                    InputValidationCombinators.extractInputResource()
+            );
+
+    ResourceEditorSupport support;
+
+    public PlainTextEditor() {
+        super();
+        setDocumentProvider(new PlainTextEditorDocumentProvider());
+        //setSourceViewerConfiguration(new QueueTextEditorViewerConfiguration(new QueueTextEditorColorManager()));
+    }
+
+    @Override
+    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+        super.init(site, input);
+
+        support = new ResourceEditorSupport(this, INPUT_VALIDATOR);
+        support.activateValidation();
+        try {
+            getResourceEditorInput().init(null);
+        } catch (DatabaseException e) {
+            throw new PartInitException("Failed to initialize " + input, e);
+        }
+    }
+
+    protected IResourceEditorInput getResourceEditorInput() {
+        return (IResourceEditorInput) getEditorInput();
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        super.createPartControl(parent);
+        updatePartName();
+    }
+
+    private void updatePartName() {
+        setPartName(getEditorInput().getName());
+
+        Session session = Simantics.peekSession();
+        if (session != null) {
+            Supplier<Boolean> disposedCallback = () -> isDisposed;
+            session.asyncRequest(
+                    new TitleRequest(null, getResourceEditorInput()),
+                    new TitleUpdater(getSite().getShell().getDisplay(), this::setPartName, disposedCallback));
+            session.asyncRequest(
+                    new ToolTipRequest(getSite().getId(), getResourceEditorInput()),
+                    new TitleUpdater(getSite().getShell().getDisplay(), this::setTitleToolTip, disposedCallback));
+        }
+
+    }
+
+    @Override
+    public void dispose() {
+        isDisposed = true;
+        if (support != null) {
+            support.dispose();
+            support = null;
+        }
+        super.dispose();
+    }
+
+}
diff --git a/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java
new file mode 100644 (file)
index 0000000..3eb40ea
--- /dev/null
@@ -0,0 +1,108 @@
+package org.simantics.graphfile.ui.editor;
+
+import java.io.StringWriter;
+import java.nio.charset.StandardCharsets;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.operation.IRunnableContext;
+import org.eclipse.jface.text.Document;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.source.AnnotationModel;
+import org.eclipse.jface.text.source.IAnnotationModel;
+import org.eclipse.ui.texteditor.AbstractDocumentProvider;
+import org.simantics.Simantics;
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.document.DocumentResource;
+import org.simantics.graphfile.ontology.GraphFileResource;
+import org.simantics.ui.workbench.ResourceEditorInput;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PlainTextEditorDocumentProvider extends AbstractDocumentProvider {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PlainTextEditor.class);
+
+    protected String currentText;
+
+    @Override
+    protected IDocument createDocument(Object element) throws CoreException {
+        ResourceEditorInput input = (ResourceEditorInput)element;
+        final Resource resource = input.getResource();
+        try {
+            return Simantics.getSession().syncRequest(new UniqueRead<Document>() {
+                @Override
+                public Document perform(ReadGraph graph) throws DatabaseException {
+                    
+                    GraphFileResource GF = GraphFileResource.getInstance(graph);
+                    DocumentResource DOC = DocumentResource.getInstance(graph);
+                    if (!graph.isInstanceOf(resource, DOC.FileDocument))
+                        throw new DatabaseException("Invalid input resource for PlainTextEditor: " + NameUtils.getSafeName(graph, resource));
+
+                    byte[] bytes = graph.getPossibleRelatedValue(resource, GF.HasFiledata, Bindings.BYTE_ARRAY);
+                    
+                    currentText = bytes != null ? new String(bytes, StandardCharsets.UTF_8) : "";
+                    
+                    return new Document(currentText);
+                    
+                }
+            });
+        } catch (DatabaseException e) {
+            StringWriter sw = new StringWriter();
+            LOGGER.error("Failed to create document", e);
+            return new Document(sw.toString());
+        }
+    }
+
+    @Override
+    protected IAnnotationModel createAnnotationModel(Object element)
+            throws CoreException {
+        return new AnnotationModel();
+    }
+
+    @Override
+    protected void doSaveDocument(IProgressMonitor monitor, Object element,
+            IDocument document, boolean overwrite) throws CoreException {
+        ResourceEditorInput input = (ResourceEditorInput)element;
+        final Resource resource = input.getResource();
+        final String text = document.get();
+        currentText = text;
+        Simantics.getSession().asyncRequest(new WriteRequest() {
+            @Override
+            public void perform(WriteGraph graph) throws DatabaseException {
+                graph.markUndoPoint();
+                GraphFileResource GF = GraphFileResource.getInstance(graph);
+                graph.claimLiteral(resource, GF.HasFiledata, text.getBytes(StandardCharsets.UTF_8));
+                graph.claimLiteral(resource, GF.LastModified, System.currentTimeMillis());
+            }
+        });
+    }
+
+    @Override
+    protected IRunnableContext getOperationRunner(IProgressMonitor monitor) {
+        return null;
+    }
+    
+    @Override
+    public boolean isModifiable(Object element) {
+        return true;
+    }
+    
+    @Override
+    public boolean isReadOnly(Object element) {
+        return false;
+    }
+    
+    @Override
+    public boolean canSaveDocument(Object element) {
+        return !getDocument(element).get().equals(currentText);
+    }
+
+}
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 409aecbea26dc04ef73d9851b5fa31f9eb0eb234..489ebd6c700a65a6dd7e70dcf8a42d6c9e93a2eb 100644 (file)
@@ -67,6 +67,7 @@ import org.simantics.diagram.handler.DeleteHandler;
 import org.simantics.diagram.handler.ExpandSelectionHandler;
 import org.simantics.diagram.handler.SimpleElementTransformHandler;
 import org.simantics.diagram.layer.ILayersViewPage;
+import org.simantics.diagram.participant.ConnectionCrossingsParticipant;
 import org.simantics.diagram.participant.ContextUtil;
 import org.simantics.diagram.participant.PointerInteractor2;
 import org.simantics.diagram.participant.SGFocusParticipant;
@@ -330,6 +331,7 @@ public class DiagramViewer
         //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
         //ctx.add(new TooltipParticipant());
         ctx.add(new TerminalTooltipParticipant());
+        ctx.add(new ConnectionCrossingsParticipant(getInputResource()));
     }
 
     protected void addPainterParticipants(ICanvasContext ctx) {
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 1db2ba151c972dccd2c52bd5f92e95d40c2a73bf..8f223a62285bbf6892240019deea73d6ed68a31b 100644 (file)
@@ -35,6 +35,7 @@ import org.simantics.diagram.handler.CopyPasteStrategy;
 import org.simantics.diagram.handler.DefaultCopyPasteStrategy;
 import org.simantics.diagram.handler.DeleteHandler;
 import org.simantics.diagram.handler.SimpleElementTransformHandler;
+import org.simantics.diagram.participant.ConnectionCrossingsParticipant;
 import org.simantics.diagram.query.DiagramRequests;
 import org.simantics.diagram.runtime.RuntimeDiagramManager;
 import org.simantics.diagram.stubs.DiagramResource;
@@ -249,6 +250,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi
         ctx.add( new Selection() );
         ctx.add( new DiagramParticipant() );
         ctx.add( new ElementPainter(true) );
+        ctx.add( new ConnectionCrossingsParticipant(resource));
 
         //ctx.add( new ElementHeartbeater() );
         ctx.add( new ZOrderHandler() );
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 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 5bb3d9ca21c95d30bb5d96200d41caade8bf59df..e058f2c36fed2fb0ba8d6753c5fd47a244aa4963 100644 (file)
@@ -5,7 +5,9 @@ import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 
 import org.simantics.Simantics;
@@ -32,17 +34,48 @@ public class DumpOntologyStructure {
     private Resource ontology;
 
     private Map<Resource, String> names = new HashMap<>();
-    private Map<Resource,Resource> parents = new HashMap<>();
+    private Map<Resource,Resource> parents = new TreeMap<>();
     private Map<Resource, File> libraryFolders = new HashMap<>();
     private Map<Resource, byte[]> contentDumps = new HashMap<>();
 
     private void readNameAndParent(ReadGraph graph, Resource container, Resource r) throws DatabaseException {
+        String name = NameUtils.getSafeName(graph, r);
         parents.put(r, container);
-        names.put(r, NameUtils.getSafeName(graph, r));
+        names.put(r, FileUtils.escapeFileName(name));
     }
 
-    private Collection<Resource> containers() {
-        return parents.values();
+    /*
+     * This shall return containers sorted by full path.
+     * This makes processing order stable and ensures that
+     * directories are processed before their contents. 
+     */
+    private Collection<Resource> sortedContainers(File rootFolder) {
+        Set<Resource> parentSet = new HashSet<Resource>(parents.values());
+        TreeMap<String,Resource> result = new TreeMap<>();
+        for(Resource r : parentSet) {
+            File f = getFolder(rootFolder, r);
+            result.put(f.getAbsolutePath(), r);
+        }
+        return result.values();
+    }
+
+    private Collection<Resource> sortedResources(File rootFolder) {
+        TreeMap<String,Resource> result = new TreeMap<>();
+        for(Resource r : parents.keySet()) {
+            byte[] dump = contentDumps.get(r);
+            if(dump == null)
+                dump = "".getBytes(StandardCharsets.UTF_8);
+            if(isParent(r)) {
+                if(dump.length > 0) {
+                    File f = new File(getFolder(rootFolder, r), "__contents__");
+                    result.put(f.getAbsolutePath(), r);
+                }
+            } else {
+                File f = getFile(rootFolder, r);
+                result.put(f.getAbsolutePath(), r);
+            }
+        }
+        return result.values();
     }
 
     private void readHierarchy(ReadGraph graph, Resource container) throws DatabaseException {
@@ -110,37 +143,56 @@ public class DumpOntologyStructure {
     public void write(File unsafeFolder) throws IOException {
         File folder = escapeFile(unsafeFolder);
         FileUtils.delete(folder.toPath());
-        folder.mkdirs();
+        folder.getParentFile().mkdirs();
         writeDirectories(folder);
         writeResources(folder);
     }
 
+    Resource getParent(Resource r) {
+        return parents.get(r);
+    }
+    
     private File getFolder(File root, Resource library) {
         if(ontology.equals(library))
             return root;
-        Resource parent = parents.get(library);
+        Resource parent = getParent(library);
         if(parent == null)
             throw new IllegalStateException("null parent for " + library);
         File parentFolder = getFolder(root, parent);
-        return new File(parentFolder, FileUtils.escapeFileName(names.get(library))); 
+        return new File(parentFolder, names.get(library)); 
     }
 
     private File getFile(File rootFolder, Resource r) {
-        Resource parent = parents.get(r);
+        Resource parent = getParent(r);
         File folder = getFolder(rootFolder, parent);
-        return new File(folder, FileUtils.escapeFileName(names.get(r)));
+        return new File(folder, names.get(r));
     }
 
+    private File makeUnique(File original, Resource r) {
+        int counter = 2;
+        File file = new File(original.getParent(), original.getName());
+        File test = file;
+        while(test.exists()) {
+            // Here we have a name clash with small and big letters! (windows)
+            test = new File(file.getParent(), file.getName() + "____" + (counter++));
+        }
+        // Enforce this renaming in future operations also
+        names.put(r, test.getName());
+        return test;
+    }
+    
     private void writeDirectories(File rootFolder) {
-        for(Resource library : containers()) {
-            File folder = getFolder(rootFolder, library);
+        // Here stuff shall be returned in alphabetical order
+        for(Resource library : sortedContainers(rootFolder)) {
+            File folder = makeUnique(getFolder(rootFolder, library), library);
             folder.mkdirs();
             libraryFolders.put(library, folder);
         }
     }
 
     private void writeResources(File rootFolder) throws IOException {
-        for(Resource r : parents.keySet()) {
+        // Here stuff shall be returned in alphabetical order
+        for(Resource r : sortedResources(rootFolder)) {
             writeResource(rootFolder, r);
         }
     }
@@ -162,7 +214,7 @@ public class DumpOntologyStructure {
     }
 
     private void write(File rootFolder, Resource resource, byte[] bytes) throws IOException {
-        FileUtils.writeFile(getFile(rootFolder, resource), bytes);
+        FileUtils.writeFile(makeUnique(getFile(rootFolder, resource), resource), bytes);
     }
 
 }
\ No newline at end of file
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java
new file mode 100644 (file)
index 0000000..a46c4e7
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ * 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.scenegraph.g2d.nodes;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Rectangle2D;
+
+import org.simantics.diagram.connection.rendering.ConnectionCrossings;
+import org.simantics.diagram.connection.rendering.ConnectionRenderingHints;
+import org.simantics.scenegraph.g2d.G2DNode;
+
+public class ConnectionCrossingsNode extends G2DNode {
+
+    private static final long serialVersionUID = -696142275610396889L;
+
+    private ConnectionCrossings crossings;
+    
+    @Override
+    public void render(Graphics2D g) {
+        crossings.reset();
+        if (crossings.getWidth() > 0 && crossings.getType() != ConnectionCrossings.Type.NONE)  {
+            g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, crossings);
+        } else {
+            g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, null);
+        }
+    }
+    
+    public void setCrossings(ConnectionCrossings crossings) {
+        this.crossings = crossings;
+    }
+
+    @Override
+    public Rectangle2D getBoundsInLocal() {
+        return null;
+    }
+    
+    public ConnectionCrossings getConnectionCrossings() {
+        return crossings;
+    }
+}
index a14be489618d659c6bf394405bce1e2d8868ac04..4e1d01816381d3ca486bae5b558f07f9af5cb7b2 100644 (file)
@@ -1,14 +1,11 @@
 package org.simantics.scl.reflection.internal;
 
-import java.util.concurrent.ForkJoinPool;
-
 import org.eclipse.core.runtime.ILog;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.simantics.scl.reflection.internal.registry.BindingRegistry;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -23,21 +20,6 @@ public class Activator implements BundleActivator {
     public void start(BundleContext context) throws Exception {
         this.context = context;
         instance = this;
-        
-        primeBindingRegistry();
-    }
-
-    private static void primeBindingRegistry() {
-        LOGGER.info("Priming BindingRegistry");
-        ForkJoinPool.commonPool().submit(() -> {
-            try {
-                // this forces static initialzation of the registry in advance
-                BindingRegistry.primeBindingRegistry();
-            } catch (Exception e) {
-                LOGGER.error("Could not prime binding registry", e);
-            }
-            LOGGER.info("Priming done");
-        });
     }
 
     @Override
index 648e314d9a2f95c9dc659615514f0133c1efbf64..f9bf3fadcc9aa3bfa47155909949d136dfe3796a 100644 (file)
@@ -49,12 +49,6 @@ public class BindingRegistry {
         }
     }
     
-    public static void primeBindingRegistry() {
-        for (Namespace ns : namespaces.values()) {
-            ns.initializeValues();
-        }
-    }
-    
     static {
         initialize();
         if (DEBUG_INIT) {
index 5234d3bfc95ab456f61ceff4c5e06e134ddeaab7..daaa204dbe708c971969ba65a3ef68bb73390651 100644 (file)
@@ -275,7 +275,7 @@ public class Namespace {
         }
     }        
         
-    synchronized void initializeValues() {
+    private synchronized void initializeValues() {
         if(values == null) {
             initializeTypes();
             TypeBindingScheme scheme = MinimalTypeBindingScheme.INSTANCE;
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 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 59e88c12b6a83843b1a69dbd2cb2766cc5bdbec2..e1abeaf48ddda6e493620ac7ac0a5d120c3665a4 100644 (file)
                <module>org.simantics.graph.db</module>
                <module>org.simantics.graphfile</module>
                <module>org.simantics.graphfile.ontology</module>
+               <module>org.simantics.graphfile.ui</module>
+               <module>org.simantics.graphfile.ui.ontology</module>
                <module>org.simantics.graphviz</module>
                <module>org.simantics.graphviz.ui</module>
                <module>org.simantics.gnuplot</module>
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>