]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.project/src/org/simantics/project/features/DependencyValidationFeature.java
Merge commit '728147df5d63a3333daff3d8c0e9bfd4f5597e3a'
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / features / DependencyValidationFeature.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
3  * in Industry THTH ry.\r
4  * All rights reserved. This program and the accompanying materials\r
5  * are made available under the terms of the Eclipse Public License v1.0\r
6  * which accompanies this distribution, and is available at\r
7  * http://www.eclipse.org/legal/epl-v10.html\r
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.project.features;\r
13 \r
14 import java.net.URI;\r
15 import java.net.URISyntaxException;\r
16 import java.util.ArrayList;\r
17 import java.util.Collection;\r
18 \r
19 import org.eclipse.core.runtime.CoreException;\r
20 import org.eclipse.core.runtime.IConfigurationElement;\r
21 import org.eclipse.core.runtime.IExecutableExtension;\r
22 import org.eclipse.core.runtime.IStatus;\r
23 import org.eclipse.core.runtime.Status;\r
24 import org.simantics.db.Resource;\r
25 import org.simantics.db.Session;\r
26 import org.simantics.db.VirtualGraph;\r
27 import org.simantics.db.WriteGraph;\r
28 import org.simantics.db.common.CommentMetadata;\r
29 import org.simantics.db.common.request.WriteRequest;\r
30 import org.simantics.db.common.utils.NameUtils;\r
31 import org.simantics.db.exception.AssumptionException;\r
32 import org.simantics.db.exception.DatabaseException;\r
33 import org.simantics.db.exception.ResourceNotFoundException;\r
34 import org.simantics.db.service.VirtualGraphSupport;\r
35 import org.simantics.layer0.Layer0;\r
36 import org.simantics.project.exception.ProjectException;\r
37 import org.simantics.project.ontology.ProjectResource;\r
38 import org.simantics.scl.reflection.OntologyVersions;\r
39 \r
40 /**\r
41  * A project feature for validating that a set of namespaces (URIs) are\r
42  * reachable in the database for which this feature is configured.\r
43  * \r
44  * The URIs are described as class arguments in the extension class spec (after\r
45  * ':' character).\r
46  * \r
47  * @author Tuukka Lehtonen\r
48  */\r
49 public class DependencyValidationFeature extends AbstractProjectFeature implements IExecutableExtension {\r
50 \r
51     private String   virtualGraphId;\r
52     private String[] uris = {};\r
53 \r
54     public DependencyValidationFeature() {\r
55     }\r
56 \r
57     public DependencyValidationFeature(String virtualGraphId, String[] uris) {\r
58         this.virtualGraphId = virtualGraphId;\r
59         this.uris = uris;\r
60     }\r
61 \r
62     @Override\r
63     public void setInitializationData(IConfigurationElement config, String propertyName, Object data)\r
64     throws CoreException {\r
65         if (data instanceof String) {\r
66             // Expecting comma-separated list of URIs in the argument.\r
67             String[] uris = ((String) data).split(",");\r
68             if (uris.length > 0) {\r
69                 for(int i=0;i<uris.length;i++) uris[i] = OntologyVersions.getInstance().currentVersion(uris[i]);\r
70                 // Validate the input data to contain valid URIs\r
71                 for (String uri : uris) {\r
72                     try {\r
73                         new URI(uri);\r
74                     } catch (URISyntaxException e) {\r
75                         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
76                     }\r
77                 }\r
78 \r
79                 this.uris = uris;\r
80             }\r
81         }\r
82     }\r
83 \r
84     @Override\r
85     public void configure() throws ProjectException {\r
86         try {\r
87             Session s = getSession();\r
88             VirtualGraph vg = null;\r
89             if (virtualGraphId != null) {\r
90                 VirtualGraphSupport support = s.getService(VirtualGraphSupport.class);\r
91                 vg = support.getWorkspacePersistent(virtualGraphId);\r
92             }\r
93             getSession().syncRequest(new WriteRequest(vg) {\r
94                 @Override\r
95                 public void perform(WriteGraph graph) throws DatabaseException {\r
96                     configure(graph);\r
97                     graph.addMetadata(graph.getMetadata(CommentMetadata.class).add("Configured by Dependency Validation Feature."));\r
98                 }\r
99             });\r
100         } catch (DatabaseException e) {\r
101             throw new ProjectException(e.getMessage(), e);\r
102         }\r
103     }\r
104 \r
105     protected void configure(WriteGraph graph) throws DatabaseException {\r
106         Collection<String> nss = new ArrayList<String>();\r
107         Collection<String> notFound = new ArrayList<String>();\r
108 \r
109         Resource project = getProject().get();\r
110         String projectName = NameUtils.getSafeName(graph, project);\r
111 \r
112         ProjectResource PROJ = ProjectResource.getInstance(graph);\r
113 \r
114         ArrayList<Resource> resourcesToLinkToProject = new ArrayList<Resource>();\r
115 \r
116         for (String uri : uris) {\r
117             // This will fail if the extension-specified URI does not exist\r
118             Resource namespaceRequirement = null;\r
119             try {\r
120                 namespaceRequirement = graph.getResource(uri);\r
121                 resourcesToLinkToProject.add(namespaceRequirement);\r
122             } catch (ResourceNotFoundException e) {\r
123                 notFound.add(uri);\r
124                 continue;\r
125             }\r
126 \r
127             for (Resource nsp : graph.getObjects(namespaceRequirement, PROJ.RequiresNamespace)) {\r
128                 String ns = graph.getValue(nsp);\r
129                 nss.add(ns);\r
130             }\r
131 \r
132             for (String ns : nss) {\r
133                 try {\r
134                     // This will fail if the namespace is not found.\r
135                     graph.getResource(ns);\r
136                 } catch (ResourceNotFoundException e) {\r
137                     notFound.add(ns);\r
138                 }\r
139             }\r
140         }\r
141 \r
142         if (!notFound.isEmpty()) {\r
143             StringBuilder sb = new StringBuilder();\r
144             sb.append("Failed to locate the following namespaces required by project '");\r
145             sb.append(projectName);\r
146             sb.append("':\n");\r
147             for (String nf : notFound) {\r
148                 sb.append("\t");\r
149                 sb.append(nf);\r
150                 sb.append("\n");\r
151             }\r
152             throw new AssumptionException(sb.toString());\r
153         }\r
154 \r
155         // Ensure that the namespace requirements are linked to the project to\r
156         // make them discoverable by database queries.\r
157         linkTo(graph, project, resourcesToLinkToProject);\r
158     }\r
159 \r
160     protected void linkTo(WriteGraph graph, Resource target, ArrayList<Resource> resourcesToLink) throws DatabaseException {\r
161         Layer0 L0 = Layer0.getInstance(graph);\r
162         for (Resource resource : resourcesToLink) {\r
163             if (!graph.hasStatement(target, L0.IsLinkedTo, resource))\r
164                 graph.claim(target, L0.IsLinkedTo, resource);\r
165         }\r
166     }\r
167 \r
168     @Override\r
169     public void deconfigure() throws ProjectException {\r
170     }\r
171 \r
172 }\r