]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/utils/HeadlessComponentTypePropertiesResultRequest.java
Support for creating shared ontology dump to git
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / utils / HeadlessComponentTypePropertiesResultRequest.java
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 (file)
index 0000000..a2f7138
--- /dev/null
@@ -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<ComponentTypePropertiesResult> {
+    
+    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<ComponentTypeViewerPropertyInfo> result = new ArrayList<>();
+        List<NamedResource> 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<String>() {
+
+                @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.<PropertyInfo>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<Variable,Object> 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