From e6e555f4c17e686c44d0681a01eab17d0ec6f2aa Mon Sep 17 00:00:00 2001 From: jsimomaa Date: Fri, 1 Feb 2019 09:39:08 +0200 Subject: [PATCH] Initial version of validating derived properties formulas Note: untested the procedural use case and still the solution can be a bit hackish with e.g. constructing Variables and passing them along However, at least this does something instead of just silently failing gitlab #252 Change-Id: I209d9d585379b7b987861355589427ee90375738 --- .../StandardGraphPropertyVariable.java | 9 ++- .../ComponentTypeViewerData.java | 35 ++++++--- .../DerivedPropertiesSection.java | 78 ++++++++++++++----- .../synchronization/client/Synchronizer.java | 1 - .../scl/CompileStructuralValueRequest.java | 10 ++- 5 files changed, 100 insertions(+), 33 deletions(-) diff --git a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java index 2dcb6e00a..9b0befc78 100644 --- a/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java +++ b/bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/variable/StandardGraphPropertyVariable.java @@ -26,6 +26,7 @@ import org.simantics.db.layer0.exception.PendingVariableException; import org.simantics.db.layer0.function.All; import org.simantics.db.layer0.request.PropertyInfo; import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.scl.SCLDatabaseException; import org.simantics.db.layer0.util.Layer0Utils; import org.simantics.layer0.Layer0; import org.simantics.utils.Development; @@ -149,9 +150,11 @@ public class StandardGraphPropertyVariable extends AbstractPropertyVariable { try { - return (T)getValueAccessor(graph).getValue(graph, this, binding); - } catch (PendingVariableException e) { - throw e; + return (T) getValueAccessor(graph).getValue(graph, this, binding); + } catch (SCLDatabaseException e) { // these can be thrown when compiling e.g. derived properties + throw e; + } catch (MissingVariableValueException | PendingVariableException e) { + throw e; } catch (Throwable t) { throw new MissingVariableValueException(t); } diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java index 048e0840e..1c4b22ee0 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/ComponentTypeViewerData.java @@ -3,6 +3,8 @@ package org.simantics.modeling.ui.componentTypeEditor; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -47,6 +49,7 @@ import org.simantics.layer0.Layer0; import org.simantics.modeling.userComponent.ComponentTypeCommands; import org.simantics.scl.runtime.function.Function2; import org.simantics.scl.runtime.function.Function4; +import org.simantics.utils.threads.ThreadUtils; import org.simantics.utils.ui.ErrorLogger; public class ComponentTypeViewerData { @@ -373,18 +376,32 @@ public class ComponentTypeViewerData { if (validator != null) { org.eclipse.swt.widgets.Listener validationListener = new org.eclipse.swt.widgets.Listener() { + + private ScheduledFuture future; + @Override public void handleEvent(Event e) { final String newValue = text.getText(); - String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue); - if (error != null) { - text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED)); - text.setToolTipText(error); - return; - } else { - text.setBackground(null); - text.setToolTipText(null); - } + if (future != null && !future.isCancelled()) + future.cancel(true); + future = ThreadUtils.getNonBlockingWorkExecutor().schedule(() -> { + String error = validator.apply(Simantics.getSession(), componentType, propertyInfo.resource, newValue); + if (!text.isDisposed()) { + text.getDisplay().asyncExec(() -> { + if (!text.isDisposed()) { + if (error != null) { + text.setBackground(text.getDisplay().getSystemColor(SWT.COLOR_RED)); + text.setToolTipText(error); + return; + } else { + text.setBackground(null); + text.setToolTipText(null); + } + } + + }); + } + }, 500, TimeUnit.MILLISECONDS); } }; text.addListener(SWT.Modify, validationListener); diff --git a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java index 869d5e32a..0f7bff396 100644 --- a/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java +++ b/bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/componentTypeEditor/DerivedPropertiesSection.java @@ -32,14 +32,25 @@ import org.simantics.db.ReadGraph; import org.simantics.db.RequestProcessor; import org.simantics.db.Resource; import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; import org.simantics.db.common.request.UniqueRead; import org.simantics.db.common.request.WriteRequest; import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.request.PropertyInfo; +import org.simantics.db.layer0.request.PropertyInfoRequest; +import org.simantics.db.layer0.variable.StandardGraphChildVariable; +import org.simantics.db.layer0.variable.StandardGraphPropertyVariable; +import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; +import org.simantics.modeling.scl.CompileProceduralSCLMonitorRequest; +import org.simantics.modeling.scl.CompileSCLMonitorRequest; import org.simantics.modeling.userComponent.ComponentTypeCommands; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function1; import org.simantics.scl.runtime.function.Function4; import org.simantics.structural.stubs.StructuralResource2; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class DerivedPropertiesSection implements ComponentTypeViewerSection { private static final String[] COLUMN_NAMES = { @@ -62,6 +73,8 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { } }; + private static final Logger LOGGER = LoggerFactory.getLogger(DerivedPropertiesSection.class); + ComponentTypeViewerData data; Table table; TableColumn[] columns; @@ -267,23 +280,33 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { StructuralResource2 STR = StructuralResource2.getInstance(graph); - Resource indexRoot = graph.syncRequest(new PossibleIndexRoot(componentType)); - + // TODO: this is a bit hackish but should get the job done in most parts and + // importantly indicates something for the user + PropertyInfo info = graph.syncRequest(new PropertyInfoRequest(relation), TransientCacheAsyncListener.instance()); + Variable parent = new StandardGraphChildVariable(null, null, componentType) { + + public Resource getType(ReadGraph graph) throws DatabaseException { + return componentType; + }; + + public Variable getPossibleProperty(ReadGraph graph, String name) throws DatabaseException { + Variable prop = super.getPossibleProperty(graph, name); + if (prop != null) { + return prop; + } else { + return getChild(graph, name); + } + }; + }; + for(Resource literal : graph.getAssertedObjects(componentType, relation)) { try { - // TODO validation + Variable context = new StandardGraphPropertyVariable(parent, null, null, info, literal); if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) { - //Layer0 L0 = Layer0.getInstance(graph); - //Resource environment = graph.getPossibleObject(literal, L0.SCLValue_environment); - //ContextModule context = graph.sync(new TypeMonitorContextRequest(componentType)); - //String SCLMain = graph.syncRequest(new SCLMainModuleRequest(indexRoot)); - //CompilationContext cc = new CompilationContext(environment, context, SCLMain); - //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); + CompileProceduralSCLMonitorRequest.compileAndEvaluate(graph, context); } else { - //CompilationContext cc = new CompileSCLMonitorRequest(literal, componentType, indexRoot).getContext(graph); - //graph.syncRequest(new ActualCompileRequest(expression, cc), TransientCacheListener.instance()); - //graph.syncRequest(new CompileSCLMonitorRequest(graph, context)); + compileAndEvaluate(graph, context, expression); } } catch (Exception e) { @@ -292,22 +315,39 @@ public class DerivedPropertiesSection implements ComponentTypeViewerSection { if(index > 0) msg = msg.substring(index); return msg; } - } - return null; - } }); } catch (DatabaseException e) { - e.printStackTrace(); + LOGGER.error("Could not validate ", e); } - return null; - } + public static void compileAndEvaluate(ReadGraph graph, Variable context, String expression) throws DatabaseException { + SCLContext sclContext = SCLContext.getCurrent(); + Object oldGraph = sclContext.get("graph"); + try { + CompileSCLMonitorRequest compileSCLMonitorRequest = new CompileSCLMonitorRequest(graph, context) { + @Override + protected String getExpressionText(ReadGraph graph) throws DatabaseException { + return expression; + } + }; + Function1 exp = graph.syncRequest(compileSCLMonitorRequest); + sclContext.put("graph", graph); + //return exp.apply(context.getParent(graph)); + } catch (DatabaseException e) { + throw (DatabaseException)e; + } catch (Throwable t) { + throw new DatabaseException(t); + } finally { + sclContext.put("graph", oldGraph); + } + } + @Override public void update(ComponentTypePropertiesResult result) { if (table.isDisposed()) diff --git a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java index b2b4ea2ec..2552192ef 100644 --- a/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java +++ b/bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/client/Synchronizer.java @@ -124,7 +124,6 @@ public class Synchronizer { while((cur = cur.getCause()) != null) { if(!(cur instanceof MissingVariableValueException)) { handler.reportProblem(cur.getMessage()); - break; } } } catch (Exception e) { diff --git a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java index 6e9975b68..5e564cc91 100644 --- a/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java +++ b/bundles/org.simantics.structural2/src/org/simantics/structural2/scl/CompileStructuralValueRequest.java @@ -5,6 +5,7 @@ import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.IndexRoot; +import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.variable.Variable; import org.simantics.layer0.Layer0; @@ -43,7 +44,14 @@ public class CompileStructuralValueRequest extends AbstractCompileStructuralValu sclContext.put("graph", graph); return exp.apply(context); } catch (Throwable t) { - throw new DatabaseException("Compiling structural value request for component=" + request.component + ", literal=" + request.literal + " and relation " + request.relation + " failed!", t); + String componentName = NameUtils.getSafeName(graph, request.component); + String literalName = NameUtils.getSafeName(graph, request.literal); + String relationName = NameUtils.getSafeName(graph, request.relation); + StringBuilder sb = new StringBuilder("Compiling structural value request for component ") + .append(componentName).append(" ").append(request.component).append(" , literal ") + .append(literalName).append(" ").append(request.literal).append(" and relation ") + .append(relationName).append(" ").append(request.relation).append(" failed!"); + throw new DatabaseException(sb.toString(), t); } finally { sclContext.put("graph", oldGraph); } -- 2.43.2