X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Futils%2FHeadlessComponentTypePropertiesResultRequest.java;fp=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Futils%2FHeadlessComponentTypePropertiesResultRequest.java;h=a2f7138b44bdd048c8b5dee813d1d9e9bfaaee85;hb=0b4ab685b0aa54ba8fbe0a5742e27726c862cfd9;hp=0000000000000000000000000000000000000000;hpb=6fc013b9a70621230879014575b244f3714d5ba8;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/HeadlessComponentTypePropertiesResultRequest.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/HeadlessComponentTypePropertiesResultRequest.java new file mode 100644 index 000000000..a2f7138b4 --- /dev/null +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/utils/HeadlessComponentTypePropertiesResultRequest.java @@ -0,0 +1,238 @@ +package org.simantics.modeling.utils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.databoard.binding.error.BindingException; +import org.simantics.databoard.type.Datatype; +import org.simantics.databoard.type.NumberType; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.common.NamedResource; +import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener; +import org.simantics.db.common.request.IsEnumeratedValue; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.utils.CommonDBUtils; +import org.simantics.db.common.utils.NameUtils; +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.util.Layer0Utils; +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.operation.Layer0X; +import org.simantics.scl.runtime.SCLContext; +import org.simantics.scl.runtime.function.Function1; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.utils.ui.ErrorLogger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class HeadlessComponentTypePropertiesResultRequest extends UniqueRead { + + private static final Logger LOGGER = LoggerFactory.getLogger(HeadlessComponentTypePropertiesResultRequest.class); + + protected final Resource componentType; + + /** + * @param componentTypeViewer + */ + public HeadlessComponentTypePropertiesResultRequest(Resource componentType) { + this.componentType = componentType; + } + + protected void readSectionSpecificData(ReadGraph graph, ComponentTypeViewerPropertyInfo info) throws DatabaseException { + } + + @Override + public ComponentTypePropertiesResult perform(ReadGraph graph) throws DatabaseException { + List result = new ArrayList<>(); + List connectionPoints = new ArrayList<>(); + Layer0 L0 = Layer0.getInstance(graph); + Layer0X L0X = Layer0X.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + boolean typeIsImmutable = graph.isImmutable(componentType) + || graph.hasStatement(componentType, STR.ComponentType_Locked) + || Layer0Utils.isPublished(graph, componentType) + || Layer0Utils.isContainerPublished(graph, componentType); + + for(Resource relation : graph.getObjects(componentType, L0.DomainOf)) { + if(graph.isSubrelationOf(relation, L0.HasProperty)) { + String name = graph.getRelatedValue(relation, L0.HasName); + String type = graph.getPossibleRelatedValue(relation, L0.RequiresValueType); + String label = graph.getPossibleRelatedValue(relation, L0.HasLabel); + if (label == null) + label = ""; //$NON-NLS-1$ + String description = graph.getPossibleRelatedValue(relation, L0.HasDescription); + if (description == null) + description = ""; //$NON-NLS-1$ + NumberType numberType = null; + if(type == null) + type = "Double"; //$NON-NLS-1$ + String unit = graph.getPossibleRelatedValue(relation, L0X.HasUnit, Bindings.STRING); + String defaultValue = "0"; //$NON-NLS-1$ + String expression = null; + + for(Resource assertion : graph.getAssertedObjects(componentType, relation)) { + try { + expression = graph.getPossibleRelatedValue(assertion, L0.SCLValue_expression, Bindings.STRING); + if(expression != null) { + defaultValue = "=" + expression; //$NON-NLS-1$ + } else if (graph.sync(new IsEnumeratedValue(assertion))) { + defaultValue = CommonDBUtils.getEnumerationValueName(graph, assertion); + } else { + Datatype dt = getPossibleDatatype(graph, assertion); + if (dt == null) + continue; + if (dt instanceof NumberType) + numberType = (NumberType) dt; + Binding binding = Bindings.getBinding(dt); + Object value = graph.getValue(assertion, binding); + try { + defaultValue = binding.toString(value, true); + } catch (BindingException e) { + ErrorLogger.defaultLogError(e); + } + } + } catch(DatabaseException e) { + ErrorLogger.defaultLogError(e); + } + } + + String valid = expression != null ? validateMonitorExpression(graph, componentType, relation, expression) : null; + + boolean immutable = typeIsImmutable || graph.isImmutable(relation); + ComponentTypeViewerPropertyInfo info = + new ComponentTypeViewerPropertyInfo(relation, name, type, defaultValue, numberType, unit, label, description, expression, valid, immutable); + + readSectionSpecificData(graph, info); + + result.add(info); + + } else if (graph.isInstanceOf(relation, STR.ConnectionRelation)) { + NamedResource nr = new NamedResource(NameUtils.getSafeName(graph, relation), relation); + connectionPoints.add(nr); + } + } + Collections.sort(result); + return new ComponentTypePropertiesResult(result, connectionPoints, typeIsImmutable); + } + + private Datatype getPossibleDatatype(ReadGraph graph, Resource literal) throws DatabaseException { + Binding binding = Bindings.getBindingUnchecked(Datatype.class); + for (Resource dataTypeResource : graph.getObjects(literal, Layer0.getInstance(graph).HasDataType)) { + Datatype dt = graph.getPossibleValue(dataTypeResource, binding); + if (dt != null) + return dt; + } + return null; + } + + public static String validateMonitorExpression(final RequestProcessor processor, final Resource componentType, final Resource relation, final String expression) { + + try { + return processor.sync(new UniqueRead() { + + @Override + public String perform(ReadGraph graph) throws DatabaseException { + + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + // 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 { + Variable context = new StandardGraphPropertyVariable(parent, null, null, info, literal); + if(graph.isInstanceOf(componentType, STR.ProceduralComponentType)) { + CompileProceduralSCLMonitorRequest.compileAndEvaluate(graph, context); + } else { + compileAndEvaluate(graph, context, expression); + } + + } catch (Exception e) { + String msg = e.getMessage(); + int index = msg.indexOf(":"); //$NON-NLS-1$ + if(index > 0) msg = msg.substring(index); + return msg; + } + } + return null; + } + + }); + } catch (DatabaseException e) { + 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 ValidationCompilationRequest(graph, context, 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); + } + } + + private static final class ValidationCompilationRequest extends CompileSCLMonitorRequest { + private final String expression; + + private ValidationCompilationRequest(ReadGraph graph, Variable context, String expression) + throws DatabaseException { + super(graph, context); + this.expression = expression; + } + + @Override + protected String getExpressionText(ReadGraph graph) throws DatabaseException { + return expression; + } + + @Override + public int hashCode() { + return super.hashCode() + 37 * expression.hashCode(); + } + + @Override + public boolean equals(Object obj) { + return super.equals(obj) && ((ValidationCompilationRequest)obj).expression.equals(expression); + } + } + +} \ No newline at end of file