]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/issue/SCLExpressionIssueProvider.java
SCL expressions to SCL Issues view
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / issue / SCLExpressionIssueProvider.java
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/issue/SCLExpressionIssueProvider.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/issue/SCLExpressionIssueProvider.java
new file mode 100644 (file)
index 0000000..bbbd6b0
--- /dev/null
@@ -0,0 +1,165 @@
+package org.simantics.modeling.scl.issue;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.Simantics;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.SyncListenerAdapter;
+import org.simantics.db.common.request.UniqueRead;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingUtils;
+import org.simantics.scl.compiler.errors.CompilationError;
+import org.simantics.scl.compiler.errors.Locations;
+import org.simantics.scl.osgi.issues.SCLIssueProviderFactory;
+import org.simantics.scl.osgi.issues.SCLIssueProviderFactory.SCLIssueProvider;
+import org.simantics.scl.osgi.issues.SCLIssuesTableEntry;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function1;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.ui.workbench.action.DefaultActions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SCLExpressionIssueProvider implements SCLIssueProvider {
+
+    public static class SCLExpressionIssueProviderFactory implements SCLIssueProviderFactory {
+
+        @Override
+        public SCLIssueProvider getSCLIssueProvider() {
+            return new SCLExpressionIssueProvider();
+        }
+
+    }
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(SCLExpressionIssueProvider.class);
+    private List<SCLIssuesTableEntry> currentIssues = new ArrayList<>();
+    private boolean disposed = false;
+
+    SCLExpressionIssueProvider() {
+    }
+
+    @Override
+    public void listenIssues(Runnable callback) {
+        Simantics.getSession().asyncRequest(new UniqueRead<List<SCLIssuesTableEntry>>() {
+
+            @Override
+            public List<SCLIssuesTableEntry> perform(ReadGraph graph) throws DatabaseException {
+                Layer0 L0 = Layer0.getInstance(graph);
+                Set<Resource> indexRoots = new TreeSet<Resource>();
+                for(Resource ontology : Layer0Utils.listOntologies(graph)) {
+                    if (graph.isInstanceOf(ontology, L0.SharedOntology)) {
+                        indexRoots.add(ontology);
+                    }
+                }
+
+                for(Resource child : graph.getObjects(Simantics.getProjectResource(), L0.ConsistsOf)) {
+                    if (graph.isInstanceOf(child, L0.IndexRoot)) {
+                        indexRoots.add(child);
+                    }
+                }
+
+                StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+                List<SCLIssuesTableEntry> results = new ArrayList<>();
+
+                for (Resource ontology : indexRoots) {
+                    List<Resource> components = ModelingUtils.searchByTypeShallow(graph, ontology, STR.Component);
+                    for (Resource component : components) {
+
+                        for (Resource predicate : graph.getPredicates(component)) {
+                            if (graph.isSubrelationOf(predicate, L0.HasProperty)) {
+                                for (Resource object : graph.getObjects(component, predicate)) {
+                                    if (graph.isInstanceOf(object, L0.SCLValue)) {
+                                        Resource type = graph.getPossibleType(object, L0.SCLValue);
+                                        Variable typeVariable = Variables.getVariable(graph, type);
+
+                                        Function1<Variable, String> func = typeVariable.getPossiblePropertyValue(graph, "validator");
+                                        if (func == null) {
+                                            // No validator available
+                                            if (LOGGER.isTraceEnabled())
+                                                LOGGER.trace("No validator available for " + typeVariable.getURI(graph));
+                                            continue;
+                                        }
+
+                                        Variable componentVariable = Variables.getVariable(graph, component);
+                                        Variable propertyVariable = componentVariable.getProperty(graph, predicate);
+
+                                        SCLContext sclContext = SCLContext.getCurrent();
+                                        Object oldGraph = sclContext.get("graph");
+                                        try {
+                                            sclContext.put("graph", graph);
+                                            String validatorValue = func.apply(propertyVariable);
+                                            if (validatorValue != null && !validatorValue.isEmpty()) {
+                                                results.add(new SCLIssuesTableEntry(propertyVariable.getURI(graph), new CompilationError(Locations.NO_LOCATION, validatorValue.replace("\n", " "))) {
+                                                    @Override
+                                                    public void openLocation() {
+                                                        openResource(Display.getCurrent().getActiveShell(), component);
+                                                    }
+                                                });
+                                            }
+                                        } catch (Throwable t) {
+                                            LOGGER.error("Failed to invoke type validator function " + func, t);
+                                        } finally {
+                                            sclContext.put("graph", oldGraph);
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                return results;
+            }
+        }, new SyncListenerAdapter<List<SCLIssuesTableEntry>>() {
+
+            @Override
+            public void execute(ReadGraph graph, List<SCLIssuesTableEntry> result) {
+                synchronized (currentIssues) {
+                    currentIssues.clear();
+                    currentIssues.addAll(result);
+                }
+                if (callback != null)
+                    callback.run();
+            }
+
+            @Override
+            public void exception(ReadGraph graph, Throwable t) {
+                LOGGER.error("Could not get SCL issues", t);
+            }
+
+            @Override
+            public boolean isDisposed() {
+                return disposed;
+            }
+        });
+    }
+
+    @Override
+    public List<SCLIssuesTableEntry> getIssues() {
+        synchronized (currentIssues) {
+            List<SCLIssuesTableEntry> results = new ArrayList<>(currentIssues);
+            return results;
+        }
+    }
+
+    @Override
+    public void dispose() {
+        disposed = true;
+    }
+
+    private static void openResource(Shell shell, Resource resource) {
+        DefaultActions.performDefaultAction(shell, new StructuredSelection(resource));
+    }
+
+}