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