]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/features/DependencyValidationFeature.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / features / DependencyValidationFeature.java
diff --git a/bundles/org.simantics.project/src/org/simantics/project/features/DependencyValidationFeature.java b/bundles/org.simantics.project/src/org/simantics/project/features/DependencyValidationFeature.java
new file mode 100644 (file)
index 0000000..45ca05b
--- /dev/null
@@ -0,0 +1,172 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.project.features;\r
+\r
+import java.net.URI;\r
+import java.net.URISyntaxException;\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IConfigurationElement;\r
+import org.eclipse.core.runtime.IExecutableExtension;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.VirtualGraph;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.common.CommentMetadata;\r
+import org.simantics.db.common.request.WriteRequest;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.AssumptionException;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.exception.ResourceNotFoundException;\r
+import org.simantics.db.service.VirtualGraphSupport;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.project.exception.ProjectException;\r
+import org.simantics.project.ontology.ProjectResource;\r
+import org.simantics.scl.reflection.OntologyVersions;\r
+\r
+/**\r
+ * A project feature for validating that a set of namespaces (URIs) are\r
+ * reachable in the database for which this feature is configured.\r
+ * \r
+ * The URIs are described as class arguments in the extension class spec (after\r
+ * ':' character).\r
+ * \r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class DependencyValidationFeature extends AbstractProjectFeature implements IExecutableExtension {\r
+\r
+    private String   virtualGraphId;\r
+    private String[] uris = {};\r
+\r
+    public DependencyValidationFeature() {\r
+    }\r
+\r
+    public DependencyValidationFeature(String virtualGraphId, String[] uris) {\r
+        this.virtualGraphId = virtualGraphId;\r
+        this.uris = uris;\r
+    }\r
+\r
+    @Override\r
+    public void setInitializationData(IConfigurationElement config, String propertyName, Object data)\r
+    throws CoreException {\r
+        if (data instanceof String) {\r
+            // Expecting comma-separated list of URIs in the argument.\r
+            String[] uris = ((String) data).split(",");\r
+            if (uris.length > 0) {\r
+                for(int i=0;i<uris.length;i++) uris[i] = OntologyVersions.getInstance().currentVersion(uris[i]);\r
+                // Validate the input data to contain valid URIs\r
+                for (String uri : uris) {\r
+                    try {\r
+                        new URI(uri);\r
+                    } catch (URISyntaxException e) {\r
+                        throw new CoreException(new Status(IStatus.ERROR, config.getContributor().getName(), "extension configuration element executable extension attribute '" + propertyName + "' argument contains invalid URIs. See cause for details.", e));\r
+                    }\r
+                }\r
+\r
+                this.uris = uris;\r
+            }\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void configure() throws ProjectException {\r
+        try {\r
+            Session s = getSession();\r
+            VirtualGraph vg = null;\r
+            if (virtualGraphId != null) {\r
+                VirtualGraphSupport support = s.getService(VirtualGraphSupport.class);\r
+                vg = support.getWorkspacePersistent(virtualGraphId);\r
+            }\r
+            getSession().syncRequest(new WriteRequest(vg) {\r
+                @Override\r
+                public void perform(WriteGraph graph) throws DatabaseException {\r
+                    configure(graph);\r
+                    graph.addMetadata(graph.getMetadata(CommentMetadata.class).add("Configured by Dependency Validation Feature."));\r
+                }\r
+            });\r
+        } catch (DatabaseException e) {\r
+            throw new ProjectException(e.getMessage(), e);\r
+        }\r
+    }\r
+\r
+    protected void configure(WriteGraph graph) throws DatabaseException {\r
+        Collection<String> nss = new ArrayList<String>();\r
+        Collection<String> notFound = new ArrayList<String>();\r
+\r
+        Resource project = getProject().get();\r
+        String projectName = NameUtils.getSafeName(graph, project);\r
+\r
+        ProjectResource PROJ = ProjectResource.getInstance(graph);\r
+\r
+        ArrayList<Resource> resourcesToLinkToProject = new ArrayList<Resource>();\r
+\r
+        for (String uri : uris) {\r
+            // This will fail if the extension-specified URI does not exist\r
+            Resource namespaceRequirement = null;\r
+            try {\r
+                namespaceRequirement = graph.getResource(uri);\r
+                resourcesToLinkToProject.add(namespaceRequirement);\r
+            } catch (ResourceNotFoundException e) {\r
+                notFound.add(uri);\r
+                continue;\r
+            }\r
+\r
+            for (Resource nsp : graph.getObjects(namespaceRequirement, PROJ.RequiresNamespace)) {\r
+                String ns = graph.getValue(nsp);\r
+                nss.add(ns);\r
+            }\r
+\r
+            for (String ns : nss) {\r
+                try {\r
+                    // This will fail if the namespace is not found.\r
+                    graph.getResource(ns);\r
+                } catch (ResourceNotFoundException e) {\r
+                    notFound.add(ns);\r
+                }\r
+            }\r
+        }\r
+\r
+        if (!notFound.isEmpty()) {\r
+            StringBuilder sb = new StringBuilder();\r
+            sb.append("Failed to locate the following namespaces required by project '");\r
+            sb.append(projectName);\r
+            sb.append("':\n");\r
+            for (String nf : notFound) {\r
+                sb.append("\t");\r
+                sb.append(nf);\r
+                sb.append("\n");\r
+            }\r
+            throw new AssumptionException(sb.toString());\r
+        }\r
+\r
+        // Ensure that the namespace requirements are linked to the project to\r
+        // make them discoverable by database queries.\r
+        linkTo(graph, project, resourcesToLinkToProject);\r
+    }\r
+\r
+    protected void linkTo(WriteGraph graph, Resource target, ArrayList<Resource> resourcesToLink) throws DatabaseException {\r
+        Layer0 L0 = Layer0.getInstance(graph);\r
+        for (Resource resource : resourcesToLink) {\r
+            if (!graph.hasStatement(target, L0.IsLinkedTo, resource))\r
+                graph.claim(target, L0.IsLinkedTo, resource);\r
+        }\r
+    }\r
+\r
+    @Override\r
+    public void deconfigure() throws ProjectException {\r
+    }\r
+\r
+}\r