]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.project/src/org/simantics/project/management/DatabaseManagement.java
Support ontology install option trueWhenDeployed also during development
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / DatabaseManagement.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.management;
13
14 import static org.simantics.db.common.utils.Transaction.writeGraph;
15
16 import java.util.Collection;
17 import java.util.HashSet;
18 import java.util.Set;
19 import java.util.regex.Matcher;
20
21 import org.simantics.databoard.Bindings;
22 import org.simantics.databoard.binding.Binding;
23 import org.simantics.db.ReadGraph;
24 import org.simantics.db.Resource;
25 import org.simantics.db.WriteGraph;
26 import org.simantics.db.WriteOnlyGraph;
27 import org.simantics.db.common.utils.Transaction;
28 import org.simantics.db.exception.AssumptionException;
29 import org.simantics.db.exception.DatabaseException;
30 import org.simantics.db.layer0.util.Layer0Utils;
31 import org.simantics.db.request.Read;
32 import org.simantics.graph.db.IImportAdvisor;
33 import org.simantics.graph.db.ImportAdvisor;
34 import org.simantics.graph.db.TransferableGraphException;
35 import org.simantics.graph.db.TransferableGraphs;
36 import org.simantics.graph.diff.Diff;
37 import org.simantics.graph.diff.TransferableGraphDelta1;
38 import org.simantics.graph.representation.TransferableGraph1;
39 import org.simantics.layer0.DatabaseManagementResource;
40 import org.simantics.layer0.Layer0;
41 import org.simantics.project.ontology.ProjectResource;
42
43 /**
44  * Database Management is a utility class for managing a database.
45  * The following management operations are supported:
46  * 
47  *   o Install Builtins
48  *   o Install Layer0
49  *   o Install & Update GraphBundles
50  *   o Manage Projects (Install/Uninstall/Discover)
51  *   o Manage Features (Install/Uninstall/Discover)
52  *   o Manage GraphBundles
53  *   
54  * This utility is based on Transaction class. The active graph must be
55  * set for the current thread.
56  *
57  * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
58  */
59 public class DatabaseManagement {
60
61         public static final String PROJECTS_URI = "http://Projects"; 
62         Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );
63
64         public DatabaseManagement() {
65         }
66
67     /////////////////////////////////////////////////////////////////////////// 
68     ///////////////           Project Managemenet        ////////////////////// 
69     /////////////////////////////////////////////////////////////////////////// 
70         /**
71          * Create a new project. A new resource is created and linked to Projects 
72          * library. 
73          * 
74          * @param g
75          * @param name
76          * @param features a list of features
77          * @return resource to the project
78          * @throws DatabaseException
79          */
80         public Resource createProject(String name, Collection<String> features) throws DatabaseException {
81                 
82             WriteGraph g = Transaction.writeGraph();
83             g.setClusterSet4NewResource(g.getRootLibrary());
84
85         Resource root = g.getResource(PROJECTS_URI);
86         Layer0 L0 = Layer0.getInstance(g);
87         ProjectResource PROJ = ProjectResource.getInstance(g);
88
89         Resource project = g.newResource();
90         g.claim(project, L0.InstanceOf, null, PROJ.Project);
91         g.claim(project, L0.PartOf, root);
92         g.claimLiteral(project, L0.HasName, name);
93         
94         // Create library for temporary resources
95         if(Layer0Utils.getPossibleChild(g, root, "Temp") == null) {
96             Resource tempLibrary = g.newResource();
97             g.claim(tempLibrary, L0.InstanceOf, null, L0.Library);
98             g.claimLiteral(tempLibrary, L0.HasName, "Temp");
99             g.claim(root, L0.ConsistsOf, tempLibrary);
100         }
101
102         // Create library for trash
103         if(Layer0Utils.getPossibleChild(g, root, "TrashBin") == null) {
104             Resource trashLibrary = g.newResource();
105             g.claim(trashLibrary, L0.InstanceOf, null, L0.Library);
106             g.claimLiteral(trashLibrary, L0.HasName, "TrashBin");
107             g.claim(root, L0.ConsistsOf, trashLibrary);
108         }
109
110         // Create library for document sessions
111         if(Layer0Utils.getPossibleChild(g, root, "DocumentSessions") == null) {
112             Resource documentSessions = g.newResource();
113             g.claim(documentSessions, L0.InstanceOf, null, L0.Library);
114             g.claimLiteral(documentSessions, L0.HasName, "DocumentSessions");
115             g.claim(root, L0.ConsistsOf, documentSessions);
116         }
117
118         // Link features
119         for (String feature_uri : features) {
120                 Resource r = g.getResource(feature_uri);
121                 g.claim(project, PROJ.HasFeature, r);
122         }
123         
124         return project;
125         }
126         
127         
128         /**
129          * Delete project. Project resource is unlinked it from the Projects library.
130          * The rest is left for garbage collection.
131          * 
132          * @param g
133          * @param projectResource
134          * @throws DatabaseException
135          */
136         public void deleteProject(Resource projectResource) throws DatabaseException {
137                 WriteGraph g = Transaction.writeGraph();
138                 Resource root = g.getResource(PROJECTS_URI);
139                 Layer0 l0 = Layer0.getInstance(g);
140                 g.denyStatement(projectResource, l0.PartOf, root);
141         }
142         
143         
144         /**
145          * A query that reads all project URIs  
146          * 
147          * @param g graph
148          * @return a query for graphs
149          * @throws DatabaseException
150          */
151         public final Read<Set<String>> ProjectURIQuery =
152                 new Read<Set<String>>() {
153                         @Override
154                         public Set<String> perform(ReadGraph g) throws DatabaseException {
155                                 Layer0 b = Layer0.getInstance(g);
156                                 Resource root = g.getResource(PROJECTS_URI);
157                                 Set<String> result = new HashSet<String>();
158                                 for (Resource r : g.getObjects(root, b.ConsistsOf) )
159                                         result.add( g.getURI(r) );
160                                 return result;
161                         }
162                 };      
163         
164         /**
165          * A query that reads all project resources  
166          * 
167          * @param g graph
168          * @return a query for graphs
169          * @throws DatabaseException
170          */
171         public final Read<Set<Resource>> ProjectsQuery =
172                 new Read<Set<Resource>>() {
173                         @Override
174                         public Set<Resource> perform(ReadGraph g) throws DatabaseException {
175                                 Layer0 b = Layer0.getInstance(g);
176                                 Resource root = g.getResource(PROJECTS_URI);
177                                 return new HashSet<Resource>( g.getObjects(root, b.ConsistsOf) );
178                         }
179                 };
180                 
181                 
182         /**
183          * Get a list of all projects in the database. 
184          * 
185          * @param g
186          * @return
187          * @throws DatabaseException
188          */
189         public Collection<Resource> getProjects() throws DatabaseException {
190                 ReadGraph g = Transaction.readGraph();
191                 Layer0 b = Layer0.getInstance(g);
192                 Resource root = g.getResource(PROJECTS_URI);
193                 return g.getObjects(root, b.ConsistsOf);
194         }
195
196     /////////////////////////////////////////////////////////////////////////// 
197     ///////////////           Feature Management         ////////////////////// 
198     /////////////////////////////////////////////////////////////////////////// 
199         
200 //      /**
201 //       * Get all features in the database. 
202 //       * 
203 //       * @param features a collection to be filled with features
204 //       */
205 //      public void getFeatures(Collection<FeatureInfo> features) throws DatabaseException 
206 //      {
207 //              ReadGraph g = Transaction.readGraph();
208 //              ProjectResource PROJ = ProjectResource.getInstance(g);
209 //              Layer0 L0 = Layer0.getInstance(g);
210 //
211 //              for (Resource r : g.getObjects(PROJ.PublishedProjectFeatures, L0.ConsistsOf)) {
212 //                      String URI = g.getURI(r);
213 //                      String name = g.getRelatedValue(r, L0.HasLabel);
214 //                      String vid_ = g.getRelatedValue(r, L0.HasName);
215 //                      VersionedId vid = (VersionedId) VersionedId.parse(vid_);
216 //                      FeatureInfo fi = new FeatureInfo(name, URI, vid);                       
217 //                      features.add( fi );             
218 //              }
219 //              
220 //      }
221 //      
222 //      /**
223 //       * Get all features installed to a project
224 //       * 
225 //       * @param g graph
226 //       * @param features a list of bundles
227 //       * @throws DatabaseException
228 //       */
229 //      public void getProjectFeatures(Resource project, Collection<FeatureInfo> features) throws DatabaseException {
230 //              ReadGraph g = Transaction.readGraph();
231 //              ProjectResource PROJ = ProjectResource.getInstance(g);
232 //              Layer0 L0 = Layer0.getInstance(g);
233 //              
234 //              for (Resource r : g.getObjects(project, PROJ.HasFeature)) {
235 //                      String URI = g.getURI(r);
236 //                      String name = g.getRelatedValue(r, L0.HasLabel);
237 //                      String vid_ = g.getRelatedValue(r, L0.HasName);
238 //                      VersionedId vid = (VersionedId) VersionedId.parse(vid_);
239 //                      FeatureInfo fi = new FeatureInfo(name, URI, vid);                       
240 //                      features.add( fi );             
241 //              }
242 //      }
243 //      
244 //      /**
245 //       * Configure project to use a feature.
246 //       * 
247 //       * @param g
248 //       * @param project
249 //       * @param featureUri feature URI
250 //       * @throws DatabaseException
251 //       */
252 //      public void installFeature(Resource project, String featureUri)
253 //      throws DatabaseException
254 //      {
255 //              WriteGraph g = Transaction.writeGraph();
256 //              Resource feature = g.getResource(featureUri);
257 //              ProjectResource PROJ = ProjectResource.getInstance(g);
258 //              g.claim(project, PROJ.HasFeature, feature);
259 //      }
260 //      
261 //      /**
262 //       * Configure project not to use a feature.
263 //       * 
264 //       * @param g
265 //       * @param project
266 //       * @param featureuri feature URI
267 //       * @throws DatabaseException
268 //       */
269 //      public void uninstallFeature(Resource project, String featureUri) 
270 //      throws DatabaseException
271 //      {
272 //              WriteGraph g = Transaction.writeGraph();
273 //              Resource feature = g.getResource(featureUri);
274 //              ProjectResource PROJ = ProjectResource.getInstance(g);
275 //              g.denyStatement(project, PROJ.HasFeature, feature);
276 //      }
277         
278         
279     /////////////////////////////////////////////////////////////////////////// 
280     ///////////////     Transferable Graph Management    ////////////////////// 
281     /////////////////////////////////////////////////////////////////////////// 
282         
283         /**
284          * Install transferable graph into database and manage install info.
285          * If different but exact same version is already installed, the new 
286          * graph is merged.<p>
287          * 
288          * Resource array field of tg argument is updated.
289          * 
290          * @param tg transferable graph
291          */
292         public void installGraphBundle(GraphBundle tg)
293         throws DatabaseException, TransferableGraphException 
294         {
295                 Resource oldResource = getGraphBundleResource(tg.getId(), tg.getMajor());
296                 // Install New
297                 if (oldResource == null) {              
298                         IImportAdvisor advisor = new ImportAdvisor();
299                         long[] resourceArray = TransferableGraphs.importGraph(writeGraph(), tg.getGraph(), advisor);
300                         tg.setResourceArray(resourceArray);
301                         setGraphBundleEntry(tg);
302                 } else
303                 // Merge with old
304                 {
305                         // Merge &
306                         GraphBundle oldTG = getGraphBundle(oldResource);
307                 TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();
308                         long[] oldResourceArray = oldTG.getResourceArray();
309                     long[] newResourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResourceArray, delta);
310                     tg.setResourceArray(newResourceArray);
311                     // Manage
312                 setGraphBundleEntry(tg);                        
313                 }
314         }
315
316         /**
317          * A query that reads all graphs in the database  
318          * 
319          * @param g graph
320          * @return a query for graphs
321          * @throws DatabaseException
322          */
323         public final Read<Set<GraphBundleRef>> GraphBundleRefQuery =
324                 new Read<Set<GraphBundleRef>>() {
325                         @Override
326                         public Set<GraphBundleRef> perform(ReadGraph g) throws DatabaseException {
327                                 Object oldGraph = Transaction.setGraph(g);
328                                 try {
329                                         return getGraphBundleReferences();
330                                 } finally {
331                                         Transaction.setGraph(oldGraph);
332                                 }
333                         }
334                 };      
335
336         
337         /**
338          * A query that reads all graphs in the database  
339          * 
340          * @param g graph
341          * @return a query for graphs
342          * @throws DatabaseException
343          */
344         public final Read<Set<GraphBundle>> GraphBundleQuery =
345                 new Read<Set<GraphBundle>>() {
346                         @Override
347                         public Set<GraphBundle> perform(ReadGraph g) throws DatabaseException {
348                                 Object oldGraph = Transaction.setGraph(g);
349                                 try {
350                                         return getGraphBundles();
351                                 } finally {
352                                         Transaction.setGraph(oldGraph);
353                                 }
354                         }
355                 };      
356
357         public Set<GraphBundle> getGraphBundles() 
358         throws DatabaseException {
359                 ReadGraph g = Transaction.readGraph();
360                 Set<GraphBundle> result = new HashSet<GraphBundle>();
361
362                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
363                 Layer0 L0 = Layer0.getInstance(g);                              
364                 
365                 for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
366                         if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue; 
367                         String name = g.getPossibleRelatedValue(tg, L0.HasName);
368                         String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);
369                         Integer hash = g.getPossibleRelatedValue(tg, DatabaseManagement.HasHashCode);
370                         //System.out.println("Found in Database: " + vid);
371                         //TransferableGraph1 data = g.getRelatedValue(tg, DatabaseManagement.HasFile, tg_binding);
372                         GraphBundle entry = new GraphBundle(name, null, vid);
373                         entry.resource = tg;
374                         entry.hashcode = hash;
375                         long[] resourceArray = g.getPossibleRelatedValue(tg, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);
376                         if (resourceArray!=null) entry.setResourceArray(resourceArray);
377                         result.add(entry);
378                 }               
379                 return result;          
380         }
381
382         public Set<GraphBundleRef> getGraphBundleReferences() 
383         throws DatabaseException {
384                 ReadGraph g = Transaction.readGraph();
385                 Set<GraphBundleRef> result = new HashSet<GraphBundleRef>();
386
387                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
388                 Layer0 L0 = Layer0.getInstance(g);                              
389                 
390                 for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
391                         if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue;
392                         String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);
393                         result.add( GraphBundleRef.of( vid ) );
394                 }               
395                 return result;          
396         }
397         
398         
399         /**
400          * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. 
401          * 
402          * @param id id <symbolic_name>_<version>
403          * @return TG resource or <tt>null</tt>
404          * @throws DatabaseException
405          */
406         public GraphBundle getGraphBundle(Resource r) throws DatabaseException {
407                 ReadGraph g = Transaction.readGraph();
408                 Layer0 L0 = Layer0.getInstance(g);
409                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
410                 
411                 String name = g.getPossibleRelatedValue(r, L0.HasName);
412                 String vid = g.getPossibleRelatedValue(r, DatabaseManagement.HasVersionedId);
413                 TransferableGraph1 data = g.getRelatedValue(r, DatabaseManagement.HasFile, tg_binding);
414                 GraphBundle entry = new GraphBundle(name, data, vid);
415                 long[] resourceArray = g.getPossibleRelatedValue(r, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);
416                 if (resourceArray!=null) entry.setResourceArray(resourceArray);         
417                 return entry;
418         }       
419         
420         /**
421          * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. 
422          * 
423          * @param id id <symbolic_name>/<version>
424          * @param major major version
425          * @return resource or <tt>null</tt>
426          * @throws DatabaseException
427          */
428         public Resource getGraphBundleResource(String id, int major) throws DatabaseException {
429                 ReadGraph g = Transaction.readGraph();
430                 Layer0 L0 = Layer0.getInstance(g);
431                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
432                 
433                 for (Resource r : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
434                         if ( !g.isInstanceOf(r, DatabaseManagement.GraphBundle) ) continue;                     
435                         String vid = g.getRelatedValue(r, DatabaseManagement.HasVersionedId);
436                         
437                         Matcher m = GraphBundle.VERSIONED_ID_PATTERN.matcher(vid);
438                         if (!m.matches()) continue;
439                         
440                         String rid = m.group(1);
441                         int rmajor = Integer.valueOf( m.group(2) );
442                         if (rid.equals(id) && rmajor==major) return r;
443                 }
444         
445                 return null;
446         }
447
448         /**
449          * Create a GraphBundle entry into the database and attach to  
450          * InstalledTransferableGraphs-library.
451          * 
452          * @param entry
453          * @param resourceArray
454          * @return Resource
455          * @throws DatabaseException
456          */
457         Resource createGraphBundle(GraphBundle entry) throws DatabaseException {
458                 WriteGraph g = Transaction.writeGraph();
459                 Layer0 L0 = Layer0.getInstance(g);
460                 DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
461
462                 Resource r = g.newResource();
463                 g.claim(r, L0.InstanceOf, DatabaseManagement.GraphBundle);
464                 g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);
465                 g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
466                 g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
467                 g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);
468                 g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);
469                 g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, r);
470                 return r;
471                 
472         }
473
474         public Resource createGraphBundle(WriteOnlyGraph g, GraphBundle entry) throws DatabaseException {
475
476                 Layer0 L0 = g.getService(Layer0.class);
477                 DatabaseManagementResource DatabaseManagement = g.getService(DatabaseManagementResource.class);
478
479                 Resource r = g.newResource();
480                 g.claim(r, L0.InstanceOf, null, DatabaseManagement.GraphBundle);
481                 g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);
482                 g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
483                 g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
484                 g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);
485                 g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);
486                 g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, L0.PartOf, r);         
487                 return r;
488                 
489         }
490         
491         /**
492          * Set TransferableGraph info.
493          * 
494          * @param entry 
495          * @param resourceArray
496          * @return new or existing feature resource
497          * @throws DatabaseException
498          * @throws AssumptionException thrown if bundle exists but is not a GraphBundle 
499          */
500         public Resource setGraphBundleEntry(GraphBundle entry) throws DatabaseException {
501                 Resource r = getGraphBundleResource(entry.getId(), entry.getMajor());
502                 
503                 // Create a new resource
504                 if (r==null) {
505                         r = createGraphBundle(entry);
506                         return r;
507                 }
508                 
509                 // Update values of an existing resource
510                 {
511                         WriteGraph g = Transaction.writeGraph();                
512                         Layer0 L0 = Layer0.getInstance(g);
513                         DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
514                         g.claimLiteral(r, L0.HasName, entry.getName(), Bindings.STRING);
515                         g.claimLiteral(r, DatabaseManagement.HasVersionedId, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
516                         g.claimLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
517                         g.claimLiteral(r, DatabaseManagement.HasHashCode, entry.hashcode, Bindings.INTEGER);
518                         g.claimLiteral(r, DatabaseManagement.HasInstallInfo, entry.getResourceArray(), Bindings.LONG_ARRAY);
519                         return r;
520                 }               
521         }       
522         
523 }
524