From: Jani Simomaa Date: Thu, 16 Apr 2020 08:55:47 +0000 (+0000) Subject: Merge "Add missing javax.servlet-api bundle requirement for jersey bundles" X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=commitdiff_plain;h=1ecae6e1ad40507badb8807fb14bb67b4adf199c;hp=688eb97a7826cde28adcf6592f5380bda7a736c6 Merge "Add missing javax.servlet-api bundle requirement for jersey bundles" --- 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/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/graph/ReadGraphImpl.java b/bundles/org.simantics.db.impl/src/org/simantics/db/impl/graph/ReadGraphImpl.java index 61580bfdc..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 @@ -1511,15 +1511,15 @@ public class ReadGraphImpl implements AsyncReadGraph { try { - int result = processor.getSingleObject(this, subject, relation); - if(result == 0) return null; - - return processor.querySupport.getResource(result); + int result = processor.getSingleObject(this, subject, relation); + if(result == 0) return null; + + return processor.querySupport.getResource(result); - } catch (ManyObjectsForFunctionalRelationException e) { + } catch (ManyObjectsForFunctionalRelationException e) { + + throw new ManyObjectsForFunctionalRelationException("Many objects in " + subject + " for functional relation " + relation); - throw new ManyObjectsForFunctionalRelationException("subject=" + subject + ", relation=" + relation, e); - } catch (DatabaseException e) { throw new ServiceException(e); 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 e3bd43741..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)); } @@ -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/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/function/All.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/function/All.java index f52148c2a..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.getPossiblePredicateResource(graph))) { - 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.getPossiblePredicateResource(graph))) { - return graph.getValue2(assertion.second, variable, binding); - } - } - } - } - } - - return graph.getValue2(variable.getRepresents(graph), context, binding); - - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph)); - } catch (DatabaseException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } - - public static void standardSetValue2(WriteGraph graph, Variable context, final Object value) throws DatabaseException { - - if(context instanceof StandardGraphPropertyVariable) { - - final StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - // First from node + + if (variable.isAsserted()) { + if (variable.parentResource != null) { + Map> 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,371 +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) { - Resource predicate = variable.getPossiblePredicateResource(graph); - if (predicate != null) { - Statement stm = graph.getPossibleStatement(variable.parentResource, predicate); - return stm != null && stm.isAsserted(variable.parentResource); - } - } - } - return Boolean.FALSE; + Variable property = context.getParent(graph); + if(property instanceof StandardGraphPropertyVariable) { + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)property; + if (variable.parentResource != null) { + Resource predicate = variable.getPossiblePredicateResource(graph); + if (predicate != null) { + Statement stm = graph.getPossibleStatement(variable.parentResource, predicate); + return stm != null && stm.isAsserted(variable.parentResource); + } + } + } + return Boolean.FALSE; } @SCLValue(type = "ReadGraph -> Resource -> a -> Boolean") public static Boolean standardReadOnlyValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Boolean.FALSE; + return Boolean.FALSE; } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object resourceAsValue(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return resource; + return resource; } - + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object functionApplication(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - return Functions.exec(graph, resource, graph, resource, context); + return Functions.exec(graph, resource, graph, resource, context); } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object computeExpression(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { + if(context instanceof Variable) { return CompileValueRequest.compileAndEvaluate(graph, (Variable)context); - } if (context instanceof Resource) { + } if (context instanceof Resource) { return CompileResourceValueRequest.compileAndEvaluate(graph, (Resource)converter); - } else { - throw new IllegalStateException("Unknown context " + context); - } + } else { + throw new IllegalStateException("Unknown context " + context); + } } @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object composedPropertyValue(ReadGraph graph, Resource converter, Object context) throws DatabaseException { - if(context instanceof Variable) { - return new StandardComposedProperty(); - } if (context instanceof Resource) { - return new StandardComposedProperty(); - } else { - throw new IllegalStateException("Unknown context " + context); - } - } - + if(context instanceof Variable) { + return new StandardComposedProperty(); + } if (context instanceof Resource) { + return new StandardComposedProperty(); + } else { + throw new IllegalStateException("Unknown context " + context); + } + } + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object numberInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - + class Validator extends FunctionImpl1 { private final Datatype datatype; - + public Validator(Datatype datatype) { this.datatype = datatype; } - + @Override public String apply(String input) { - + if(datatype == null) return null; - + try { if(datatype instanceof NumberType) { - + Number number = (Number)PrimitiveValueParser.parse(input, datatype); NumberType nt = (NumberType)datatype; Range r = nt.getRange(); @@ -1239,130 +1244,130 @@ public class All { } } return null; - + } catch (NumberFormatException e) { return "Not a valid floating-point number"; } catch (IllegalArgumentException e) { return "Not a valid floating-point number"; } - + } - + } if(context instanceof Variable) { - + Variable variable = (Variable)context; Variable property = variable.getParent(graph); Datatype datatype = property.getPossibleDatatype(graph); return new Validator(datatype); - + } else if (context instanceof Resource) { Layer0 L0 = Layer0.getInstance(graph); Resource literal = (Resource)context; Datatype datatype = graph.getRelatedValue(literal, L0.HasDataType, Bindings.getBindingUnchecked(Datatype.class)); return new Validator(datatype); - + } else { - + return new Validator(null); - + } - + } - + @SCLValue(type = "ReadGraph -> Resource -> a -> b") public static Object booleanInputValidator(ReadGraph graph, Resource resource, Object context) throws DatabaseException { - + return new FunctionImpl1() { @Override public String apply(String input) { - - String lower = input.toLowerCase(); - if("true".equals(lower) || "false".equals(lower)) return null; - return "Not a valid boolean: " + input; - + String lower = input.toLowerCase(); + if("true".equals(lower) || "false".equals(lower)) return null; + + return "Not a valid boolean: " + input; + } - + }; - + } @SCLValue(type = "ReadGraph -> Resource -> Variable -> Resource") public static Resource hasStandardResource(ReadGraph graph, Resource resource, Variable context) throws DatabaseException { - Variable parent = context.getParent(graph); - if(parent instanceof StandardGraphChildVariable) { - StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; - return variable.resource; - } - return null; + Variable parent = context.getParent(graph); + if(parent instanceof StandardGraphChildVariable) { + StandardGraphChildVariable variable = (StandardGraphChildVariable)parent; + return variable.resource; + } + return null; } @SCLValue(type = "ReadGraph -> Resource -> Variable -> a") - public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); - } - - if (variable.parentResource == null) - throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); - - try { - return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } + public static Object valueWithoutBinding(ReadGraph graph, Resource converter, Variable context) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel); + } + + if (variable.parentResource == null) + throw new InvalidVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ")."); + + try { + return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } @SCLValue(type = "ReadGraph -> Variable -> Binding -> a") - public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { - - StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; - - if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { - Layer0 L0 = Layer0.getInstance(graph); - return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); - } - - if (variable.parentResource == null) - throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph)); - - - try { - return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); - } catch (NoSingleResultException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } catch (DoesNotContainValueException e) { - throw new MissingVariableValueException(variable.getPossibleURI(graph), e); - } - - } + public static Object valueWithBinding(ReadGraph graph, Variable context, Binding binding) throws DatabaseException { + + StandardGraphPropertyVariable variable = (StandardGraphPropertyVariable)context; + + if(graph.sync(new IsEnumeratedValue(variable.getRepresents(graph)))) { + Layer0 L0 = Layer0.getInstance(graph); + return graph.getRelatedValue2(variable.getRepresents(graph), L0.HasLabel, binding); + } + + if (variable.parentResource == null) + throw new MissingVariableException("Variable is not represented by any resource (URI=" + variable.getPossibleURI(graph) + ").", context.getPossibleRepresents(graph)); + + + try { + return graph.getRelatedValue2(variable.parentResource, variable.getPredicateResource(graph), variable); + } catch (NoSingleResultException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } catch (DoesNotContainValueException e) { + throw new MissingVariableValueException(variable.getPossibleURI(graph), e); + } + + } @SCLValue(type = "WriteGraph -> Variable -> a -> Binding -> b") - public static Object valueSetterWithBinding(WriteGraph graph, Variable variable, Object value, Binding binding) throws DatabaseException { - - Function4 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; @@ -1377,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(); } @@ -1443,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/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/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.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java index b2895fb34..2f218d8fa 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java @@ -126,16 +126,18 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable { double dy1 = curY-oldY; double dx2 = curX-newX; double dy2 = curY-newY; - double maxRadius = 0.5 * Math.min(Math.sqrt(dx1*dx1 + dy1*dy1), Math.sqrt(dx2*dx2 + dy2*dy2)); + double r1 = Math.sqrt(dx1*dx1 + dy1*dy1); + double r2 = Math.sqrt(dx2*dx2 + dy2*dy2); + double maxRadius = 0.5 * Math.min(r1, r2); double radius = Math.min(rounding, maxRadius); - newPath.lineTo(curX + radius*Math.signum(oldX-curX), curY + radius*Math.signum(oldY-curY)); + double dx1Normalized = r1 > 0 ? dx1 / r1 : 0; + double dy1Normalized = r1 > 0 ? dy1 / r1 : 0; + double dx2Normalized = r2 > 0 ? dx2 / r2 : 0; + double dy2Normalized = r2 > 0 ? dy2 / r2 : 0; + newPath.lineTo(curX - radius*dx1Normalized, curY - radius*dy1Normalized); newPath.curveTo(curX, curY, curX, curY, - curX + radius*Math.signum(newX-curX), curY + radius*Math.signum(newY-curY)); - - //newPath.lineTo(curX + round*Math.signum(oldX-curX), curY + round*Math.signum(oldY-curY)); - //newPath.lineTo(curX + round*Math.signum(newX-curX), curY + round*Math.signum(newY-curY)); - //newPath.lineTo(curX, curY); + curX - radius*dx2Normalized, curY - radius*dy2Normalized); } else ++state; @@ -216,6 +218,8 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable { result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode()); result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode()); + temp = Double.doubleToLongBits(rounding); + result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode()); return result; } @@ -248,6 +252,8 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable { return false; } else if (!lineStroke.equals(other.lineStroke)) return false; + if (Double.doubleToLongBits(rounding) != Double.doubleToLongBits(other.rounding)) + return false; if (routeLineStroke == null) { if (other.routeLineStroke != null) return false; diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java new file mode 100644 index 000000000..3ccb492b6 --- /dev/null +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionCrossings.java @@ -0,0 +1,214 @@ +/******************************************************************************* + * Copyright (c) 2020 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.diagram.connection.rendering; + +import java.awt.geom.Arc2D; +import java.awt.geom.Path2D; +import java.awt.geom.PathIterator; +import java.awt.geom.Point2D; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class ConnectionCrossings implements PathModifier { + public enum Type { + NONE, + GAP, + ARC, + SQUARE + } + + private List segments = new ArrayList<>(); + private double width; + private Type type; + + public void setWidth(double gapWidth) { + this.width = gapWidth; + } + + public double getWidth() { + return width; + } + + public void setType(Type type) { + this.type = type; + } + + public Type getType() { + return type; + } + + static class Segment { + public double x1, y1, x2, y2; + + public Segment(double x1, double y1, double x2, double y2) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + } + }; + + public void reset() { + segments.clear(); + } + + static Double lineLineIntersection(Segment l1, Segment l2) { + double epsilon = 0.001; + + double d = (l1.x1 - l1.x2) * (l2.y1 - l2.y2) - (l1.y1 - l1.y2) * (l2.x1 - l2.x2); + if (d == 0.0) return null; + double s = ((l1.x1 - l2.x1) * (l2.y1 - l2.y2) - (l1.y1 - l2.y1) * (l2.x1 - l2.x2)) / d; + if ((s > epsilon) && (s < 1 - epsilon)) { + double t = -((l1.x1 - l1.x2) * (l1.y1 - l2.y1) - (l1.y1 - l1.y2) * (l1.x1 - l2.x1)) / d; + if ((t > epsilon) && (t < 1 - epsilon)) { + return t; + } + } + return null; + } + + public Path2D modify(Path2D path) { + Path2D.Double path2 = new Path2D.Double(); + PathIterator iter = path.getPathIterator(null); + + while (!iter.isDone()) { + + double c[] = new double[6]; + int i = iter.currentSegment(c); + switch (i) { + case PathIterator.SEG_MOVETO: + path2.moveTo(c[0], c[1]); + break; + case PathIterator.SEG_LINETO: + Segment l = new Segment(path2.getCurrentPoint().getX(), path2.getCurrentPoint().getY(), c[0], c[1]); + + List gaps = new ArrayList<>(); + for (Segment old : segments) { + Double t = lineLineIntersection(old, l); + if (t != null) { + gaps.add(t); + } + } + + if (gaps.isEmpty()) { + path2.lineTo(c[0], c[1]); + } else { + Collections.sort(gaps); + double dx = l.x2 - l.x1; + double dy = l.y2 - l.y1; + + double pos = 0.0; + double len = Math.sqrt(dx*dx + dy*dy); + + boolean finish = true; + Point2D prevGapEnd = null; + for (Double gapCenter : gaps) { + double pos2 = gapCenter - width / 2 / len; + double pos3 = gapCenter + width / 2 / len; + if (pos2 > pos) { + handleGap(path2, prevGapEnd); + prevGapEnd = null; + path2.lineTo(l.x1 + pos2 * dx, l.y1 + pos2 * dy); + } + if (pos3 < 1.0) { + double x = l.x1 + pos3 * dx; + double y = l.y1 + pos3 * dy; + prevGapEnd = new Point2D.Double(x, y); + } else { + finish = false; + } + pos = pos3; + } + + if (finish) { + handleGap(path2, prevGapEnd); + path2.lineTo(l.x2, l.y2); + } else { + prevGapEnd = new Point2D.Double(l.x2, l.y2); + handleGap(path2, prevGapEnd); + } + } + segments.add(l); + + break; + case PathIterator.SEG_QUADTO: + // TODO: implement gaps + path2.quadTo(c[0], c[1], c[2], c[3]); + break; + case PathIterator.SEG_CUBICTO: + // TODO: implement gaps + path2.curveTo(c[0], c[1], c[2], c[3], c[4], c[5]); + break; + case PathIterator.SEG_CLOSE: + // TODO: implement gaps + path2.closePath(); + break; + default: + throw new RuntimeException("Unexpected segment type " + i); + } + iter.next(); + } + return path2; + } + + private void handleGap(Path2D path, Point2D prevGapEnd) { + if (prevGapEnd != null) { + switch (type) { + case ARC: + arcTo(path, prevGapEnd.getX(), prevGapEnd.getY()); + break; + case SQUARE: + squareTo(path, prevGapEnd.getX(), prevGapEnd.getY(), width); + break; + case GAP: + path.moveTo(prevGapEnd.getX(), prevGapEnd.getY()); + break; + case NONE: + break; + } + } + } + + private static void arcTo(Path2D path, double x2, double y2) { + Arc2D arc = new Arc2D.Double(); + double x1 = path.getCurrentPoint().getX(); + double y1 = path.getCurrentPoint().getY(); + double dx = x2 - x1; + double dy = y2 - y1; + double r = Math.sqrt(dx * dx + dy * dy) / 2; + double angle = Math.atan2(dx, dy) * 180 / Math.PI + 90; + double span = (angle > 225 || angle < 45) ? 180 : -180; + arc.setArcByCenter((x1 + x2) / 2, (y1 + y2) / 2, r, angle, span, Arc2D.OPEN); + path.append(arc, true); + } + + private static void squareTo(Path2D path, double x2, double y2, double width) { + double x1 = path.getCurrentPoint().getX(); + double y1 = path.getCurrentPoint().getY(); + double dx = x2 - x1; + double dy = y2 - y1; + double l = Math.sqrt(dx * dx + dy* dy); + if (l > 0) { + double nx = -dy / l; + double ny = dx / l; + if (nx - ny < 0) { + nx = -nx; + ny = -ny; + } + path.lineTo(x1 + nx * width / 2, y1 + ny * width / 2); + path.lineTo(x2 + nx * width / 2, y2 + ny * width / 2); + path.lineTo(x2, y2); + } + } + +} diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java new file mode 100644 index 000000000..a78bec04b --- /dev/null +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/ConnectionRenderingHints.java @@ -0,0 +1,24 @@ +/******************************************************************************* + * Copyright (c) 2020 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.diagram.connection.rendering; + +import java.awt.RenderingHints.Key; + +public final class ConnectionRenderingHints { + + public static final Key KEY_PATH_MODIFIER = new Key(0) { + @Override + public boolean isCompatibleValue(Object val) { + return val == null || val instanceof PathModifier; + } + }; +} \ No newline at end of file diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java new file mode 100644 index 000000000..50d771a40 --- /dev/null +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/PathModifier.java @@ -0,0 +1,18 @@ +/******************************************************************************* + * Copyright (c) 2020 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.diagram.connection.rendering; + +import java.awt.geom.Path2D; + +public interface PathModifier { + public Path2D modify(Path2D source); +} diff --git a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java index dd9473042..fa1447469 100644 --- a/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java +++ b/bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/StyledRouteGraphRenderer.java @@ -62,6 +62,10 @@ public class StyledRouteGraphRenderer implements IRouteGraphRenderer, Serializab path.reset(); rg.getPath2D(path); + PathModifier pm = (PathModifier) g.getRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER); + if (pm != null) { + path = pm.modify(path); + } style.drawPath(g, path, false); branchPoints.clear(); diff --git a/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph b/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph index b26bfc698..6ea207f88 100644 --- a/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph +++ b/bundles/org.simantics.diagram.ontology/graph/Diagram.pgraph @@ -68,6 +68,9 @@ DIA.IOTableRename -- DIA.Diagram.IOTableRenaming --> DIA.IOTableRename DIA.ProfileEntryContribution.HasEntry --> DIA.ProfileEntry >(diagram){ + + @Override + public Pair perform(ReadGraph graph) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + Double gap = graph.getPossibleRelatedValue(diagram, DIA.ConnectionCrossingStyle_Width); + Resource typeRes = graph.getPossibleObject(diagram, DIA.ConnectionCrossingStyle_HasType); + ConnectionCrossings.Type type; + if (DIA.ConnectionCrossingStyle_Type_Gap.equals(typeRes)) { + type = ConnectionCrossings.Type.GAP; + } else if (DIA.ConnectionCrossingStyle_Type_Arc.equals(typeRes)) { + type = ConnectionCrossings.Type.ARC; + } else if (DIA.ConnectionCrossingStyle_Type_Square.equals(typeRes)) { + type = ConnectionCrossings.Type.SQUARE; + } else { + type = ConnectionCrossings.Type.NONE; + } + return new Pair<>(gap, type); + } + + }, listener); + } + } + + @Override + public void removedFromContext(ICanvasContext ctx) { + if (listener != null) { + listener.dispose(); + listener = null; + } + super.removedFromContext(ctx); + } + + class ConnectionCrossingStyleListener implements Listener> { + ICanvasContext context; + public ConnectionCrossingStyleListener(ICanvasContext context) { + this.context = context; + } + @Override + public void execute(final Pair result) { + context.getThreadAccess().asyncExec(new Runnable() { + @Override + public void run() { + ICanvasContext ctx = context; + if (ctx == null) + return; + if (ctx.isDisposed()) + return; + crossings.setWidth(result.first != null ? result.first : 0.0); + crossings.setType(result.second); + ccNode.repaint(); + } + }); + } + public void dispose() { + context = null; + } + @Override + public boolean isDisposed() { + return context == null || context.isDisposed(); + } + @Override + public void exception(Throwable t) { + ErrorLogger.defaultLogError(t); + } + } + +} 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.graphfile.ui.ontology/.classpath b/bundles/org.simantics.graphfile.ui.ontology/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui.ontology/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/bundles/org.simantics.graphfile.ui.ontology/.project b/bundles/org.simantics.graphfile.ui.ontology/.project new file mode 100644 index 000000000..740f3f884 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui.ontology/.project @@ -0,0 +1,34 @@ + + + org.simantics.graphfile.ui.ontology + + + + + + org.simantics.graph.builder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + org.simantics.graph.nature + + diff --git a/bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF b/bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF new file mode 100644 index 000000000..05c34057d --- /dev/null +++ b/bundles/org.simantics.graphfile.ui.ontology/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: http://www.simantics.org/GraphFileUI +Bundle-SymbolicName: org.simantics.graphfile.ui.ontology +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: org.simantics.graphfile.ui.ontology +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.simantics.modeling.ontology;bundle-version="1.2.0", + org.simantics.silk.ontology;bundle-version="1.1.0", + org.simantics.layer0;bundle-version="1.1.0", + org.simantics.viewpoint.ontology;bundle-version="1.2.0", + org.simantics.action.ontology;bundle-version="1.1.0", + org.simantics.graphfile.ontology;bundle-version="0.1.0" diff --git a/bundles/org.simantics.graphfile.ui.ontology/build.properties b/bundles/org.simantics.graphfile.ui.ontology/build.properties new file mode 100644 index 000000000..e85b630a0 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui.ontology/build.properties @@ -0,0 +1,5 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + graph.tg diff --git a/bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph b/bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph new file mode 100644 index 000000000..196296ec4 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui.ontology/graph/GraphFileUI.pgraph @@ -0,0 +1,48 @@ +L0 = +MOD = +SILK = +VP = +ACT = +GF = + +GFUI = : L0.Ontology + @L0.new + L0.HasResourceClass "org.simantics.graphfile.ui.ontology.GraphFileUIResource" : L0.String + +GFUI.BrowseContext : VP.BrowseContext + +ACTIONS = GFUI.BrowseContext.Actions : L0.Library + +ACTIONS.ImportFileDocument : ACT.Action +ACTIONS.ImportDocumentFolder : ACT.Action +ACTIONS.NewFileDocument : ACT.Action +ACTIONS.NewDocumentFolder : ACT.Action +ACTIONS.ExportFileDocument : ACT.Action +ACTIONS.ExportDocumentFolder : ACT.Action + +GFUI.ModelingBrowseContext : VP.BrowseContext + VP.BrowseContext.IsIncludedIn MOD.ModelingBrowseContext + @VP.relationChildRule L0.Library L0.ConsistsOf GF.Folder + @VP.relationChildRule L0.Library L0.ConsistsOf GF.File + @VP.relationChildRule GF.Folder L0.ConsistsOf GF.File + @VP.relationChildRule GF.Folder L0.ConsistsOf GF.Folder + + @VP.constantImageRule GF.Folder SILK.folder_page + @VP.constantImageRule GF.File SILK.page_white + @VP.customLabelRule GF.File VP.ResourceNameLabelRule + +GFUI.ModelingActionContext : VP.BrowseContext + VP.BrowseContext.IsIncludedIn MOD.ModelingActionContext + @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder + @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.NewActionCategory ACTIONS.NewDocumentFolder + @VP.actionContribution "File" L0.Library SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument + @VP.actionContribution "File" GF.Folder SILK.page_white VP.NewActionCategory ACTIONS.NewFileDocument + + @VP.actionContribution "Files" L0.Library SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument + @VP.actionContribution "Files" GF.Folder SILK.page_white VP.ImportActionCategory ACTIONS.ImportFileDocument + + @VP.actionContribution "Folder" L0.Library SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder + @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ImportActionCategory ACTIONS.ImportDocumentFolder + + @VP.actionContribution "File" GF.File SILK.page_white VP.ExportActionCategory ACTIONS.ExportFileDocument + @VP.actionContribution "Folder" GF.Folder SILK.folder_page VP.ExportActionCategory ACTIONS.ExportDocumentFolder \ No newline at end of file diff --git a/bundles/org.simantics.graphfile.ui/.classpath b/bundles/org.simantics.graphfile.ui/.classpath new file mode 100644 index 000000000..eca7bdba8 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/bundles/org.simantics.graphfile.ui/.project b/bundles/org.simantics.graphfile.ui/.project new file mode 100644 index 000000000..7533101c2 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/.project @@ -0,0 +1,28 @@ + + + org.simantics.graphfile.ui + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF b/bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF new file mode 100644 index 000000000..6c0a3817f --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: GraphfileUI +Bundle-SymbolicName: org.simantics.graphfile.ui;singleton:=true +Bundle-Version: 1.0.0.qualifier +Automatic-Module-Name: org.simantics.graphfile.ui +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: org.eclipse.ui.editors, + org.simantics.ui, + org.eclipse.jface.text;bundle-version="3.12.0", + org.simantics.graphfile.ontology, + org.slf4j.api;bundle-version="1.7.25", + org.simantics.document.ui;bundle-version="1.0.0" diff --git a/bundles/org.simantics.graphfile.ui/adapters.xml b/bundles/org.simantics.graphfile.ui/adapters.xml new file mode 100644 index 000000000..6eceb37e4 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/adapters.xml @@ -0,0 +1,50 @@ + + + + + + + + http://www.simantics.org/Layer0-0.0/ConsistsOf + + + + http://www.simantics.org/GraphFile-0.0/Folder + http://www.simantics.org/Layer0-0.0/ConsistsOf + + + + http://www.simantics.org/Layer0-0.0/ConsistsOf + File + + + + http://www.simantics.org/GraphFile-0.0/Folder + http://www.simantics.org/Layer0-0.0/ConsistsOf + + + + + http://www.simantics.org/Layer0-0.0/ConsistsOf + false + + + + \ No newline at end of file diff --git a/bundles/org.simantics.graphfile.ui/build.properties b/bundles/org.simantics.graphfile.ui/build.properties new file mode 100644 index 000000000..2df8c94f4 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/build.properties @@ -0,0 +1,6 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + plugin.xml,\ + adapters.xml diff --git a/bundles/org.simantics.graphfile.ui/plugin.xml b/bundles/org.simantics.graphfile.ui/plugin.xml new file mode 100644 index 000000000..925a7f3f8 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/plugin.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + diff --git a/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java new file mode 100644 index 000000000..d30210f30 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditor.java @@ -0,0 +1,92 @@ +package org.simantics.graphfile.ui.editor; + +import java.util.function.Supplier; + +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IEditorInput; +import org.eclipse.ui.IEditorSite; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.editors.text.TextEditor; +import org.simantics.Simantics; +import org.simantics.db.Session; +import org.simantics.db.common.request.ParametrizedRead; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.request.combinations.Combinators; +import org.simantics.ui.workbench.IResourceEditorInput; +import org.simantics.ui.workbench.ResourceEditorSupport; +import org.simantics.ui.workbench.TitleRequest; +import org.simantics.ui.workbench.TitleUpdater; +import org.simantics.ui.workbench.ToolTipRequest; +import org.simantics.ui.workbench.editor.input.InputValidationCombinators; + +/** + * @author Antti Villberg + */ +public class PlainTextEditor extends TextEditor { + + boolean isDisposed = false; + + ParametrizedRead INPUT_VALIDATOR = + Combinators.compose( + InputValidationCombinators.hasURI(), + InputValidationCombinators.extractInputResource() + ); + + ResourceEditorSupport support; + + public PlainTextEditor() { + super(); + setDocumentProvider(new PlainTextEditorDocumentProvider()); + //setSourceViewerConfiguration(new QueueTextEditorViewerConfiguration(new QueueTextEditorColorManager())); + } + + @Override + public void init(IEditorSite site, IEditorInput input) throws PartInitException { + super.init(site, input); + + support = new ResourceEditorSupport(this, INPUT_VALIDATOR); + support.activateValidation(); + try { + getResourceEditorInput().init(null); + } catch (DatabaseException e) { + throw new PartInitException("Failed to initialize " + input, e); + } + } + + protected IResourceEditorInput getResourceEditorInput() { + return (IResourceEditorInput) getEditorInput(); + } + + @Override + public void createPartControl(Composite parent) { + super.createPartControl(parent); + updatePartName(); + } + + private void updatePartName() { + setPartName(getEditorInput().getName()); + + Session session = Simantics.peekSession(); + if (session != null) { + Supplier disposedCallback = () -> isDisposed; + session.asyncRequest( + new TitleRequest(null, getResourceEditorInput()), + new TitleUpdater(getSite().getShell().getDisplay(), this::setPartName, disposedCallback)); + session.asyncRequest( + new ToolTipRequest(getSite().getId(), getResourceEditorInput()), + new TitleUpdater(getSite().getShell().getDisplay(), this::setTitleToolTip, disposedCallback)); + } + + } + + @Override + public void dispose() { + isDisposed = true; + if (support != null) { + support.dispose(); + support = null; + } + super.dispose(); + } + +} diff --git a/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java new file mode 100644 index 000000000..3eb40ead5 --- /dev/null +++ b/bundles/org.simantics.graphfile.ui/src/org/simantics/graphfile/ui/editor/PlainTextEditorDocumentProvider.java @@ -0,0 +1,108 @@ +package org.simantics.graphfile.ui.editor; + +import java.io.StringWriter; +import java.nio.charset.StandardCharsets; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.operation.IRunnableContext; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.source.AnnotationModel; +import org.eclipse.jface.text.source.IAnnotationModel; +import org.eclipse.ui.texteditor.AbstractDocumentProvider; +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.document.DocumentResource; +import org.simantics.graphfile.ontology.GraphFileResource; +import org.simantics.ui.workbench.ResourceEditorInput; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class PlainTextEditorDocumentProvider extends AbstractDocumentProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(PlainTextEditor.class); + + protected String currentText; + + @Override + protected IDocument createDocument(Object element) throws CoreException { + ResourceEditorInput input = (ResourceEditorInput)element; + final Resource resource = input.getResource(); + try { + return Simantics.getSession().syncRequest(new UniqueRead() { + @Override + public Document perform(ReadGraph graph) throws DatabaseException { + + GraphFileResource GF = GraphFileResource.getInstance(graph); + DocumentResource DOC = DocumentResource.getInstance(graph); + if (!graph.isInstanceOf(resource, DOC.FileDocument)) + throw new DatabaseException("Invalid input resource for PlainTextEditor: " + NameUtils.getSafeName(graph, resource)); + + byte[] bytes = graph.getPossibleRelatedValue(resource, GF.HasFiledata, Bindings.BYTE_ARRAY); + + currentText = bytes != null ? new String(bytes, StandardCharsets.UTF_8) : ""; + + return new Document(currentText); + + } + }); + } catch (DatabaseException e) { + StringWriter sw = new StringWriter(); + LOGGER.error("Failed to create document", e); + return new Document(sw.toString()); + } + } + + @Override + protected IAnnotationModel createAnnotationModel(Object element) + throws CoreException { + return new AnnotationModel(); + } + + @Override + protected void doSaveDocument(IProgressMonitor monitor, Object element, + IDocument document, boolean overwrite) throws CoreException { + ResourceEditorInput input = (ResourceEditorInput)element; + final Resource resource = input.getResource(); + final String text = document.get(); + currentText = text; + Simantics.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.markUndoPoint(); + GraphFileResource GF = GraphFileResource.getInstance(graph); + graph.claimLiteral(resource, GF.HasFiledata, text.getBytes(StandardCharsets.UTF_8)); + graph.claimLiteral(resource, GF.LastModified, System.currentTimeMillis()); + } + }); + } + + @Override + protected IRunnableContext getOperationRunner(IProgressMonitor monitor) { + return null; + } + + @Override + public boolean isModifiable(Object element) { + return true; + } + + @Override + public boolean isReadOnly(Object element) { + return false; + } + + @Override + public boolean canSaveDocument(Object element) { + return !getDocument(element).get().equals(currentText); + } + +} 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/diagramEditor/DiagramViewer.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.java index 409aecbea..489ebd6c7 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.java @@ -67,6 +67,7 @@ import org.simantics.diagram.handler.DeleteHandler; import org.simantics.diagram.handler.ExpandSelectionHandler; import org.simantics.diagram.handler.SimpleElementTransformHandler; import org.simantics.diagram.layer.ILayersViewPage; +import org.simantics.diagram.participant.ConnectionCrossingsParticipant; import org.simantics.diagram.participant.ContextUtil; import org.simantics.diagram.participant.PointerInteractor2; import org.simantics.diagram.participant.SGFocusParticipant; @@ -330,6 +331,7 @@ public class DiagramViewer //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID)); //ctx.add(new TooltipParticipant()); ctx.add(new TerminalTooltipParticipant()); + ctx.add(new ConnectionCrossingsParticipant(getInputResource())); } protected void addPainterParticipants(ICanvasContext ctx) { 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 1db2ba151..8f223a622 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 @@ -35,6 +35,7 @@ import org.simantics.diagram.handler.CopyPasteStrategy; import org.simantics.diagram.handler.DefaultCopyPasteStrategy; import org.simantics.diagram.handler.DeleteHandler; import org.simantics.diagram.handler.SimpleElementTransformHandler; +import org.simantics.diagram.participant.ConnectionCrossingsParticipant; import org.simantics.diagram.query.DiagramRequests; import org.simantics.diagram.runtime.RuntimeDiagramManager; import org.simantics.diagram.stubs.DiagramResource; @@ -249,6 +250,7 @@ public class DiagramSceneGraphProvider implements ICanvasSceneGraphProvider, IDi ctx.add( new Selection() ); ctx.add( new DiagramParticipant() ); ctx.add( new ElementPainter(true) ); + ctx.add( new ConnectionCrossingsParticipant(resource)); //ctx.add( new ElementHeartbeater() ); ctx.add( new ZOrderHandler() ); 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/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.modeling/src/org/simantics/modeling/utils/DumpOntologyStructure.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/DumpOntologyStructure.java index 5bb3d9ca2..e058f2c36 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/DumpOntologyStructure.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/DumpOntologyStructure.java @@ -5,7 +5,9 @@ import java.io.IOException; import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.TreeMap; import org.simantics.Simantics; @@ -32,17 +34,48 @@ public class DumpOntologyStructure { private Resource ontology; private Map names = new HashMap<>(); - private Map parents = new HashMap<>(); + private Map parents = new TreeMap<>(); private Map libraryFolders = new HashMap<>(); private Map contentDumps = new HashMap<>(); private void readNameAndParent(ReadGraph graph, Resource container, Resource r) throws DatabaseException { + String name = NameUtils.getSafeName(graph, r); parents.put(r, container); - names.put(r, NameUtils.getSafeName(graph, r)); + names.put(r, FileUtils.escapeFileName(name)); } - private Collection containers() { - return parents.values(); + /* + * This shall return containers sorted by full path. + * This makes processing order stable and ensures that + * directories are processed before their contents. + */ + private Collection sortedContainers(File rootFolder) { + Set parentSet = new HashSet(parents.values()); + TreeMap result = new TreeMap<>(); + for(Resource r : parentSet) { + File f = getFolder(rootFolder, r); + result.put(f.getAbsolutePath(), r); + } + return result.values(); + } + + private Collection sortedResources(File rootFolder) { + TreeMap result = new TreeMap<>(); + for(Resource r : parents.keySet()) { + byte[] dump = contentDumps.get(r); + if(dump == null) + dump = "".getBytes(StandardCharsets.UTF_8); + if(isParent(r)) { + if(dump.length > 0) { + File f = new File(getFolder(rootFolder, r), "__contents__"); + result.put(f.getAbsolutePath(), r); + } + } else { + File f = getFile(rootFolder, r); + result.put(f.getAbsolutePath(), r); + } + } + return result.values(); } private void readHierarchy(ReadGraph graph, Resource container) throws DatabaseException { @@ -110,37 +143,56 @@ public class DumpOntologyStructure { public void write(File unsafeFolder) throws IOException { File folder = escapeFile(unsafeFolder); FileUtils.delete(folder.toPath()); - folder.mkdirs(); + folder.getParentFile().mkdirs(); writeDirectories(folder); writeResources(folder); } + Resource getParent(Resource r) { + return parents.get(r); + } + private File getFolder(File root, Resource library) { if(ontology.equals(library)) return root; - Resource parent = parents.get(library); + Resource parent = getParent(library); if(parent == null) throw new IllegalStateException("null parent for " + library); File parentFolder = getFolder(root, parent); - return new File(parentFolder, FileUtils.escapeFileName(names.get(library))); + return new File(parentFolder, names.get(library)); } private File getFile(File rootFolder, Resource r) { - Resource parent = parents.get(r); + Resource parent = getParent(r); File folder = getFolder(rootFolder, parent); - return new File(folder, FileUtils.escapeFileName(names.get(r))); + return new File(folder, names.get(r)); } + private File makeUnique(File original, Resource r) { + int counter = 2; + File file = new File(original.getParent(), original.getName()); + File test = file; + while(test.exists()) { + // Here we have a name clash with small and big letters! (windows) + test = new File(file.getParent(), file.getName() + "____" + (counter++)); + } + // Enforce this renaming in future operations also + names.put(r, test.getName()); + return test; + } + private void writeDirectories(File rootFolder) { - for(Resource library : containers()) { - File folder = getFolder(rootFolder, library); + // Here stuff shall be returned in alphabetical order + for(Resource library : sortedContainers(rootFolder)) { + File folder = makeUnique(getFolder(rootFolder, library), library); folder.mkdirs(); libraryFolders.put(library, folder); } } private void writeResources(File rootFolder) throws IOException { - for(Resource r : parents.keySet()) { + // Here stuff shall be returned in alphabetical order + for(Resource r : sortedResources(rootFolder)) { writeResource(rootFolder, r); } } @@ -162,7 +214,7 @@ public class DumpOntologyStructure { } private void write(File rootFolder, Resource resource, byte[] bytes) throws IOException { - FileUtils.writeFile(getFile(rootFolder, resource), bytes); + FileUtils.writeFile(makeUnique(getFile(rootFolder, resource), resource), bytes); } } \ No newline at end of file diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java new file mode 100644 index 000000000..a46c4e748 --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ConnectionCrossingsNode.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * Copyright (c) 2020 Association for Decentralized Information Management in + * Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Semantum Oy - initial API and implementation + *******************************************************************************/ +package org.simantics.scenegraph.g2d.nodes; + +import java.awt.Graphics2D; +import java.awt.geom.Rectangle2D; + +import org.simantics.diagram.connection.rendering.ConnectionCrossings; +import org.simantics.diagram.connection.rendering.ConnectionRenderingHints; +import org.simantics.scenegraph.g2d.G2DNode; + +public class ConnectionCrossingsNode extends G2DNode { + + private static final long serialVersionUID = -696142275610396889L; + + private ConnectionCrossings crossings; + + @Override + public void render(Graphics2D g) { + crossings.reset(); + if (crossings.getWidth() > 0 && crossings.getType() != ConnectionCrossings.Type.NONE) { + g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, crossings); + } else { + g.setRenderingHint(ConnectionRenderingHints.KEY_PATH_MODIFIER, null); + } + } + + public void setCrossings(ConnectionCrossings crossings) { + this.crossings = crossings; + } + + @Override + public Rectangle2D getBoundsInLocal() { + return null; + } + + public ConnectionCrossings getConnectionCrossings() { + return crossings; + } +} diff --git a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/Activator.java b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/Activator.java index a14be4896..4e1d01816 100644 --- a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/Activator.java +++ b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/Activator.java @@ -1,14 +1,11 @@ package org.simantics.scl.reflection.internal; -import java.util.concurrent.ForkJoinPool; - import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.osgi.framework.Bundle; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; -import org.simantics.scl.reflection.internal.registry.BindingRegistry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,21 +20,6 @@ public class Activator implements BundleActivator { public void start(BundleContext context) throws Exception { this.context = context; instance = this; - - primeBindingRegistry(); - } - - private static void primeBindingRegistry() { - LOGGER.info("Priming BindingRegistry"); - ForkJoinPool.commonPool().submit(() -> { - try { - // this forces static initialzation of the registry in advance - BindingRegistry.primeBindingRegistry(); - } catch (Exception e) { - LOGGER.error("Could not prime binding registry", e); - } - LOGGER.info("Priming done"); - }); } @Override diff --git a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/BindingRegistry.java b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/BindingRegistry.java index 648e314d9..f9bf3fadc 100644 --- a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/BindingRegistry.java +++ b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/BindingRegistry.java @@ -49,12 +49,6 @@ public class BindingRegistry { } } - public static void primeBindingRegistry() { - for (Namespace ns : namespaces.values()) { - ns.initializeValues(); - } - } - static { initialize(); if (DEBUG_INIT) { diff --git a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/Namespace.java b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/Namespace.java index 5234d3bfc..daaa204db 100644 --- a/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/Namespace.java +++ b/bundles/org.simantics.scl.reflection/src/org/simantics/scl/reflection/internal/registry/Namespace.java @@ -275,7 +275,7 @@ public class Namespace { } } - synchronized void initializeValues() { + private synchronized void initializeValues() { if(values == null) { initializeTypes(); TypeBindingScheme scheme = MinimalTypeBindingScheme.INSTANCE; diff --git a/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java b/bundles/org.simantics.scl.runtime/src/org/simantics/scl/runtime/exceptions/CheckedFunctionException.java new file mode 100644 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.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/bundles/pom.xml b/bundles/pom.xml index 59e88c12b..e1abeaf48 100644 --- a/bundles/pom.xml +++ b/bundles/pom.xml @@ -133,6 +133,8 @@ org.simantics.graph.db org.simantics.graphfile org.simantics.graphfile.ontology + org.simantics.graphfile.ui + org.simantics.graphfile.ui.ontology org.simantics.graphviz org.simantics.graphviz.ui org.simantics.gnuplot 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