From: Tuukka Lehtonen Date: Tue, 7 Apr 2020 09:00:26 +0000 (+0000) Subject: Merge "Revert "Prime SCL BindingRegistry to shave ~0.5s from startup"" X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=035118aa5f35c9e5acd1f34d22065055dfdee486;hp=91e878ce39c9db112d658b3236f29a13e12724e6 Merge "Revert "Prime SCL BindingRegistry to shave ~0.5s from startup"" --- diff --git a/.mvn/extensions.xml b/.mvn/extensions.xml index 3b43bdfdd..e73295bbd 100644 --- a/.mvn/extensions.xml +++ b/.mvn/extensions.xml @@ -3,6 +3,6 @@ org.eclipse.tycho.extras tycho-pomless - 1.5.0 + 1.6.0 diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartCopyHandler.java b/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartCopyHandler.java index 65108d6f7..183000045 100644 --- a/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartCopyHandler.java +++ b/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartCopyHandler.java @@ -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 index 000000000..0cc582024 --- /dev/null +++ b/bundles/org.simantics.charts/src/org/simantics/charts/editor/ChartPreferencesAction.java @@ -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 index 000000000..5771b1421 --- /dev/null +++ b/bundles/org.simantics.charts/src/org/simantics/charts/editor/Messages.java @@ -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() { + } +} diff --git a/bundles/org.simantics.charts/src/org/simantics/charts/editor/TimeSeriesEditor.java b/bundles/org.simantics.charts/src/org/simantics/charts/editor/TimeSeriesEditor.java index bffd4c8a2..ad718e49e 100644 --- a/bundles/org.simantics.charts/src/org/simantics/charts/editor/TimeSeriesEditor.java +++ b/bundles/org.simantics.charts/src/org/simantics/charts/editor/TimeSeriesEditor.java @@ -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 index 000000000..37bbe90f6 --- /dev/null +++ b/bundles/org.simantics.charts/src/org/simantics/charts/editor/messages.properties @@ -0,0 +1 @@ +ChartPreferencesAction_ChartPreferences=Chart Preferences diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java index e9523c0c8..dfb5780f9 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/MergingGraphRequestProcessor.java @@ -33,7 +33,6 @@ import org.simantics.db.common.procedure.adapter.SyncMultiProcedureAdapter; import org.simantics.db.common.procedure.wrapper.NoneToAsyncProcedure; import org.simantics.db.common.request.ReadRequest; import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.CancelTransactionException; import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.AsyncListener; @@ -63,9 +62,13 @@ import org.simantics.db.request.WriteOnlyResult; import org.simantics.db.request.WriteResult; import org.simantics.utils.DataContainer; import org.simantics.utils.datastructures.Pair; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class MergingGraphRequestProcessor implements AsyncRequestProcessor { + private static final Logger LOGGER = LoggerFactory.getLogger(MergingGraphRequestProcessor.class); + private static class SyncWriteRequestAdapter implements Write { private Semaphore semaphore = new Semaphore(0); @@ -128,7 +131,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { try { semaphore.acquire(); } catch (InterruptedException e) { - Logger.defaultLogError(e); + LOGGER.error("SyncWriteRequestAdapter interrupted", e); } } @@ -223,7 +226,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { try { MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod); } catch (InterruptedException e) { - Logger.defaultLogError(e); + LOGGER.error("MergedRead interrupted", e); } if (requestQueue.isEmpty()) break; @@ -262,7 +265,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { } catch(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("MergedRead failed", t); // if(currentRequest.second instanceof AsyncProcedure) { // ((AsyncProcedure)currentRequest.second).exception(graph, t); @@ -281,7 +284,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { } else { - try{ + try { if(currentRequest.second instanceof AsyncProcedure) { if(currentRequest.first instanceof AsyncRead) { @@ -298,7 +301,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { } catch(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("MergedRead failed", t); // if(currentRequest.second instanceof AsyncProcedure) { // ((AsyncProcedure)currentRequest.second).exception(graph, t); @@ -355,7 +358,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { try { MergingGraphRequestProcessor.this.wait(transactionKeepalivePeriod); } catch (InterruptedException e) { - Logger.defaultLogError(e); + LOGGER.error("RunnerWriteGraphRequest interrupted", e); } if (requestQueue.isEmpty()) break; @@ -385,7 +388,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { graph.syncRequest(adapter); if(callback != null) callback.accept(null); } catch(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("RunnerWriteGraphRequest failed", t); if(callback != null) callback.accept(t); } @@ -399,7 +402,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { else if(currentRequest.first instanceof DelayedWrite) graph.syncRequest((DelayedWrite)currentRequest.first); if(callback != null) callback.accept(null); } catch(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("RunnerWriteGraphRequest failed", t); if(callback != null) callback.accept(t); } @@ -572,7 +575,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { Throwable t = throwable.get(); if(t != null) { - Logger.defaultLogError(t); + LOGGER.error("syncRequest(AsyncMultiRead, AsyncMultiProcedure) failed", t); throw new RuntimeException(t.getMessage()); } @@ -625,7 +628,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { Throwable t = throwable.get(); if(t != null) { - Logger.defaultLogError(t); + LOGGER.error("syncRequest(AsyncRead, AsyncProcedure) failed", t); throw new RuntimeException(t.getMessage()); } @@ -691,7 +694,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { @Override public void exception(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("asyncRequest(AsyncRead) failed", t); } }); @@ -736,7 +739,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { Throwable t = throwable.get(); if(t != null) { - Logger.defaultLogError(t); + LOGGER.error("syncRequest(AsyncRead) failed", t); throw new RuntimeException(t.getMessage()); } @@ -775,7 +778,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { Throwable t = throwable.get(); if(t != null) { - Logger.defaultLogError(t); + LOGGER.error("syncRequest(AsyncMultiRead) failed", t); throw new RuntimeException(t.getMessage()); } @@ -878,7 +881,7 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { @Override public void exception(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("asyncRequest(Read) failed", t); } }); @@ -1305,4 +1308,9 @@ public class MergingGraphRequestProcessor implements AsyncRequestProcessor { throw new UnsupportedOperationException(); } + @Override + public T l0() { + return processor.l0(); + } + } diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/ProcessorBase.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/ProcessorBase.java index 1f00ff008..f47ebb3f3 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/ProcessorBase.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/processor/ProcessorBase.java @@ -46,6 +46,11 @@ import org.simantics.db.request.WriteResult; public class ProcessorBase implements AsyncRequestProcessor { + @Override + public T l0() { + throw new UnsupportedOperationException(); + } + @Override public void asyncRequest(AsyncMultiRead request, AsyncMultiProcedure procedure) { throw new UnsupportedOperationException(); diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java index b3eba37fb..aeea33f02 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/request/AdaptValue.java @@ -14,7 +14,7 @@ import org.simantics.scl.runtime.function.FunctionImpl3; * @author Hannu Niemistö */ public class AdaptValue extends ResourceRead { - + public AdaptValue(Resource resource) { super(resource); } @@ -31,14 +31,14 @@ public class AdaptValue extends ResourceRead { } }; - + @Override public Object perform(ReadGraph graph) throws DatabaseException { - String uri = graph.getURI(resource); - if(Layer0.URIs.Functions_functionApplication.equals(uri)) return functionApplication; + Layer0 L0 = graph.l0(); + if (L0.Functions_functionApplication.equalsResource(resource)) + return functionApplication; ComputationalValue ev = graph.adapt(resource, ComputationalValue.class); return ev.getValue(graph, resource); - } } diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/request/TransientResourceRead.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/request/TransientResourceRead.java index 117a1a27f..73e612a9f 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/request/TransientResourceRead.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/request/TransientResourceRead.java @@ -19,37 +19,41 @@ import org.simantics.db.service.QueryControl; abstract public class TransientResourceRead extends BinaryRead implements ReadExt { - protected static final Object WITH_PARENT = new Object(); - - public TransientResourceRead(ReadGraph graph, Resource parameter) throws DatabaseException { - this(graph, graph.getService(QueryControl.class), parameter); - } - - public TransientResourceRead(ReadGraph graph, QueryControl qc, Resource parameter) throws DatabaseException { - super(resolveFirstParameter(graph, qc), parameter); - } - - final private static Object resolveFirstParameter(ReadGraph graph, QueryControl qc) throws DatabaseException { - if(qc.hasParentRequest(graph)) return WITH_PARENT; - else return graph.getModificationCounter(); - } - - @Override - final public R perform(ReadGraph _graph) throws DatabaseException { - if(parameter == WITH_PARENT) { - return perform(_graph, parameter2); - } else { - QueryControl qc = _graph.getService(QueryControl.class); - ReadGraph graph = qc.getIndependentGraph(_graph); - return perform(graph, parameter2); - } - } - - abstract public R perform(ReadGraph graph, Resource parameter) throws DatabaseException; - - @Override - public boolean isImmutable(ReadGraph graph) throws DatabaseException { - return graph.isImmutable(parameter2); - } - + protected static final Object WITH_PARENT = new Object(); + + public TransientResourceRead(ReadGraph graph, Resource parameter) throws DatabaseException { + this(graph, graph.getService(QueryControl.class), parameter); + } + + public TransientResourceRead(ReadGraph graph, QueryControl qc, Resource parameter) throws DatabaseException { + super(resolveFirstParameter(graph, qc), parameter); + } + + final private static Object resolveFirstParameter(ReadGraph graph, QueryControl qc) throws DatabaseException { + if(qc.hasParentRequest(graph)) return WITH_PARENT; + else return graph.getModificationCounter(); + } + + @Override + final public R perform(ReadGraph _graph) throws DatabaseException { + if(parameter == WITH_PARENT) { + return perform(_graph, parameter2); + } else { + QueryControl qc = _graph.getService(QueryControl.class); + return qc.syncRequestIndependent(_graph, new UniqueRead() { + @Override + public R perform(ReadGraph graph) throws DatabaseException { + return TransientResourceRead.this.perform(graph, parameter2); + } + }); + } + } + + abstract public R perform(ReadGraph graph, Resource parameter) throws DatabaseException; + + @Override + public boolean isImmutable(ReadGraph graph) throws DatabaseException { + return graph.isImmutable(parameter2); + } + } diff --git a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java index 143d3e443..8e8171f85 100644 --- a/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java +++ b/bundles/org.simantics.db.common/src/org/simantics/db/common/utils/OrderedSetUtils.java @@ -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 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. */ diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java index 8f96bb9e6..9f89a0d8f 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/BlockingAsyncProcedure.java @@ -19,34 +19,31 @@ import org.simantics.db.impl.query.AsyncReadEntry; import org.simantics.db.impl.query.PendingTaskSupport; import org.simantics.db.procedure.AsyncProcedure; import org.simantics.db.request.AsyncRead; -public class BlockingAsyncProcedure implements AsyncProcedure { + +public class BlockingAsyncProcedure implements AsyncProcedure, Runnable { private static final Object NO_RESULT = new Object(); private final Object key; private final ReadGraphImpl queryGraph; private final ReadGraphImpl callerGraph; + private final AsyncReadEntry entry; private final AsyncProcedure procedure; private PendingTaskSupport pendingTaskSupport; private final boolean needsToBlock; private Object result = NO_RESULT; private Throwable exception = null; - - private ReadGraphImpl queryGraph() { - return queryGraph; - } public BlockingAsyncProcedure(ReadGraphImpl callerGraph, AsyncReadEntry entry, AsyncProcedure procedure, Object key, boolean needsToBlock) { // A new graph for evaluating the query with correct parent and asyncBarrier - queryGraph = callerGraph.withParent(entry, () -> { - - dispatchProcedure(queryGraph(), callerGraph, entry, procedure, needsToBlock); - - }, needsToBlock); - + queryGraph = callerGraph.withParent(entry, this, needsToBlock); queryGraph.asyncBarrier.inc(); + + // This makes sure that caller does not quit before dispatch + callerGraph.asyncBarrier.inc(); + this.entry = entry; this.procedure = procedure; this.key = key; this.queryGraph.asyncBarrier.inc(); @@ -112,34 +109,39 @@ public class BlockingAsyncProcedure implements AsyncProcedure { return "." + procedure; } - private void dispatchProcedure(ReadGraphImpl queryGraph, ReadGraphImpl parentGraph, AsyncReadEntry entry, AsyncProcedure procedure_, boolean needsToBlock) { + @Override + public void run() { - AsyncProcedure procedure = entry != null ? entry : procedure_; + AsyncProcedure procedure__ = entry != null ? entry : procedure; - ReadGraphImpl executeGraph = parentGraph.withParent(parentGraph.parent, null, needsToBlock); + ReadGraphImpl executeGraph = callerGraph.withParent(callerGraph.parent, null, needsToBlock); executeGraph.asyncBarrier.inc(); + + // This counters the inc in the constructor + callerGraph.asyncBarrier.dec(); + try { - if(procedure != null) { - procedure.execute(executeGraph, get()); + if(procedure__ != null) { + procedure__.execute(executeGraph, get()); } } catch (DatabaseException e) { - if(procedure != null) procedure.exception(executeGraph, e); + if(procedure__ != null) procedure__.exception(executeGraph, e); exception = e; } catch (Throwable t) { DatabaseException dbe = new DatabaseException(t); - if(procedure != null) procedure.exception(executeGraph, dbe); + if(procedure__ != null) procedure__.exception(executeGraph, dbe); exception = dbe; } finally { if (entry != null) { assert(entry.isReady()); // This does not throw - entry.performFromCache(executeGraph, procedure_); + entry.performFromCache(executeGraph, procedure); } executeGraph.asyncBarrier.dec(); if(needsToBlock) - executeGraph.asyncBarrier.waitBarrier(procedure, executeGraph); + executeGraph.asyncBarrier.waitBarrier(procedure__, executeGraph); } if (BarrierTracing.BOOKKEEPING) { diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/AsyncBarrierImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/AsyncBarrierImpl.java index 637db3f26..f1e5b5cce 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/AsyncBarrierImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/AsyncBarrierImpl.java @@ -14,13 +14,15 @@ package org.simantics.db.impl.graph; import java.util.Collection; import java.util.concurrent.atomic.AtomicInteger; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.RuntimeDatabaseException; import org.simantics.db.impl.query.CacheEntry; import org.simantics.db.impl.query.QueryProcessor.AsyncBarrier; +import org.slf4j.LoggerFactory; public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(AsyncBarrierImpl.class); + private static final long serialVersionUID = 4724463372850048672L; static final int WAIT_TIME = 60000; @@ -107,7 +109,7 @@ public class AsyncBarrierImpl extends AtomicInteger implements AsyncBarrier { } } if (count < 0) { - Logger.defaultLogError( + LOGGER.error( "Database request processing error. The application code has performed illegal actions (probably called multiple times the execute or exception method of a single result request.", new Exception()); } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java index 48662d190..27336b23d 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java @@ -188,8 +188,6 @@ import org.simantics.utils.DataContainer; import org.simantics.utils.Development; import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.collections.CollectionUtils; -import org.simantics.utils.threads.logger.ITask; -import org.simantics.utils.threads.logger.ThreadLogger; import org.slf4j.LoggerFactory; import gnu.trove.map.hash.TObjectIntHashMap; @@ -1513,15 +1511,15 @@ public class ReadGraphImpl implements AsyncReadGraph { try { - int result = processor.getSingleObject(this, subject, relation); - if(result == 0) return null; - - return processor.querySupport.getResource(result); + int result = processor.getSingleObject(this, subject, relation); + if(result == 0) return null; + + return processor.querySupport.getResource(result); - } catch (ManyObjectsForFunctionalRelationException e) { + } catch (ManyObjectsForFunctionalRelationException e) { + + throw new ManyObjectsForFunctionalRelationException("Many objects in " + subject + " for functional relation " + relation); - throw new ManyObjectsForFunctionalRelationException("subject=" + subject + ", relation=" + relation, e); - } catch (DatabaseException e) { throw new ServiceException(e); @@ -1922,14 +1920,11 @@ public class ReadGraphImpl implements AsyncReadGraph { * Implementation of the interface RequestProcessor */ - @Override - public T syncRequest(final Read request) throws DatabaseException { - assert (request != null); - - T result = (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true); - return result; - - } + @Override + public T syncRequest(final Read request) throws DatabaseException { + assert (request != null); + return (T)QueryCache.runnerReadEntry(this, request, parent, null, null, true); + } @Override public T syncRequest(Read request, SyncListener procedure) @@ -1943,16 +1938,12 @@ public class ReadGraphImpl implements AsyncReadGraph { return syncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - public T syncRequest(final Read request, final AsyncProcedure procedure) throws DatabaseException { - - assert (request != null); - - ListenerBase listener = procedure != null ? getListenerBase(procedure) : null; - T result = (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true); - return result; - - } + @Override + public T syncRequest(final Read request, final AsyncProcedure procedure) throws DatabaseException { + assert (request != null); + ListenerBase listener = procedure != null ? getListenerBase(procedure) : null; + return (T)QueryCache.runnerReadEntry(this, request, parent, listener, procedure, true); + } @Override public T syncRequest(final Read request, @@ -2028,17 +2019,13 @@ public class ReadGraphImpl implements AsyncReadGraph { return syncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public T syncRequest(final AsyncRead request, - final AsyncProcedure procedure) throws DatabaseException { - - assert (request != null); - - ListenerBase listener = getListenerBase(procedure); - T result = (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); - return result; - - } + @Override + final public T syncRequest(final AsyncRead request, + final AsyncProcedure procedure) throws DatabaseException { + assert (request != null); + ListenerBase listener = getListenerBase(procedure); + return (T)QueryCache.runnerAsyncReadEntry(this, request, parent, listener, procedure, true); + } @Override public T syncRequest(AsyncRead request, @@ -5235,54 +5222,55 @@ public class ReadGraphImpl implements AsyncReadGraph { asyncRequest(request, new NoneToAsyncListener(procedure)); } - @Override - final public void asyncRequest(final AsyncRead request, - final AsyncProcedure procedure) { + @Override + final public void asyncRequest(final AsyncRead request, + final AsyncProcedure procedure) { - assert (request != null); - assert (procedure != null); + assert (request != null); + assert (procedure != null); AsyncBarrierImpl barrier = asyncBarrier; if(barrier != null) barrier.inc(); - processor.scheduleNow(new SessionTask(this) { + processor.scheduleNow(new SessionTask(this) { - @Override - public void run0(int thread) { + @Override + public void run0(int thread) { - if(barrier != null) - barrier.inc(); + if(barrier != null) + barrier.inc(); - try { - final ListenerBase listener = getListenerBase(procedure); - QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure() { + try { + final ListenerBase listener = getListenerBase(procedure); + QueryCache.runnerAsyncReadEntry(ReadGraphImpl.this, request, parent, listener, new AsyncProcedure() { - @Override - public void execute(AsyncReadGraph graph, T result) { - procedure.execute(graph, result); - if(barrier != null) - barrier.dec(); - } + @Override + public void execute(AsyncReadGraph graph, T result) { + procedure.execute(graph, result); + if(barrier != null) + barrier.dec(); + } - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - procedure.exception(graph, throwable); + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + procedure.exception(graph, throwable); if(barrier != null) barrier.dec(); - } - - }, false); - if(barrier != null) - barrier.dec(); - } catch (DatabaseException e) { - Logger.defaultLogError(e); - } - } - - }); + } + + }, false); + } catch (DatabaseException e) { + LOGGER.error("Error while executing async request", e); + } finally { + if(barrier != null) + barrier.dec(); + } + } - } + }); + + } @Override public void asyncRequest(AsyncRead request, @@ -6399,4 +6387,10 @@ public class ReadGraphImpl implements AsyncReadGraph { else return getTopLevelGraphStatic(impl.parentGraph); } + @SuppressWarnings("unchecked") + @Override + public T l0() { + return (T) processor.getL0(); + } + } diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/WriteGraphImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/WriteGraphImpl.java index 0c4e68138..8cb1688fb 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/WriteGraphImpl.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/WriteGraphImpl.java @@ -14,10 +14,13 @@ package org.simantics.db.impl.graph; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; +import java.util.IdentityHashMap; +import java.util.Map; import java.util.TreeMap; import java.util.function.Consumer; import org.simantics.databoard.Bindings; +import org.simantics.databoard.Datatypes; import org.simantics.databoard.accessor.Accessor; import org.simantics.databoard.binding.Binding; import org.simantics.databoard.binding.error.BindingConstructionException; @@ -31,7 +34,16 @@ import org.simantics.databoard.primitives.MutableLong; import org.simantics.databoard.primitives.MutableString; import org.simantics.databoard.serialization.SerializationException; import org.simantics.databoard.serialization.Serializer; +import org.simantics.databoard.type.ArrayType; +import org.simantics.databoard.type.BooleanType; +import org.simantics.databoard.type.ByteType; import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.DoubleType; +import org.simantics.databoard.type.FloatType; +import org.simantics.databoard.type.IntegerType; +import org.simantics.databoard.type.LongType; +import org.simantics.databoard.type.StringType; +import org.simantics.databoard.type.VariantType; import org.simantics.databoard.util.binary.RandomAccessBinary; import org.simantics.db.DevelopmentKeys; import org.simantics.db.ExternalValueSupport; @@ -69,8 +81,6 @@ import org.simantics.layer0.Layer0; import org.simantics.utils.Development; import org.simantics.utils.datastructures.Pair; -import gnu.trove.map.hash.THashMap; - final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph { @@ -683,7 +693,7 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph { } - THashMap, Resource> builtinValues = new THashMap, Resource>(32); + Map builtinValues = new IdentityHashMap<>(40); private void initBuiltinValues(Layer0 b) { @@ -714,6 +724,76 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph { builtinValues.put(MutableByte.class, b.Byte); builtinValues.put(MutableBoolean.class, b.Boolean); + builtinValues.put(Datatypes.DOUBLE, b.Double); + builtinValues.put(Datatypes.STRING, b.String); + builtinValues.put(Datatypes.INTEGER, b.Integer); + builtinValues.put(Datatypes.LONG, b.Long); + builtinValues.put(Datatypes.FLOAT, b.Float); + builtinValues.put(Datatypes.BYTE, b.Byte); + builtinValues.put(Datatypes.BOOLEAN, b.Boolean); + builtinValues.put(Datatypes.VARIANT, b.Variant); + + builtinValues.put(Datatypes.DOUBLE_ARRAY, b.DoubleArray); + builtinValues.put(Datatypes.STRING_ARRAY, b.StringArray); + builtinValues.put(Datatypes.INTEGER_ARRAY, b.IntegerArray); + builtinValues.put(Datatypes.LONG_ARRAY, b.LongArray); + builtinValues.put(Datatypes.FLOAT_ARRAY, b.FloatArray); + builtinValues.put(Datatypes.BYTE_ARRAY, b.ByteArray); + builtinValues.put(Datatypes.BOOLEAN_ARRAY, b.BooleanArray); + builtinValues.put(Datatypes.VARIANT_ARRAY, b.VariantArray); + } + + private static Datatype canonicalizeToBuiltinDatatype(Datatype datatype) { + if (datatype instanceof ArrayType) { + ArrayType at = (ArrayType) datatype; + datatype = at.componentType(); + if (datatype instanceof ByteType) { + return Datatypes.BYTE_ARRAY; + } else if (datatype instanceof DoubleType) { + return Datatypes.DOUBLE_ARRAY; + } else if (datatype instanceof FloatType) { + return Datatypes.FLOAT_ARRAY; + } else if (datatype instanceof IntegerType) { + return Datatypes.INTEGER_ARRAY; + } else if (datatype instanceof LongType) { + return Datatypes.LONG_ARRAY; + } else if (datatype instanceof BooleanType) { + return Datatypes.BOOLEAN_ARRAY; + } else if (datatype instanceof StringType) { + return Datatypes.STRING_ARRAY; + } else if (datatype instanceof VariantType) { + return Datatypes.VARIANT_ARRAY; + } + return null; + } + if (datatype instanceof ByteType) { + return Datatypes.BYTE; + } else if (datatype instanceof DoubleType) { + return Datatypes.DOUBLE; + } else if (datatype instanceof FloatType) { + return Datatypes.FLOAT; + } else if (datatype instanceof IntegerType) { + return Datatypes.INTEGER; + } else if (datatype instanceof LongType) { + return Datatypes.LONG; + } else if (datatype instanceof BooleanType) { + return Datatypes.BOOLEAN; + } else if (datatype instanceof StringType) { + return Datatypes.STRING; + } else if (datatype instanceof VariantType) { + return Datatypes.VARIANT; + } + return null; + } + + private Resource resolveBuiltinResourceType(Class valueClass, Datatype datatype) { + Resource type = builtinValues.get(valueClass); + return type != null ? type : builtinValues.get(datatype); + } + + private Resource resolveBuiltinResourceTypeByCanonicalizedDatatype(Datatype datatype, Resource defaultResult) { + Datatype cdt = canonicalizeToBuiltinDatatype(datatype); + return cdt != null ? builtinValues.get(cdt) : defaultResult; } @Override @@ -734,13 +814,13 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph { initBuiltinValues(b); Resource literal = newResource(); - Class clazz = value.getClass(); - Resource type = builtinValues.get(clazz); + Datatype dt = binding.type(); + Resource type = resolveBuiltinResourceType(value.getClass(), dt); if (type == null) { - type = b.Literal; + type = resolveBuiltinResourceTypeByCanonicalizedDatatype(dt, b.Literal); Resource dataType = newResource(); claim(dataType, b.InstanceOf, null, b.DataType); - claimValue(dataType, binding.type(), DATA_TYPE_BINDING); + claimValue(dataType, dt, DATA_TYPE_BINDING); claim(literal, b.HasDataType, b.HasDataType_Inverse, dataType); } @@ -805,14 +885,14 @@ final public class WriteGraphImpl extends ReadGraphImpl implements WriteGraph { } else { - Class clazz = value.getClass(); - Resource type = builtinValues.get(clazz); Resource literal = newResource(); + Datatype dt = binding.type(); + Resource type = resolveBuiltinResourceType(value.getClass(), dt); if (type == null) { - type = b.Literal; + type = resolveBuiltinResourceTypeByCanonicalizedDatatype(dt, b.Literal); Resource dataType = newResource(); claim(dataType, b.InstanceOf, null, b.DataType); - claimValue(dataType, binding.type(), DATA_TYPE_BINDING); + claimValue(dataType, dt, DATA_TYPE_BINDING); claim(literal, b.HasDataType, null, dataType); } claim(literal, b.InstanceOf, null, type); diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java index f74344b2f..8bac42263 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Objects.java @@ -37,569 +37,566 @@ import org.simantics.db.request.RequestFlags; public final class Objects extends CollectionBinaryQuery 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 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 NOP = new InternalProcedure() { + final static InternalProcedure NOP = new InternalProcedure() { - @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() { + @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() { - 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 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 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() { + @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 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 { diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java index dd410b4ce..91200f1fc 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryListening.java @@ -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 consumer; private final Map addedEntries = new HashMap<>(); private THashSet scheduledListeners = new THashSet(); @@ -46,210 +42,11 @@ public class QueryListening { final THashMap> listeners = new THashMap>(10, 0.75f); - private static class ThreadQueue extends ThreadLocal> { - - private final Map> allQueues = new HashMap<>(); - - private ArrayList> dispatchedQueues = new ArrayList<>(); - - @Override - protected synchronized ArrayList initialValue() { - ArrayList result = new ArrayList<>(); - allQueues.put(Thread.currentThread(), result); - return result; - } - - synchronized void sendToExecution() { - ArrayList rs = allQueues.remove(Thread.currentThread()); - dispatchedQueues.add(rs); - notify(); - } - - synchronized ArrayList> getDispatchedQueues() { - ArrayList> 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 newConsumer() { - return (task) -> { - - ArrayList 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> qs = queues.getDispatchedQueues(); - for(ArrayList queue : qs) { - for(Runnable r : queue) - r.run(); - } - if(flush != null) { - for(ArrayList 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.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 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.getProperty(DevelopmentKeys.QUERYPROCESSOR_LISTENERS, Bindings.BOOLEAN)) { - new Exception().printStackTrace(); - System.err.println("addListener -> " + list.size() + " " + entry + " " + base + " " + procedure); - } - } - - queryListening.addedEntries.put(base, result); - - } - - - } QueryListening(QueryProcessor processor) { this.processor = processor; scheduler = new Scheduler(processor); - consumer = scheduler.newConsumer(); scheduler.start(); } @@ -260,7 +57,7 @@ public class QueryListening { void sync() { try { - scheduler.flush(); + scheduler.sync(); } catch (Throwable t) { LOGGER.error("Error while waiting for query dependency management", t); } @@ -276,7 +73,7 @@ public class QueryListening { if(parent != null) { try { if(!child.isImmutable(graph)) - consumer.accept(new RegisterParentRunnable(parent, child)); + scheduler.accept(new RegisterParentRunnable(parent, child)); } catch (DatabaseException e) { LOGGER.error("Error while registering query dependencies", e); } @@ -284,7 +81,7 @@ public class QueryListening { if(listener != null) if(!listener.isDisposed()) - consumer.accept(new RegisterListenerRunnable(this, listener, procedure, parent, child)); + scheduler.accept(new RegisterListenerRunnable(this, listener, procedure, parent, child)); } @@ -292,10 +89,7 @@ public class QueryListening { if(base == null) return; - consumer.accept(() -> { - ListenerEntry entry = addedEntries.get(base); - if(entry != null) entry.setLastKnown(result); - }); + scheduler.accept(new RegisterFirstKnownRunnable(addedEntries, base, result)); } @@ -413,7 +207,7 @@ public class QueryListening { } - public void fireListeners(WriteGraphImpl graph) { + public void fireListeners(ReadGraphImpl graph) { assert (!processor.updating); assert (!processor.cache.collecting); @@ -529,5 +323,102 @@ public class QueryListening { else return Collections.emptyList(); } - + + private static class RegisterParentRunnable implements Runnable { + + private final CacheEntry parent; + private final CacheEntry child; + + public RegisterParentRunnable(CacheEntry parent, CacheEntry child) { + this.parent = parent; + this.child = child; + } + + @Override + public void run() { + child.addParent(parent); + if (Development.DEVELOPMENT) { + if(Development.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 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.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 addedEntries; + private final ListenerBase base; + private final Object result; + + public RegisterFirstKnownRunnable(Map 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/QueryProcessor.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java index a46bc0e8d..6d9560940 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/QueryProcessor.java @@ -1279,8 +1279,9 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap entry.prepareRecompute(querySupport); ReadGraphImpl parentGraph = graph.forRecompute(entry); - + parentGraph.asyncBarrier.inc(); query.recompute(parentGraph); + parentGraph.asyncBarrier.dec(); if(entry.isExcepted()) return ListenerEntry.NO_VALUE; @@ -4053,6 +4054,10 @@ final public class QueryProcessor extends AbstractDisposable implements ReadGrap return L0; } + public Layer0 getL0() { + return L0; + } + public static ThreadLocal thread = new ThreadLocal() { protected Integer initialValue() { return -1; diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Scheduler.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Scheduler.java new file mode 100644 index 000000000..2c9c47574 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Scheduler.java @@ -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 { + + 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 dispatchedTaskLists; + + /* + * This replicates the ThreadLocal map of TaskList objects to enable listing of tasks active queues + */ + private final Map 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(); + 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 getDispatchedQueues() { + synchronized(taskDispatchMonitor) { + if(dispatchedTaskLists == null) + return null; + ArrayList 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 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 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 diff --git a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java index 6652f1b6b..218777413 100644 --- a/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/Statements.java @@ -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 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 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 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 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 NOP = new InternalProcedure() { - @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() { - + @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 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 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 }); } - + } 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 } 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 final IntArray value = (IntArray)getResult(); for(int i=0;i>>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 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 index 000000000..7734bae77 --- /dev/null +++ b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/query/TaskList.java @@ -0,0 +1,24 @@ +package org.simantics.db.impl.query; + +import java.util.ArrayList; + +class TaskList extends ArrayList { + + 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 diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ContextualRelatedValue.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ContextualRelatedValue.java index 517ce761e..6ad6315b9 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ContextualRelatedValue.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/adapter/ContextualRelatedValue.java @@ -27,41 +27,43 @@ import org.simantics.scl.runtime.function.FunctionImpl3; */ public abstract class ContextualRelatedValue implements ConverterComputationalValue { - @SuppressWarnings("unchecked") - @Override - public T getValue(ReadGraph graph, Resource resource) throws DatabaseException { - return (T) new FunctionImpl3() { - @Override - public Object apply(ReadGraph graph, Resource converter, Object context) { - SCLContext sclContext = SCLContext.getCurrent(); - Object oldGraph = sclContext.get("graph"); - try { - if (context instanceof Variable) { - Variable variable = (Variable)context; - try { - Function1 fn = getFunction(graph, variable.getParent(graph).getRepresents(graph), variable.getRepresents(graph), variable.getPredicateResource(graph)); - sclContext.put("graph", graph); - return fn.apply(variable); - } catch (DatabaseException e) { - throw new RuntimeDatabaseException(e); - } - } if (context instanceof Resource) { - Resource resource = (Resource)context; - try { - // Here converter is the object and context is the subject - Function1 fn = getFunction(graph, resource, converter, null); - return fn.apply(resource); - } catch (DatabaseException e) { - throw new RuntimeDatabaseException(e); - } - } else { - throw new IllegalStateException("Unknown context " + context); + private final FunctionImpl3 function = new FunctionImpl3() { + @Override + public Object apply(ReadGraph graph, Resource converter, Object context) { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); + try { + if (context instanceof Variable) { + Variable variable = (Variable)context; + try { + Function1 fn = getFunction(graph, variable.getParent(graph).getRepresents(graph), variable.getRepresents(graph), variable.getPredicateResource(graph)); + sclContext.put("graph", graph); + return fn.apply(variable); + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + } if (context instanceof Resource) { + Resource resource = (Resource)context; + try { + // Here converter is the object and context is the subject + Function1 fn = getFunction(graph, resource, converter, null); + return fn.apply(resource); + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); } - } finally { - sclContext.put("graph", oldGraph); + } else { + throw new IllegalStateException("Unknown context " + context); } + } finally { + sclContext.put("graph", oldGraph); } - }; + } + }; + + @SuppressWarnings("unchecked") + @Override + public T getValue(ReadGraph graph, Resource resource) throws DatabaseException { + return (T) function; } } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java index 4e775e08a..671810d8e 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java @@ -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 = ""; - 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 = ""; + return label; + } + } } - + if (variable.isAsserted()) { - if (variable.parentResource != null) { - Map> 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 assertion : assertions.values()) { - if (assertion.first.predicate.equals(variable.property.predicate)) { - return graph.getValue2(assertion.second, variable); - } - } - } - } + if (variable.parentResource != null) { + Map> 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 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> 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 assertion : assertions.values()) { - if (assertion.first.predicate.equals(variable.property.predicate)) { - return graph.getValue2(assertion.second, variable, binding); - } - } - } - } - } - - return graph.getValue2(variable.getRepresents(graph), context, binding); - - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DatabaseException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } - - public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - - final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node + + if (variable.isAsserted()) { + if (variable.parentResource != null) { + Map> 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 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 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 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 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 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 getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - // Get properties with null identification + // Get properties with null identification return getStandardChildDomainPropertyVariables(graph, context, null, map); } public static Map getStandardChildDomainPropertyVariables(ReadGraph graph, Variable context, String classification, Map map) throws DatabaseException { - + StandardGraphChildVariable variable = (StandardGraphChildVariable)context; - + Collection nodeProperties = getPossibleNodeProperties(graph, variable); if(!nodeProperties.isEmpty()) { // Get variables for properties read from the graph Map graphProperties = collectPropertyInfosFromContext(graph, variable, variable.resource); - + Set used = new THashSet(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 predicates = graph.getPredicates(variable.resource); + if(predicates.isEmpty()) return map; + + map = ensureVariableMap(map, predicates.size()); - // Only graph properties - Collection 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.instance());// : - //graph.syncRequest(new PropertyInfoRequest(predicate)); - if(!info.isHasProperty) continue; - + PropertyInfo info = //graph.isImmutable(predicate) ? + graph.syncRequest(new PropertyInfoRequest(predicate), TransientCacheAsyncListener.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 getVariables(ReadGraph graph, Variable context, Map 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 getVariables(ReadGraph graph, Variable context, Map 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 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 getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - Variable parent = context.getParent(graph); - Resource container = parent.getPossibleRepresents(graph); - if(container == null) - return Collections.emptyMap(); - Map methods = graph.syncRequest(new UnescapedMethodMapOfResource(container)); - for(Map.Entry 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 getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map 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 getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map 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 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 getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + Variable parent = context.getParent(graph); + Resource container = parent.getPossibleRepresents(graph); + if(container == null) + return Collections.emptyMap(); + Map methods = graph.syncRequest(new UnescapedMethodMapOfResource(container)); + for(Map.Entry 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 getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, Map 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 getStandardPropertyDomainPropertyVariablesFromValue(ReadGraph graph, Variable context, String classification, Map 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.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 getVariables(ReadGraph graph, Variable context, Map 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 getVariables(ReadGraph graph, Variable context, String classification, Map 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.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 getVariables(ReadGraph graph, Variable context, Map 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 getVariables(ReadGraph graph, Variable context, String classification, Map 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 graphChildren = graph.syncRequest(new UnescapedChildMapOfResource(resource)); return graphChildren.get(name); } public static Map 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 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 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 getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); } @Deprecated public static Map getStandardChildDomainChildVariables(ReadGraph graph, Variable context, Map graphChildren, Map 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 getStandardNodeChildVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - AbstractVariable variable = (AbstractVariable)context; - if (variable.node == null) return map; - + AbstractVariable variable = (AbstractVariable)context; + if (variable.node == null) return map; + Collection nodeChildren = getPossibleNodeChildren(graph, variable); if (nodeChildren.isEmpty()) return map; - + map = ensureVariableMap(map, nodeChildren.size()); for(Object nodeChild : nodeChildren) { String name = getNodeName(variable, nodeChild); if (!map.containsKey(name)) - map.put(name, createStandardGraphChildVariable(variable, nodeChild)); + map.put(name, createStandardGraphChildVariable(variable, nodeChild)); } return map; @@ -866,368 +871,371 @@ public class All { * @throws DatabaseException */ public static Map getStandardNodePropertyVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { - AbstractVariable variable = (AbstractVariable)context; - if (variable.node == null) return map; - + AbstractVariable variable = (AbstractVariable)context; + if (variable.node == null) return map; + Collection 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 getVariables(ReadGraph graph, Variable context, Map map) throws DatabaseException { + return StandardChildDomainChildren.getStandardChildDomainChildVariables(graph, context, map); + } - @Override - public Map getVariables(ReadGraph graph, Variable context, Map 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 getVariables(ReadGraph graph, Variable context, Map 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 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 getVariables(ReadGraph graph, Variable context, Map 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 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.instance()); // return graph.syncRequest(new PossibleRelatedValueImplied2(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(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 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(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 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 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 p = info.subliteralPredicates.get(name); + if(p == null) return null; + + return new SubliteralPropertyVariable(graph, variable, p.first, p.second); + } public static Map 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.>instance()) : - graph.syncRequest(new UnescapedPropertyMapOfResource(context)); - } - - public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map map) throws DatabaseException { - - Map properties = graph.isImmutable(context) ? - graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>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 collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map 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> entry : info.subliteralPredicates.entrySet()) { - String key = entry.getKey(); - Pair p = entry.getValue(); - if(map == null) map = new THashMap(); - map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second)); - } - - return map; - - } - - public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map map) throws DatabaseException { - - if(graph.isImmutable(context)) { - - Map properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>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(); - map.put(name, v); - } - - } - - } else { - - Collection 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.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(); - map.put(name, v); - } - - } - - } - - return map; - - } - + return graph.isImmutable(context) ? + graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>instance()) : + graph.syncRequest(new UnescapedPropertyMapOfResource(context)); + } + + public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, Map map) throws DatabaseException { + + Map properties = graph.isImmutable(context) ? + graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>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 collectSubliteralProperties(ReadGraph graph, StandardGraphPropertyVariable variable, Map 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> entry : info.subliteralPredicates.entrySet()) { + String key = entry.getKey(); + Pair p = entry.getValue(); + if(map == null) map = new THashMap(); + map.put(key, new SubliteralPropertyVariable(graph, variable, p.first, p.second)); + } + + return map; + + } + + public static Map collectPropertiesFromContext(ReadGraph graph, Variable variable, Resource context, String classification, Map map) throws DatabaseException { + + if(graph.isImmutable(context)) { + + Map properties = graph.syncRequest(new UnescapedPropertyMapOfResource(context), TransientCacheAsyncListener.>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(); + map.put(name, v); + } + + } + + } else { + + Collection 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.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(); + 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 standardClassifications(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - ArrayList result = new ArrayList(); - 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 result = new ArrayList(); + Resource predicate = context.getParent(graph).getPossiblePredicateResource(graph); + if(predicate != null) { + for(Resource type : graph.getTypes(predicate)) { + String uri = graph.getPossibleURI(type); + if(uri != null) result.add(uri); + } + } + return result; } @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") public static Boolean standardValidValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.TRUE; + return Boolean.TRUE; } @SCLValue(type = "ReadGraph -> Resource -> a -> StringInputValidator") public static StringInputValidator standardValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return StringInputValidator.PASS; + return StringInputValidator.PASS; } @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") public static Boolean standardRequiredValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.FALSE; + return Boolean.FALSE; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> Boolean") public static Boolean standardDefaultValue(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - Variable property = context.getParent(graph); - if(property instanceof StandardGraphPropertyVariable) { - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property; - if (variable.parentResource != null) { - Statement stm = graph.getPossibleStatement(variable.parentResource, variable.property.predicate); - return stm != null && stm.isAsserted(variable.parentResource); - } - } - return Boolean.FALSE; + Variable property = context.getParent(graph); + if(property instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property; + if (variable.parentResource != null) { + Resource predicate = variable.getPossiblePredicateResource(graph); + if (predicate != null) { + Statement stm = graph.getPossibleStatement(variable.parentResource, predicate); + return stm != null && stm.isAsserted(variable.parentResource); + } + } + } + return Boolean.FALSE; } @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.FALSE; + return Boolean.FALSE; } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return resource; + return resource; } - + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Functions.exec(graph, resource, graph, resource, context); + return Functions.exec(graph, resource, graph, resource, context); } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { + if(context instanceof Variable) { return CompileValueRequest.compileAndEvaluate(graph, (Variable)context); - } if (context instanceof Resource) { + } if (context instanceof Resource) { return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter); - } else { - throw new IllegalStateException("Unknown context " + context); - } + } else { + throw new IllegalStateException("Unknown context " + context); + } } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { - return new StandardComposedProperty(); - } if (context instanceof Resource) { - return new StandardComposedProperty(); - } else { - throw new IllegalStateException("Unknown context " + context); - } - } - + if(context instanceof Variable) { + return new StandardComposedProperty(); + } if (context instanceof Resource) { + return new StandardComposedProperty(); + } else { + throw new IllegalStateException("Unknown context " + context); + } + } + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - + class Validator extends FunctionImpl1 { private final Datatype datatype; - + public Validator(Datatype datatype) { this.datatype = datatype; } - + @Override public String apply(String input) { - + if(datatype == null) return null; - + try { if(datatype instanceof NumberType) { - + Number number = (Number)PrimitiveValueParser.parse(input, datatype); NumberType nt = (NumberType)datatype; Range r = nt.getRange(); @@ -1236,129 +1244,130 @@ public class All { } } return null; - + } catch (NumberFormatException e) { return "Not a valid floating-point number"; } catch (IllegalArgumentException e) { return "Not a valid floating-point number"; } - + } - + } if(context instanceof Variable) { - + Variable variable = (Variable)context; Variable property = variable.getParent(graph); Datatype datatype = property.getPossibleDatatype(graph); return new Validator(datatype); - + } else if (context instanceof Resource) { Layer0 L0 = Layer0.getInstance(graph); Resource literal = (Resource)context; Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); return new Validator(datatype); - + } else { - + return new Validator(null); - + } - + } - + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - + return new FunctionImpl1() { @Override public String apply(String input) { - - String lower = input.toLowerCase(); - if("true".equals(lower) || "false".equals(lower)) return null; - return "Not a valid boolean: " + input; - + String lower = input.toLowerCase(); + if("true".equals(lower) || "false".equals(lower)) return null; + + return "Not a valid boolean: " + input; + } - + }; - + } @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource") public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - Variable parent = context.getParent(graph); - if(parent instanceof StandardGraphChildVariable) { - StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; - return variable.resource; - } - return null; + Variable parent = context.getParent(graph); + if(parent instanceof StandardGraphChildVariable) { + StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; + return variable.resource; + } + return null; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") - public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); - } - - if (variable.parentResource == null) - throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); - - try { - return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } + public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); + } + + if (variable.parentResource == null) + throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); + + try { + return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } @SCLValue(type = "ReadGraph -> Variable -> Binding -> a") - public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); - } - - if (variable.parentResource == null) - throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph)); - - try { - return graph.getRelatedValue2(variable.parentResource, variable.property.predicate, variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } + public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); + } + + if (variable.parentResource == null) + throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph)); + + + try { + return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b") - public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException { - - Function4 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 modifier = variable.getPossiblePropertyValue(graph, Variables.INPUT_MODIFIER); + if(modifier == null) modifier = VariableUtils.defaultInputModifier; + modifier.apply(graph, variable, value, binding); + return null; + + } + static class L0Issue extends StandardIssue { - + private final String description; - + public L0Issue(String description, Resource type, Resource ... contexts) { super(type, contexts); this.description = description; @@ -1373,63 +1382,63 @@ public class All { graph.addLiteral(issue, L0.HasDescription, L0.HasDescription_Inverse, description, Bindings.STRING); return issue; } - - } - - private static List reportInconsistency(ReadGraph graph, Resource subject, String description, List issues) throws DatabaseException { - if(issues == null) issues = new ArrayList(); - 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 reportInconsistency(ReadGraph graph, Resource subject, String description, List issues) throws DatabaseException { + if(issues == null) issues = new ArrayList(); + 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 relationValidator(ReadGraph graph, Resource resource) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - - List 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 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 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.emptyList(); + Layer0 L0 = Layer0.getInstance(graph); + + List 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 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 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.emptyList(); } @@ -1439,197 +1448,197 @@ public class All { List 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.emptyList(); } - - + + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") public static List valueValidator(ReadGraph graph, Resource resource) throws DatabaseException { List 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.emptyList(); - + } - + @SCLValue(type = "ReadGraph -> Resource -> [Issue]") public static List uriValidator(ReadGraph graph, Resource resource) throws DatabaseException { - + List 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.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 clusterValidator(ReadGraph graph, Resource resource) throws DatabaseException { - if(!Development.DEVELOPMENT) return Collections.emptyList(); - - if(quirks(graph, resource)) return Collections.emptyList(); - + if(!Development.DEVELOPMENT) return Collections.emptyList(); + + if(quirks(graph, resource)) return Collections.emptyList(); + List 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.emptyList(); + // This means that there is no owner since RootLibrary is a cluster set + return Collections.emptyList(); } - + if(!set.equals(nearestSet)) return reportInconsistency(graph, resource, "The cluster set of a resource is not the nearest owner set", issues); return Collections.emptyList(); - + } private static boolean isInstanceOfAny(ReadGraph graph, Resource r, Collection 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 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 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 ensureVariableMap( - Map map, int size) { - if(map == null) map = new THashMap(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 ensureVariableMap( + Map map, int size) { + if(map == null) map = new THashMap(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 { diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java index 0aa36390b..83837a960 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/Dependencies.java @@ -13,13 +13,14 @@ package org.simantics.db.layer0.genericrelation; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.common.utils.Logger; +import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.GenericRelationIndex; import org.simantics.db.service.QueryControl; import org.simantics.operation.Layer0X; import org.simantics.scl.runtime.function.FunctionImpl4; import org.simantics.scl.runtime.function.UnsaturatedFunction2; +import org.slf4j.LoggerFactory; /** * dependencies: @@ -30,6 +31,8 @@ import org.simantics.scl.runtime.function.UnsaturatedFunction2; */ public class Dependencies extends FunctionImpl4 { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(Dependencies.class); + public static final String FIELD_MODEL = "Model"; public static final String FIELD_PARENT = "Parent"; public static final String FIELD_RESOURCE = "Resource"; @@ -71,10 +74,15 @@ public class Dependencies extends FunctionImpl4() { + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + return index.query(graph, query, getBindingPattern(), new Object[] { model }, maxResults); + } + }); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("Error while performing index query", e); return null; } } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyResources.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyResources.java index 1702af0f3..a2059a6ad 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyResources.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyResources.java @@ -13,13 +13,14 @@ package org.simantics.db.layer0.genericrelation; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; -import org.simantics.db.common.utils.Logger; +import org.simantics.db.common.request.UniqueRead; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.adapter.GenericRelationIndex; import org.simantics.db.service.QueryControl; import org.simantics.operation.Layer0X; import org.simantics.scl.runtime.function.FunctionImpl4; import org.simantics.scl.runtime.function.UnsaturatedFunction2; +import org.slf4j.LoggerFactory; /** * dependencyResources: @@ -30,6 +31,8 @@ import org.simantics.scl.runtime.function.UnsaturatedFunction2; */ public class DependencyResources extends FunctionImpl4 { + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(DependencyResources.class); + protected Resource getIndexRelation(ReadGraph graph) { return Layer0X.getInstance(graph).DependenciesRelation; } @@ -61,10 +64,15 @@ public class DependencyResources extends FunctionImpl4() { + @Override + public Object perform(ReadGraph graph) throws DatabaseException { + return index.queryResources(graph, query, getBindingPattern(), new Object[] { model }, maxResults); + } + }); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("Error while performing index query", e); return null; } } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java new file mode 100644 index 000000000..a1b74638f --- /dev/null +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NoPredicateResourceException.java @@ -0,0 +1,34 @@ +package org.simantics.db.layer0.variable; + +import org.simantics.db.Resource; +import org.simantics.db.exception.AssumptionException; + +public class NoPredicateResourceException extends AssumptionException { + + private static final long serialVersionUID = -374051341908276908L; + + public NoPredicateResourceException(Throwable cause) { + super(cause); + } + + public NoPredicateResourceException(String message, Throwable cause, Resource... rs) { + super(message, cause, rs); + } + + public NoPredicateResourceException(String message, Resource... resources) { + super(message, resources); + } + + public NoPredicateResourceException(String message, Throwable cause) { + super(message, cause); + } + + public NoPredicateResourceException(String message, int... args) { + super(message, args); + } + + public NoPredicateResourceException(String message) { + super(message); + } + +} diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java index 2bd089d1e..140ee8fa0 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/NodeValueRequest.java @@ -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, Variant> implements VariableNodeReadRunnable { + private static final Logger LOGGER = LoggerFactory.getLogger(NodeValueRequest.class); + private Listener listener = null; private Variant value = Variables.PENDING_NODE_VALUE; private boolean wasRun = false; static class Probe implements Runnable { - private Pair parameter; - public Variant result; - - public Probe(Pair 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 parameter; + public Variant result; + + public Probe(Pair 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.make(node, null)); } @@ -55,18 +59,18 @@ class NodeValueRequest extends ParametrizedPrimitiveRead 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 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 listener = this.listener; if (listener != null) listener.exception(new DatabaseException("External data access error", e)); diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java index b7eaf075e..c9214e398 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java @@ -21,6 +21,7 @@ import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.DatatypeNotFoundException; import org.simantics.db.exception.ValidationException; import org.simantics.db.layer0.exception.InvalidVariableException; +import org.simantics.db.layer0.exception.MissingVariableException; import org.simantics.db.layer0.exception.MissingVariableValueException; import org.simantics.db.layer0.exception.PendingVariableException; import org.simantics.db.layer0.function.All; @@ -100,11 +101,15 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { @Override public String getPossibleLabel(ReadGraph graph) throws DatabaseException { + if (property.predicate == null) + return null; return graph.getPossibleRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING); } @Override public String getLabel(ReadGraph graph) throws DatabaseException { + if (property.predicate == null) + throw new NoPredicateResourceException("No predicate resource for property " + getName(graph)); return graph.getRelatedValue2(property.predicate, graph.getService(Layer0.class).HasLabel, parent, Bindings.STRING); } @@ -124,10 +129,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { if(Development.DEVELOPMENT) { if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { - String error = L0Validations.checkValueType(graph, parentResource, property.predicate); - if(error != null) { - LOGGER.error(error); - throw new ValidationException(error); + if (property.predicate != null) { + String error = L0Validations.checkValueType(graph, parentResource, property.predicate); + if(error != null) { + LOGGER.error(error); + throw new ValidationException(error); + } } } } @@ -145,10 +152,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { if(Development.DEVELOPMENT) { if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { - String error = L0Validations.checkValueType(graph, parentResource, property.predicate); - if(error != null) { - LOGGER.error(error); - throw new ValidationException(error); + if (property.predicate != null) { + String error = L0Validations.checkValueType(graph, parentResource, property.predicate); + if(error != null) { + LOGGER.error(error); + throw new ValidationException(error); + } } } } @@ -183,10 +192,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { if(Development.DEVELOPMENT) { if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { - String error = L0Validations.checkValueType(graph, parentResource, property.predicate); - if(error != null) { - LOGGER.error(error); - throw new ValidationException(error); + if (property.predicate != null) { + String error = L0Validations.checkValueType(graph, parentResource, property.predicate); + if(error != null) { + LOGGER.error(error); + throw new ValidationException(error); + } } } } @@ -200,10 +211,12 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { if(Development.DEVELOPMENT) { if(Development.getProperty(DevelopmentKeys.L0_VALIDATION, Bindings.BOOLEAN)) { - String error = L0Validations.checkValueType(graph, parentResource, property.predicate); - if(error != null) { - LOGGER.error(error); - throw new ValidationException(error); + if (property.predicate != null) { + String error = L0Validations.checkValueType(graph, parentResource, property.predicate); + if(error != null) { + LOGGER.error(error); + throw new ValidationException(error); + } } } } @@ -324,11 +337,15 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { @Override public Variable getPredicate(ReadGraph graph) throws DatabaseException { + if (property.predicate == null) + throw new MissingVariableException("No predicate for property " + getName(graph)); return Variables.getVariable(graph, graph.getURI(property.predicate)); } @Override public Resource getPredicateResource(ReadGraph graph) throws DatabaseException { + if (property.predicate == null) + throw new NoPredicateResourceException("No predicate for property " + getName(graph)); return property.predicate; } diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java index 341a496a4..218a268a4 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/Variables.java @@ -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 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 getValue1, Function2 getValue2, - Function2 setValue2, Function3 setValue3, - Function1 getDatatype) { - return new SCLValueAccessor(getValue1, getValue2, setValue2, setValue3, getDatatype); - } + + public static ValueAccessor createValueAccessor(Function1 getValue1, Function2 getValue2, + Function2 setValue2, Function3 setValue3, + Function1 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); diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QueryControlImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QueryControlImpl.java index 53a3dc1ad..f5e55deaa 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QueryControlImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/QueryControlImpl.java @@ -13,6 +13,7 @@ import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.procedure.AsyncContextMultiProcedure; import org.simantics.db.procedure.AsyncMultiProcedure; import org.simantics.db.request.ExternalRead; +import org.simantics.db.request.Read; import org.simantics.db.service.QueryControl; import org.simantics.utils.DataContainer; import org.slf4j.Logger; @@ -145,6 +146,17 @@ public class QueryControlImpl implements QueryControl { ReadGraphImpl impl = (ReadGraphImpl)graph; return impl.withParent(null, null, false); } + + @Override + public T syncRequestIndependent(ReadGraph graph, Read request) throws DatabaseException { + ReadGraphImpl independent = ((ReadGraphImpl)graph).withParent(null, null, false); + independent.asyncBarrier.inc(); + try { + return independent.syncRequest(request); + } finally { + independent.asyncBarrier.dec(); + } + } @Override public boolean hasParentRequest(ReadGraph graph) { diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java index 92c5e9dda..0178e805f 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplDb.java @@ -18,7 +18,6 @@ import org.simantics.db.SessionManager; import org.simantics.db.SessionReference; import org.simantics.db.VirtualGraph; import org.simantics.db.authentication.UserAuthenticationAgent; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.InvalidAuthenticationException; import org.simantics.db.exception.InvalidUserException; @@ -30,9 +29,13 @@ import org.simantics.db.impl.graph.WriteSupport; import org.simantics.db.impl.query.QueryProcessor; import org.simantics.db.impl.query.QuerySupport; import org.simantics.db.service.ServerInformation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; final public class SessionImplDb extends SessionImplSocket { + private static final Logger LOGGER = LoggerFactory.getLogger(SessionImplDb.class); + /** * Cached ServerInformation structure fetched from the server at connection * time. It should never change during a single session and therefore it @@ -58,7 +61,7 @@ final public class SessionImplDb extends SessionImplSocket { try { newId = cluster.createResource(clusterTranslator); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("createResource failed", e); return null; } return new ResourceImpl(resourceSupport, newId); @@ -114,8 +117,7 @@ final public class SessionImplDb extends SessionImplSocket { // clusterTable.dispose(); clusterTable = null; // throw e; } catch (Throwable e) { - e.printStackTrace(); - Logger.defaultLogError("Unhandled error. See exception for details.", e); + LOGGER.error("Unhandled error. See exception for details.", e); graphSession = null; clusterTable.dispose(); clusterTable = null; throw new Exception(e); diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java index 22d0f3165..29c70445b 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplSocket.java @@ -328,7 +328,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule try { getClusterTable().refresh(csid, this, clusterUID); } catch (Throwable t) { - Logger.defaultLogError("Refesh failed.", t); + LOGGER.error("refresh({}, {}) failed", thread, csid, t); } } @@ -461,17 +461,17 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule }); assert (null != writer); -// writer.state.barrier.inc(); + writer.asyncBarrier.inc(); try { request.perform(writer); assert (null != writer); } catch (Throwable t) { if (!(t instanceof CancelTransactionException)) - Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", t); + LOGGER.error("Write transaction caused an unexpected error, see exception.", t); writeState.except(t); } finally { -// writer.state.barrier.dec(); + writer.asyncBarrier.dec(); // writer.waitAsync(request); } @@ -482,7 +482,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule // Log it first, just to be safe that the error is always logged. if (!(e instanceof CancelTransactionException)) - Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e); + LOGGER.error("Write transaction caused an unexpected error, see exception.", e); // writeState.getGraph().state.barrier.dec(); // writeState.getGraph().waitAsync(request); @@ -571,52 +571,21 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule VirtualGraph vg = getProvider(request.getProvider()); WriteGraphImpl writer = WriteGraphImpl.create(getQueryProvider2(), writeSupport, vg); - try { - WriteState writeStateT = new WriteState(writer, request, notify, procedure); - writeState = writeStateT; + WriteState writeStateT = new WriteState(writer, request, notify, procedure); + writeState = writeStateT; + assert (null != writer); - assert (null != writer); -// writer.state.barrier.inc(); + try { + writer.asyncBarrier.inc(); writeStateT.setResult(request.perform(writer)); assert (null != writer); - -// writer.state.barrier.dec(); -// writer.waitAsync(null); - } catch (Throwable e) { - -// writer.state.barrier.dec(); -// writer.waitAsync(null); - writeState.except(e); - -// state.stopWriteTransaction(clusterStream); -// -// } catch (Throwable e) { -// // Log it first, just to be safe that the error is always logged. -// Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e); -// -// try { -// // Callback is client code, we have to be prepared for it to throw unexpected exceptions. -// // All we can do here is to log those, can't really pass them anywhere. -// if (procedure != null) { -// if(e instanceof DatabaseException) procedure.exception((DatabaseException)e); -// else procedure.exception(new DatabaseException(e)); -// } -// } catch (Throwable e2) { -// Logger.defaultLogError("Write request callback caused an unexpected error, see exception.", e2); -// } -// -// clientChanges = new ClientChangesImpl(SessionImplSocket.this); -// -// state.stopWriteTransaction(clusterStream); - } finally { + writer.asyncBarrier.dec(); fireSessionVariableChange(SessionVariables.QUEUED_WRITES); } -// if(notify != null) notify.release(); - task.finish(); } @@ -657,7 +626,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule if (t instanceof DatabaseException) callback.accept((DatabaseException) t); else callback.accept(new DatabaseException(t)); } else - Logger.defaultLogError("Unhandled exception", t); + LOGGER.error("Unhandled exception", t); } }; @@ -1355,7 +1324,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule callback.exception(new DatabaseException(e)); state.stopWriteTransaction(clusterStream); - Logger.defaultLogError("Write transaction caused an unexpected error, see exception.", e); + LOGGER.error("Write transaction caused an unexpected error, see exception.", e); } finally { @@ -1561,7 +1530,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule if(throwable != null) { throwable.set(th); } else { - Logger.defaultLogError("Unhandled exception", th); + LOGGER.error("Unhandled exception", th); } } @@ -1574,7 +1543,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule if(throwable != null) { throwable.set(t); } else { - Logger.defaultLogError("Unhandled exception", t); + LOGGER.error("Unhandled exception", t); } try { @@ -1586,7 +1555,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule if(throwable != null) { throwable.set(t2); } else { - Logger.defaultLogError("Unhandled exception", t2); + LOGGER.error("Unhandled exception", t2); } } @@ -1626,6 +1595,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule ITask task = ThreadLogger.task(request); final ReadGraphImpl newGraph = ReadGraphImpl.create(getQueryProvider2()); + newGraph.asyncBarrier.inc(); try { @@ -1663,6 +1633,8 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule } finally { + newGraph.asyncBarrier.dec(); + fireSessionVariableChange(SessionVariables.QUEUED_READS); } @@ -2479,6 +2451,7 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule return; WriteGraphImpl reactionGraph = WriteGraphImpl.create(graph.processor, writeSupport, null); + reactionGraph.asyncBarrier.inc(); try { @@ -2493,6 +2466,8 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule } finally { + reactionGraph.asyncBarrier.dec(); + } } catch (Throwable t) { @@ -2536,39 +2511,41 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule */ @SuppressWarnings("unchecked") @Override - public synchronized T peekService(Class api) { - - if(serviceKey1 == api) { - return (T)service1; - } else if (serviceKey2 == api) { - // Promote this key - Object result = service2; - service2 = service1; - serviceKey2 = serviceKey1; - service1 = result; - serviceKey1 = api; - return (T)result; - } + public T peekService(Class api) { + if (Layer0.class == api) + return (T) L0; - if (Layer0.class == api) - return (T) L0; - if (ServerInformation.class == api) - return (T) getCachedServerInformation(); - else if (WriteGraphImpl.class == api) - return (T) writeState.getGraph(); - else if (ClusterBuilder.class == api) - return (T)new ClusterBuilderImpl(this, (WriteOnlySupport)writeState.getGraph().writeSupport); - else if (ClusterBuilderFactory.class == api) - return (T)new ClusterBuilderFactoryImpl(this); + synchronized (this) { + if (serviceKey1 == api) { + return (T) service1; + } + if (serviceKey2 == api) { + // Promote this key + Object result = service2; + service2 = service1; + serviceKey2 = serviceKey1; + service1 = result; + serviceKey1 = api; + return (T)result; + } - service2 = service1; - serviceKey2 = serviceKey1; + if (ServerInformation.class == api) + return (T) getCachedServerInformation(); + else if (WriteGraphImpl.class == api) + return (T) writeState.getGraph(); + else if (ClusterBuilder.class == api) + return (T)new ClusterBuilderImpl(this, (WriteOnlySupport)writeState.getGraph().writeSupport); + else if (ClusterBuilderFactory.class == api) + return (T)new ClusterBuilderFactoryImpl(this); - service1 = serviceLocator.peekService(api); - serviceKey1 = api; + service2 = service1; + serviceKey2 = serviceKey1; - return (T)service1; + service1 = serviceLocator.peekService(api); + serviceKey1 = api; + return (T)service1; + } } /* @@ -2615,9 +2592,9 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule try { h.valuesChanged(ctx); } catch (Exception e) { - Logger.defaultLogError("monitor handler notification produced the following exception", e); + LOGGER.error("monitor handler notification produced the following exception", e); } catch (LinkageError e) { - Logger.defaultLogError("monitor handler notification produced a linkage error", e); + LOGGER.error("monitor handler notification produced a linkage error", e); } } } @@ -3604,4 +3581,10 @@ public abstract class SessionImplSocket implements Session, WriteRequestSchedule state.setCombine(false); } + @SuppressWarnings("unchecked") + @Override + public T l0() { + return (T) L0; + } + } diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplVirtual.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplVirtual.java index 50184528e..d90f2c3a5 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplVirtual.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/SessionImplVirtual.java @@ -16,7 +16,6 @@ import java.io.IOException; import org.simantics.db.ServerI; import org.simantics.db.VirtualGraph; import org.simantics.db.authentication.UserAuthenticationAgent; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.InvalidAuthenticationException; import org.simantics.db.exception.InvalidUserException; @@ -24,6 +23,8 @@ import org.simantics.db.impl.ResourceImpl; import org.simantics.db.impl.VirtualGraphImpl; import org.simantics.db.impl.query.QueryProcessor; import org.simantics.db.service.ServerInformation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import fi.vtt.simantics.procore.BackdoorAuthenticator; import fi.vtt.simantics.procore.ProCoreServerReference; @@ -31,6 +32,9 @@ import fi.vtt.simantics.procore.ProCoreSessionReference; import fi.vtt.simantics.procore.SessionManagerSource; public class SessionImplVirtual extends SessionImplSocket { + + private static final Logger LOGGER = LoggerFactory.getLogger(SessionImplVirtual.class); + protected VirtualGraphImpl virtualGraphImpl; public SessionImplVirtual(UserAuthenticationAgent authAgent) throws DatabaseException { @@ -75,12 +79,11 @@ public class SessionImplVirtual extends SessionImplSocket { } catch (InvalidUserException e) { throw e; } catch (IOException e) { - Logger.defaultLogError("I/O error. See exception for details.", e); + LOGGER.error("I/O error. See exception for details.", e); graphSession = null; throw new DatabaseException(e); } catch (Throwable e) { - e.printStackTrace(); - Logger.defaultLogError("Unhandled error. See exception for details.", e); + LOGGER.error("Unhandled error. See exception for details.", e); graphSession = null; throw new DatabaseException(e); } @@ -108,7 +111,7 @@ public class SessionImplVirtual extends SessionImplSocket { try { return gs.getServerInformation(); } catch (DatabaseException e) { - Logger.defaultLogError("Failed to get server info.", e); + LOGGER.error("Failed to get server info.", e); return null; } } diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/State.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/State.java index 4c6e77b1a..1e468f2c3 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/State.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/State.java @@ -24,6 +24,7 @@ import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.InternalException; import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.impl.graph.ReadGraphImpl; import org.simantics.db.impl.graph.WriteGraphImpl; import org.simantics.db.impl.query.QueryProcessor; import org.simantics.db.request.WriteOnly; @@ -340,7 +341,10 @@ class State { // start = System.nanoTime(); queryProvider.propagateChangesInQueryCache(graph); - queryProvider.listening.fireListeners(graph); + ReadGraphImpl listenerGraph = graph.forRecompute(null); + listenerGraph.asyncBarrier.inc(); + queryProvider.listening.fireListeners(listenerGraph); + listenerGraph.asyncBarrier.dec(); // duration = System.nanoTime() - start; // System.out.println("performScheduledUpdates " + 1e-9*duration + "s. "); diff --git a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java index ea4319ace..247df4645 100644 --- a/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java +++ b/bundles/org.simantics.db.procore/src/fi/vtt/simantics/procore/internal/WriteSupportImpl.java @@ -8,7 +8,6 @@ import org.simantics.db.VirtualGraph; import org.simantics.db.WriteGraph; import org.simantics.db.common.MetadataUtils; import org.simantics.db.common.exception.DebugException; -import org.simantics.db.common.utils.Logger; import org.simantics.db.exception.DatabaseException; import org.simantics.db.exception.ImmutableException; import org.simantics.db.exception.ServiceException; @@ -28,9 +27,13 @@ import org.simantics.db.request.WriteOnly; import org.simantics.db.request.WriteResult; import org.simantics.db.request.WriteTraits; import org.simantics.db.service.ByteReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class WriteSupportImpl implements WriteSupport { + private static final Logger LOGGER = LoggerFactory.getLogger(WriteSupportImpl.class); + final private SessionImplSocket session; final private QueryProcessor queryProcessor; final private State state; @@ -122,7 +125,7 @@ public class WriteSupportImpl implements WriteSupport { try { addSetValue(((ResourceImpl) resource).id, value, value.length); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("writeOnly setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e); } } } else { @@ -134,7 +137,7 @@ public class WriteSupportImpl implements WriteSupport { try { addSetValue(((ResourceImpl) resource).id, value, value.length); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("setValue({}, {}, byte[{}]) failed", provider, resource, value.length, e); } } queryProcessor.releaseWrite(session.writeState.getGraph()); @@ -199,7 +202,7 @@ public class WriteSupportImpl implements WriteSupport { try { cluster.removeValue(key, session.clusterTranslator); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("denyValue({}, {}) failed", provider, resource, e); return; } queryProcessor.updateValue(key); @@ -460,7 +463,7 @@ public class WriteSupportImpl implements WriteSupport { if (null != c && c != cluster) session.clusterTable.replaceCluster(c); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("claimImpl({}, {}, {}) failed", subject, predicate, object, e); throw new RuntimeException(e); } queryProcessor.updateStatements(subject, predicate); @@ -480,7 +483,7 @@ public class WriteSupportImpl implements WriteSupport { if (null != c && c != cluster) session.clusterTable.replaceCluster(c); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("claimImpl2({}, {}, {}) failed", subject, predicate, object, e); } if (cluster.isWriteOnly()) return; @@ -504,7 +507,7 @@ public class WriteSupportImpl implements WriteSupport { try { cluster.denyRelation(subject, predicate, object, session.clusterTranslator); } catch (DatabaseException e) { - Logger.defaultLogError(e); + LOGGER.error("removeStatement({}, {}, {}) failed", subject, predicate, object, e); return false; } queryProcessor.updateStatements(subject, predicate); diff --git a/bundles/org.simantics.db/src/org/simantics/db/RequestProcessor.java b/bundles/org.simantics.db/src/org/simantics/db/RequestProcessor.java index 5e818cb99..924ccffb0 100644 --- a/bundles/org.simantics.db/src/org/simantics/db/RequestProcessor.java +++ b/bundles/org.simantics.db/src/org/simantics/db/RequestProcessor.java @@ -62,7 +62,7 @@ import org.simantics.db.request.WriteInterface; * @see MergingGraphRequestProcessor * @see AsyncRequestProcessor */ -public interface RequestProcessor extends RequestProcessorSpecific, ServiceLocator { +public interface RequestProcessor extends RequestProcessorSpecific, ServiceLocator, ResourceLocator { Resource getRootLibrary(); diff --git a/bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java b/bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java new file mode 100644 index 000000000..8a8b0fa48 --- /dev/null +++ b/bundles/org.simantics.db/src/org/simantics/db/ResourceLocator.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2020 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.db; + +/** + * @author Tuukka Lehtonen + * @since 1.43.0 + */ +public interface ResourceLocator { + + /** + * Layer0 is an integral part of Simantics database modelling and for performance + * reasons deserves simplest possible access to its resource class. + * + * @return returns the internally cached + * org.simantics.layer0.Layer0 instance + */ + public T l0(); + +} diff --git a/bundles/org.simantics.db/src/org/simantics/db/service/QueryControl.java b/bundles/org.simantics.db/src/org/simantics/db/service/QueryControl.java index 3da3c5aa3..a8c728643 100644 --- a/bundles/org.simantics.db/src/org/simantics/db/service/QueryControl.java +++ b/bundles/org.simantics.db/src/org/simantics/db/service/QueryControl.java @@ -17,9 +17,11 @@ import org.simantics.db.AsyncReadGraph; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; +import org.simantics.db.exception.DatabaseException; import org.simantics.db.procedure.AsyncContextMultiProcedure; import org.simantics.db.procedure.AsyncMultiProcedure; import org.simantics.db.request.ExternalRead; +import org.simantics.db.request.Read; /** @@ -87,12 +89,25 @@ public interface QueryControl { * performed with the specified ReadGraph. DB listeners are therefore not * triggered by anything that is performed with the returned ReadGraph. * + * @Deprecated In favor of syncRequestIndependent * @param graph read transaction handle to clone for listener-independent * use * @return read transaction handle that is independent of the requests * performed with the parameter */ ReadGraph getIndependentGraph(ReadGraph graph); + + /** + * Performs the given request without accumulating query dependencies. + * DB listeners are therefore not triggered by anything that is performed within the request. + * + * @param graph read transaction handle to clone for listener-independent + * use + * @param request the request to perform + * @return the result of the request evaluation + */ + T syncRequestIndependent(ReadGraph graph, Read request) throws DatabaseException; + boolean hasParentRequest(ReadGraph graph); } diff --git a/bundles/org.simantics.desktop.product/splash.svg b/bundles/org.simantics.desktop.product/splash.svg index b984365f4..2b4ec84d2 100644 --- a/bundles/org.simantics.desktop.product/splash.svg +++ b/bundles/org.simantics.desktop.product/splash.svg @@ -401,7 +401,7 @@ id="tspan6235" x="4.0821486" y="291.79337" - style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.6444446px;font-family:'Cascadia Code';-inkscape-font-specification:'Cascadia Code, Normal';fill:#ffffff;fill-opacity:1;stroke-width:0.26458335px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">1.43.0 + style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:5.6444446px;font-family:'Cascadia Code';-inkscape-font-specification:'Cascadia Code, Normal';fill:#ffffff;fill-opacity:1;stroke-width:0.26458335px;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;">1.44.0 DESKTOP diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java index fe9371766..6357e537a 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteGraph.java @@ -277,6 +277,12 @@ public class RouteGraph implements Serializable { transientLines.clear(); } + protected void removeRouteTerminalsFromRouteLines() { + for(RouteLine line : lines) { + line.removeRouteTerminals(); + } + } + /** * Rotates given terminal clockwise by given amount * (also negative numbers are allowed). @@ -311,6 +317,7 @@ public class RouteGraph implements Serializable { public void update() { needsUpdate = false; removeTransientRouteLines(); + removeRouteTerminalsFromRouteLines(); //print(); diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java index a6a4f22d2..2011bfa28 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteLine.java @@ -188,6 +188,10 @@ public class RouteLine implements RouteNode, Serializable { return lines; } + public void removeRouteTerminals() { + points.removeIf(p -> p instanceof RouteTerminal); + } + public RouteTerminal getTerminal() { return terminal; } diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java index dd660d4aa..3d6bd182f 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java @@ -164,18 +164,31 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable boolean routeLineDoesNotIntersectTerminal; double linePosition = line.position; if(line.isHorizontal) { + if (linePosition == y) { + // direct route to terminal + line.addPoint(this); + return; + } lineDir = linePosition < y ? 3 : 1; routeLineDoesNotIntersectTerminal = linePosition <= minY || linePosition >= maxY || boundingBoxesIntersect /* we ignore intersection in this case */; } else { + if (linePosition == x) { + // direct route to terminal + line.addPoint(this); + return; + } lineDir = linePosition < x ? 2 : 0; routeLineDoesNotIntersectTerminal = linePosition <= minX || linePosition >= maxX || boundingBoxesIntersect /* we ignore intersection in this case */; } // We can route the connection directly to the right direction - if(routeLineDoesNotIntersectTerminal && + if((routeLineDoesNotIntersectTerminal || + (line.isHorizontal && (x == minX || x == maxX)) || // already on the top/bottom edge + (!line.isHorizontal && (y == minY || y == maxY)) // already on the left/right edge + ) && Directions.isAllowed(allowedDirections, lineDir)) { RouteLine line0 = createLine0(lineDir); new RouteLink(line0, line); diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/SimpleConnectionUtility.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/SimpleConnectionUtility.java index 0628573d0..f36417b48 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/SimpleConnectionUtility.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/SimpleConnectionUtility.java @@ -145,7 +145,7 @@ public class SimpleConnectionUtility { return MORE_BENDS_BBS_DONT_INTERSECT; } - private static int simpleConnectionCaseRouteToBounds(RouteTerminal a, + public static int simpleConnectionCaseRouteToBounds(RouteTerminal a, RouteTerminal b) { double aX = 0.5*(a.getMinX() + a.getMaxX()); double aY = 0.5*(a.getMinY() + a.getMaxY()); diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java index 539e28461..32df540ee 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/handler/MouseScaleMode.java @@ -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/symbolcontribution/GroupProxySymbolItem.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/symbolcontribution/GroupProxySymbolItem.java index fb3666e0b..1d04653b5 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/symbolcontribution/GroupProxySymbolItem.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/symbolcontribution/GroupProxySymbolItem.java @@ -37,6 +37,10 @@ public class GroupProxySymbolItem implements ISymbolItem { this.group = group; } + public ISymbolItem getSubject() { + return proxy; + } + @Override public String getName() { return proxy.getName(); diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementReorder.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementReorder.java index b0146cc21..e0d757417 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementReorder.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/synchronization/graph/ElementReorder.java @@ -55,9 +55,7 @@ public class ElementReorder extends ModificationAdapter { List graphOrder = OrderedSetUtils.toList(g, l); Set graphContents = new HashSet(graphOrder); - List diagramOrder = new ArrayList(order.size()); - Map diagramOrderIndex = new HashMap(order.size()); - int i = 0; + List 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 added = new HashSet(newGraphOrder); + for (Resource r : graphOrder) { + if (!added.contains(r)) { + newGraphOrder.add(r); } } } + + OrderedSetUtils.reorder(g, l, newGraphOrder); } } diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java index 7896e52a7..9134c1729 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ElementPainter.java @@ -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); diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ZOrderHandler.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ZOrderHandler.java index 007d039f2..8b893a2b1 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ZOrderHandler.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/participant/ZOrderHandler.java @@ -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); diff --git a/bundles/org.simantics.gnuplot/pom.xml b/bundles/org.simantics.gnuplot/pom.xml index 2d270fb11..3622652c9 100644 --- a/bundles/org.simantics.gnuplot/pom.xml +++ b/bundles/org.simantics.gnuplot/pom.xml @@ -18,7 +18,7 @@ UTF-8 - 1.5.0 + 1.6.0 diff --git a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java index f2321dce9..9873f8f1e 100644 --- a/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java +++ b/bundles/org.simantics.graph/src/org/simantics/graph/representation/TransferableGraphUtils.java @@ -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.history/src/org/simantics/history/csv/CSVFormatter.java b/bundles/org.simantics.history/src/org/simantics/history/csv/CSVFormatter.java index 4e405e2ac..6cc7a2a6f 100644 --- a/bundles/org.simantics.history/src/org/simantics/history/csv/CSVFormatter.java +++ b/bundles/org.simantics.history/src/org/simantics/history/csv/CSVFormatter.java @@ -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) { diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/expression/InvertBasicExpressionVisitor.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/expression/InvertBasicExpressionVisitor.java index 3f4ccc20b..9101700d0 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/expression/InvertBasicExpressionVisitor.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/expression/InvertBasicExpressionVisitor.java @@ -1,109 +1,15 @@ 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 stack = new Stack(); - - 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 p = (Triple)o2; - stack.push(Triple.make(p.first, p.second + (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third )); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)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); - } - - } - } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/CSVPreferencePage.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/CSVPreferencePage.java index aadd9395a..7a2e7a6eb 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/CSVPreferencePage.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/preferences/CSVPreferencePage.java @@ -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); + } + } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java index d3170b950..1db2ba151 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/sg/DiagramSceneGraphProvider.java @@ -348,13 +348,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi } try { - - IModelingRules modelingRules = Simantics.getSession().syncRequest(DiagramRequests.getModelingRules(resource, null)); - if (modelingRules != null) { - initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules); - } - - initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor()); + fillInitialDiagramHints(initialHints); final RuntimeDiagramManager runtimeDiagramManager = RuntimeDiagramManager.create(Simantics.getSession(), resource, modelURI, RVI); @@ -385,6 +379,15 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi return ctx.getSceneGraph(); } + protected void fillInitialDiagramHints(IHintContext initialHints) throws DatabaseException { + IModelingRules modelingRules = Simantics.getSession().syncRequest(DiagramRequests.getModelingRules(resource, null)); + if (modelingRules != null) { + initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules); + } + + initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor()); + } + protected IElementClassProvider createElementClassProvider(ReadGraph graph) throws DatabaseException { DiagramResource dr = DiagramResource.getInstance(graph); return ElementClassProviders.mappedProvider( diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java index 5bcce3ee4..6293cbac9 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitor.java @@ -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 stack = new Stack(); - - 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 p = (Triple)o2; - stack.push(Triple.make(p.first, p.second + (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(-p.first, (Double)o1 - p.second, p.third )); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)o2; - stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third)); - } else if (o2 instanceof Double && o1 instanceof Triple) { - Triple p = (Triple)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 p = (Triple)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 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 data = (Triple)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) result; return null; } + public static Variable possibleInvertibleExpressionReferencedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException { + Triple 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 possibleInvertibleExpressionReferencedTransformedProperty(ReadGraph graph, Variable base, String expression) throws DatabaseException { + Triple 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 index 000000000..8ccf5c28c --- /dev/null +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/InvertBasicExpressionVisitorBase.java @@ -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 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 p = (Triple)o2; + stack.push(Triple.make(p.first, p.second + (Double)o1, p.third)); + } else if (o2 instanceof Double && o1 instanceof Triple) { + Triple p = (Triple)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) { + // o2 - double o1 + Triple p = (Triple)o2; + stack.push(Triple.make(p.first, p.second - (Double)o1, p.third)); + } else if (o2 instanceof Double && o1 instanceof Triple) { + // double o2 - o1 + Triple p = (Triple)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 p = (Triple)o2; + stack.push(Triple.make(p.first * (Double)o1, p.second * (Double)o1, p.third)); + } else if (o2 instanceof Double && o1 instanceof Triple) { + Triple p = (Triple)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) { + // o2 / double o1 + Triple p = (Triple)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 / 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 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/ProceduralSubstructureMapRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/ProceduralSubstructureMapRequest.java index e8c54fa98..6256891b8 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/ProceduralSubstructureMapRequest.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/ProceduralSubstructureMapRequest.java @@ -3,6 +3,7 @@ package org.simantics.modeling; import gnu.trove.map.hash.THashMap; import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PropertyInfo; import org.simantics.db.layer0.request.PropertyInfoRequest; @@ -21,19 +22,28 @@ public class ProceduralSubstructureMapRequest extends VariableRead> perform(ReadGraph graph) throws DatabaseException { THashMap> propertyMap = new THashMap>(); for(Variable child : variable.getChildren(graph)) { - for(Variable property : child.getProperties(graph)) { - PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(property.getPredicateResource(graph))); + for(Variable property : child.getProperties(graph)) { + Resource predicate = property.getPossiblePredicateResource(graph); + if (predicate == null) + continue; + + PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(predicate)); propertyMap.put(child.getName(graph) + "." + propertyInfo.name, Pair.make("/" + child.getName(graph) + "#" + propertyInfo.name, SCLTypeUtils.getType(propertyInfo))); - } + } } - for(Variable property : variable.getProperties(graph)) { - PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(property.getPredicateResource(graph))); + for(Variable property : variable.getProperties(graph)) { + Resource predicate = property.getPossiblePredicateResource(graph); + if (predicate == null) + continue; + + PropertyInfo propertyInfo = graph.syncRequest(new PropertyInfoRequest(predicate)); propertyMap.put(propertyInfo.name, Pair.make("#" + propertyInfo.name, SCLTypeUtils.getType(propertyInfo))); - } + } + return propertyMap; } diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java index db65b4de3..82115ef0e 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/SCLScenegraph.java @@ -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, ""); - parentBuilder.append(MAIN_SECTION, svg); - parentBuilder.append(MAIN_SECTION, "\n"); + 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"); + parentBuilder2.append(SELECTION_SECTION, svg); + parentBuilder2.append(SELECTION_SECTION, "\n"); + + parentBuilder2.append(SELECTION_MASK_SECTION, "\n"); + Rectangle2D rect = node.getBounds(); + // NaN + if(rect.getHeight() == rect.getHeight() && rect.getWidth() == rect.getWidth()) { + parentBuilder2.append(SELECTION_MASK_SECTION,""); + } + parentBuilder2.append(SELECTION_MASK_SECTION,"\n"); + } + } else { + parentBuilder.append(MAIN_SECTION, ""); + parentBuilder.append(MAIN_SECTION, svg); + parentBuilder.append(MAIN_SECTION, "\n"); + } } 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. } diff --git a/bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF b/bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF index e032ff417..6d8c271b0 100644 --- a/bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF +++ b/bundles/org.simantics.scenegraph.profile/META-INF/MANIFEST.MF @@ -14,7 +14,7 @@ Require-Bundle: org.simantics.db.layer0;bundle-version="1.1.0", org.simantics.scenegraph;bundle-version="1.1.1", org.eclipse.core.runtime;bundle-version="3.6.0", org.simantics.diagram.ontology;bundle-version="1.1.1", - org.simantics.db.common + org.slf4j.api Bundle-ActivationPolicy: lazy Bundle-Activator: org.simantics.scenegraph.profile.impl.Activator Import-Package: org.simantics diff --git a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java index 9d379c890..440ee2714 100644 --- a/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java +++ b/bundles/org.simantics.scenegraph.profile/src/org/simantics/scenegraph/profile/common/ProfileObserver.java @@ -23,8 +23,8 @@ import org.simantics.db.AsyncRequestProcessor; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.common.session.SessionEventListenerAdapter; -import org.simantics.db.common.utils.Logger; import org.simantics.db.procedure.Procedure; +import org.simantics.db.service.QueryControl; import org.simantics.db.service.SessionEventSupport; import org.simantics.scenegraph.INode; import org.simantics.scenegraph.g2d.G2DSceneGraph; @@ -38,9 +38,13 @@ import org.simantics.utils.datastructures.Pair; import org.simantics.utils.datastructures.disposable.IDisposable; import org.simantics.utils.threads.IThreadWorkQueue; import org.simantics.utils.threads.ThreadUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class ProfileObserver implements EvaluationContext { + private static final Logger LOGGER = LoggerFactory.getLogger(ProfileObserver.class); + private final Session session; /** @@ -58,6 +62,7 @@ public class ProfileObserver implements EvaluationContext { private volatile boolean dirty = true; private volatile boolean disposed = false; + private boolean needSynchronizedUpdates = false; private List> updates = new ArrayList<>(); private boolean updateAll; @@ -95,6 +100,7 @@ public class ProfileObserver implements EvaluationContext { this.sceneGraph = sceneGraph; this.constants.putAll(constants); this.notification = notification; + this.needSynchronizedUpdates = session.getService(QueryControl.class).getAmountOfQueryThreads() > 1; attachSessionListener(); @@ -139,8 +145,14 @@ public class ProfileObserver implements EvaluationContext { public void update(Style style, Object item) { if (DebugPolicy.DEBUG_PROFILE_OBSERVER_UPDATE) System.out.println("Profile observer marked dirty."); - - updates.add(Pair.make(style, item)); + + if (needSynchronizedUpdates) { + synchronized (updates) { + updates.add(Pair.make(style, item)); + } + } else { + updates.add(Pair.make(style, item)); + } //updateAll = true; dirty = true; } @@ -179,10 +191,25 @@ public class ProfileObserver implements EvaluationContext { e.apply(ProfileObserver.this); } updateAll = false; - updates.clear(); + if (needSynchronizedUpdates) { + synchronized (updates) { + updates.clear(); + } + } else { + updates.clear(); + } } else { - List> updatesCopy = new ArrayList<>(updates); - updates.clear(); + List> updatesCopy; + if (needSynchronizedUpdates) { + synchronized (updates) { + updatesCopy = new ArrayList<>(updates); + updates.clear(); + } + } else { + updatesCopy = new ArrayList<>(updates); + updates.clear(); + } + for (Pair update : updatesCopy) { Style style = update.first; Object item = update.second; @@ -221,7 +248,7 @@ public class ProfileObserver implements EvaluationContext { @Override public void exception(Throwable t) { - Logger.defaultLogError(t); + LOGGER.error("RuntimeProfileActiveEntries request failed", t); } }); } @@ -233,7 +260,7 @@ public class ProfileObserver implements EvaluationContext { @Override public void exception(Throwable throwable) { - Logger.defaultLogError(throwable); + LOGGER.error("Exception occurred during diagram profile observation", throwable); } @SuppressWarnings("unchecked") diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java new file mode 100644 index 000000000..2601728f2 --- /dev/null +++ b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java @@ -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); + } + +} diff --git a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java index dd71e323b..899b9e731 100644 --- a/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java +++ b/bundles/org.simantics.scl.ui/src/org/simantics/scl/ui/assist/StyledTextContentAdapter.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.simantics.scl.ui.assist; +import org.eclipse.jface.fieldassist.ContentProposalAdapter; import org.eclipse.jface.fieldassist.IControlContentAdapter; import org.eclipse.jface.fieldassist.IControlContentAdapter2; import org.eclipse.swt.custom.StyledText; @@ -69,26 +70,51 @@ public class StyledTextContentAdapter implements IControlContentAdapter, IContro public void insertControlContents(Control control, String contents, int cursorPosition) { StyledText text = ((StyledText)control); cursorPosition = Math.min(cursorPosition, contents.length()); - int caretEndRange = text.getCaretOffset(); + + int caretOffset = text.getCaretOffset(); String currentText = text.getText(); - - int offset = caretEndRange; - int length = currentText.length(); - while (--offset >= 0 && (Character.isJavaIdentifierPart(currentText.charAt(offset)) && !Character.isWhitespace(currentText.charAt(offset)))) - length--; - - int nameSpaceBeginRange = currentText.lastIndexOf(".", caretEndRange - 1); //$NON-NLS-1$ - if (nameSpaceBeginRange > length) - length = nameSpaceBeginRange; - int endRange = currentText.length(); - if (caretEndRange < endRange) - endRange = caretEndRange; - text.setSelection(length, endRange); + int replacementOffset = findPrefixMatchOffset(currentText, caretOffset, contents); + +// System.out.println("text: " + currentText); +// System.out.println("proposal to fill: " + contents); +// System.out.format("longest match of proposed contents found from text @ offset %d: \"%s[%s]%s\"%n", +// replacementOffset, +// currentText.substring(0, replacementOffset), +// currentText.substring(replacementOffset, caretOffset), +// currentText.substring(caretOffset)); + + // The text between [replaceOffset, caretOffset) will be replaced with `contents` + text.setSelection(replacementOffset, caretOffset); text.insert(contents); - // calculate the initial count of letters that was typed when the proposal was accepted to insert the caret - // at the right position - int proposalFirstLettersCount = endRange - (length); - text.setCaretOffset(caretEndRange + cursorPosition - proposalFirstLettersCount); + text.setSelection(replacementOffset + contents.length()); + } + + /** + * Find offset of longest prefix match of match in + * text ending at offset endOffset. + * + * Example: + *
+	 * ...  res (=text)
+	 * resource (=match)
+	 *  resourc
+	 *   resour
+	 *    resou
+	 *     reso
+	 *      res match! return endOffset - 3
+	 * 
+ * + * @param text the text from which to find the match + * @param endOffset endOffset until which to search for the longest match + * @param match the text to prefix-match + * @return + */ + private static int findPrefixMatchOffset(String text, int endOffset, String match) { + for (int i = match.length(); i >= 0; --i) { + if (text.regionMatches(true, endOffset - i, match, 0, i)) + return endOffset - i; + } + return 0; } /* diff --git a/bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java b/bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java index 1ee543f4c..34fbb587d 100644 --- a/bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java +++ b/bundles/org.simantics.simulation/src/org/simantics/simulation/data/DatasourceAdapter.java @@ -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 handles = new ArrayList(); @@ -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; } - } diff --git a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java index 402f3884d..e09b3136e 100644 --- a/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java +++ b/bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java @@ -194,7 +194,10 @@ public class StandardNodeManager { - // --- 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 getChildNames(Node node) throws NodeManagerException; - List getPropertyNames(Node node) throws NodeManagerException; - List getChildren(Node node) throws NodeManagerException; - List 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 getChildNames(Node node) throws NodeManagerException; + List getPropertyNames(Node node) throws NodeManagerException; + List getChildren(Node node) throws NodeManagerException; + List 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 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 getClassifications(Node node) throws NodeManagerException; } \ No newline at end of file diff --git a/bundles/org.simantics.trend/src/org/simantics/trend/impl/HorizRuler.java b/bundles/org.simantics.trend/src/org/simantics/trend/impl/HorizRuler.java index a70949d5e..708a32efc 100644 --- a/bundles/org.simantics.trend/src/org/simantics/trend/impl/HorizRuler.java +++ b/bundles/org.simantics.trend/src/org/simantics/trend/impl/HorizRuler.java @@ -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. diff --git a/features/org.simantics.sdk.feature/feature.xml b/features/org.simantics.sdk.feature/feature.xml index 0d0bc2f07..ca5692d4b 100644 --- a/features/org.simantics.sdk.feature/feature.xml +++ b/features/org.simantics.sdk.feature/feature.xml @@ -13,7 +13,7 @@ diff --git a/releng/org.simantics.sdk.build.targetdefinition/simantics.target b/releng/org.simantics.sdk.build.targetdefinition/simantics.target index f06dc5e47..ad1d836da 100644 --- a/releng/org.simantics.sdk.build.targetdefinition/simantics.target +++ b/releng/org.simantics.sdk.build.targetdefinition/simantics.target @@ -1,7 +1,7 @@ - + diff --git a/releng/org.simantics.sdk.build.targetdefinition/simantics.tpd b/releng/org.simantics.sdk.build.targetdefinition/simantics.tpd index 1d7588e26..8d63f70f4 100644 --- a/releng/org.simantics.sdk.build.targetdefinition/simantics.tpd +++ b/releng/org.simantics.sdk.build.targetdefinition/simantics.tpd @@ -1,4 +1,4 @@ -target "Simantics 1.43.0" +target "Simantics 1.44.0" with source allEnvironments diff --git a/releng/org.simantics.sdk.repository/pom.xml b/releng/org.simantics.sdk.repository/pom.xml index c636acba4..42fd442e8 100644 --- a/releng/org.simantics.sdk.repository/pom.xml +++ b/releng/org.simantics.sdk.repository/pom.xml @@ -2,7 +2,7 @@ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 4.0.0 org.simantics.sdk.repository - 1.43.0-SNAPSHOT + 1.44.0-SNAPSHOT eclipse-repository diff --git a/releng/org.simantics.tycho.configuration/pom.xml b/releng/org.simantics.tycho.configuration/pom.xml index da8b7254d..527066818 100644 --- a/releng/org.simantics.tycho.configuration/pom.xml +++ b/releng/org.simantics.tycho.configuration/pom.xml @@ -8,8 +8,8 @@ pom - 1.5.0 - 1.5.0 + 1.6.0 + 1.6.0 UTF-8