]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.project/src/org/simantics/project/management/DatabaseManagement.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.project / src / org / simantics / project / management / DatabaseManagement.java
index ed041450f0d05030ec99c21bf2c58e1ec0d87ca7..be082a72473e8d0d70d1c0b62819a686919ea5a0 100644 (file)
-/*******************************************************************************\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.management;\r
-\r
-import static org.simantics.db.common.utils.Transaction.writeGraph;\r
-\r
-import java.util.Collection;\r
-import java.util.HashSet;\r
-import java.util.Set;\r
-import java.util.regex.Matcher;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.WriteOnlyGraph;\r
-import org.simantics.db.common.utils.Transaction;\r
-import org.simantics.db.exception.AssumptionException;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.util.Layer0Utils;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.graph.db.IImportAdvisor;\r
-import org.simantics.graph.db.ImportAdvisor;\r
-import org.simantics.graph.db.TransferableGraphException;\r
-import org.simantics.graph.db.TransferableGraphs;\r
-import org.simantics.graph.diff.Diff;\r
-import org.simantics.graph.diff.TransferableGraphDelta1;\r
-import org.simantics.graph.representation.TransferableGraph1;\r
-import org.simantics.layer0.DatabaseManagementResource;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.project.ontology.ProjectResource;\r
-\r
-/**\r
- * Database Management is a utility class for managing a database.\r
- * The following management operations are supported:\r
- * \r
- *   o Install Builtins\r
- *   o Install Layer0\r
- *   o Install & Update GraphBundles\r
- *   o Manage Projects (Install/Uninstall/Discover)\r
- *   o Manage Features (Install/Uninstall/Discover)\r
- *   o Manage GraphBundles\r
- *   \r
- * This utility is based on Transaction class. The active graph must be\r
- * set for the current thread.\r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class DatabaseManagement {\r
-\r
-       public static final String PROJECTS_URI = "http://Projects"; \r
-       Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );\r
-\r
-       public DatabaseManagement() {\r
-       }\r
-\r
-    ///////////////////////////////////////////////////////////////////////////        \r
-    ///////////////           Project Managemenet        //////////////////////        \r
-    ///////////////////////////////////////////////////////////////////////////        \r
-       /**\r
-        * Create a new project. A new resource is created and linked to Projects \r
-        * library. \r
-        * \r
-        * @param g\r
-        * @param name\r
-        * @param features a list of features\r
-        * @return resource to the project\r
-        * @throws DatabaseException\r
-        */\r
-       public Resource createProject(String name, Collection<String> features) throws DatabaseException {\r
-               \r
-           WriteGraph g = Transaction.writeGraph();\r
-           g.setClusterSet4NewResource(g.getRootLibrary());\r
-\r
-        Resource root = g.getResource(PROJECTS_URI);\r
-        Layer0 L0 = Layer0.getInstance(g);\r
-        ProjectResource PROJ = ProjectResource.getInstance(g);\r
-\r
-        Resource project = g.newResource();\r
-        g.claim(project, L0.InstanceOf, null, PROJ.Project);\r
-        g.claim(project, L0.PartOf, root);\r
-        g.claimLiteral(project, L0.HasName, name);\r
-        \r
-        // Create library for temporary resources\r
-        if(Layer0Utils.getPossibleChild(g, root, "Temp") == null) {\r
-            Resource tempLibrary = g.newResource();\r
-            g.claim(tempLibrary, L0.InstanceOf, null, L0.Library);\r
-            g.claimLiteral(tempLibrary, L0.HasName, "Temp");\r
-            g.claim(root, L0.ConsistsOf, tempLibrary);\r
-        }\r
-\r
-        // Create library for trash\r
-        if(Layer0Utils.getPossibleChild(g, root, "TrashBin") == null) {\r
-            Resource trashLibrary = g.newResource();\r
-            g.claim(trashLibrary, L0.InstanceOf, null, L0.Library);\r
-            g.claimLiteral(trashLibrary, L0.HasName, "TrashBin");\r
-            g.claim(root, L0.ConsistsOf, trashLibrary);\r
-        }\r
-\r
-        // Create library for document sessions\r
-        if(Layer0Utils.getPossibleChild(g, root, "DocumentSessions") == null) {\r
-            Resource documentSessions = g.newResource();\r
-            g.claim(documentSessions, L0.InstanceOf, null, L0.Library);\r
-            g.claimLiteral(documentSessions, L0.HasName, "DocumentSessions");\r
-            g.claim(root, L0.ConsistsOf, documentSessions);\r
-        }\r
-\r
-        // Link features\r
-        for (String feature_uri : features) {\r
-               Resource r = g.getResource(feature_uri);\r
-               g.claim(project, PROJ.HasFeature, r);\r
-        }\r
-        \r
-        return project;\r
-       }\r
-       \r
-       \r
-       /**\r
-        * Delete project. Project resource is unlinked it from the Projects library.\r
-        * The rest is left for garbage collection.\r
-        * \r
-        * @param g\r
-        * @param projectResource\r
-        * @throws DatabaseException\r
-        */\r
-       public void deleteProject(Resource projectResource) throws DatabaseException {\r
-               WriteGraph g = Transaction.writeGraph();\r
-               Resource root = g.getResource(PROJECTS_URI);\r
-               Layer0 l0 = Layer0.getInstance(g);\r
-               g.denyStatement(projectResource, l0.PartOf, root);\r
-       }\r
-       \r
-       \r
-       /**\r
-        * A query that reads all project URIs  \r
-        * \r
-        * @param g graph\r
-        * @return a query for graphs\r
-        * @throws DatabaseException\r
-        */\r
-       public final Read<Set<String>> ProjectURIQuery =\r
-               new Read<Set<String>>() {\r
-                       @Override\r
-                       public Set<String> perform(ReadGraph g) throws DatabaseException {\r
-                               Layer0 b = Layer0.getInstance(g);\r
-                               Resource root = g.getResource(PROJECTS_URI);\r
-                               Set<String> result = new HashSet<String>();\r
-                               for (Resource r : g.getObjects(root, b.ConsistsOf) )\r
-                                       result.add( g.getURI(r) );\r
-                               return result;\r
-                       }\r
-               };      \r
-       \r
-       /**\r
-        * A query that reads all project resources  \r
-        * \r
-        * @param g graph\r
-        * @return a query for graphs\r
-        * @throws DatabaseException\r
-        */\r
-       public final Read<Set<Resource>> ProjectsQuery =\r
-               new Read<Set<Resource>>() {\r
-                       @Override\r
-                       public Set<Resource> perform(ReadGraph g) throws DatabaseException {\r
-                               Layer0 b = Layer0.getInstance(g);\r
-                               Resource root = g.getResource(PROJECTS_URI);\r
-                               return new HashSet<Resource>( g.getObjects(root, b.ConsistsOf) );\r
-                       }\r
-               };\r
-               \r
-               \r
-       /**\r
-        * Get a list of all projects in the database. \r
-        * \r
-        * @param g\r
-        * @return\r
-        * @throws DatabaseException\r
-        */\r
-       public Collection<Resource> getProjects() throws DatabaseException {\r
-               ReadGraph g = Transaction.readGraph();\r
-               Layer0 b = Layer0.getInstance(g);\r
-               Resource root = g.getResource(PROJECTS_URI);\r
-               return g.getObjects(root, b.ConsistsOf);\r
-       }\r
-\r
-    ///////////////////////////////////////////////////////////////////////////        \r
-    ///////////////           Feature Management         //////////////////////        \r
-    ///////////////////////////////////////////////////////////////////////////        \r
-       \r
-//     /**\r
-//      * Get all features in the database. \r
-//      * \r
-//      * @param features a collection to be filled with features\r
-//      */\r
-//     public void getFeatures(Collection<FeatureInfo> features) throws DatabaseException \r
-//     {\r
-//             ReadGraph g = Transaction.readGraph();\r
-//             ProjectResource PROJ = ProjectResource.getInstance(g);\r
-//             Layer0 L0 = Layer0.getInstance(g);\r
-//\r
-//             for (Resource r : g.getObjects(PROJ.PublishedProjectFeatures, L0.ConsistsOf)) {\r
-//                     String URI = g.getURI(r);\r
-//                     String name = g.getRelatedValue(r, L0.HasLabel);\r
-//                     String vid_ = g.getRelatedValue(r, L0.HasName);\r
-//                     VersionedId vid = (VersionedId) VersionedId.parse(vid_);\r
-//                     FeatureInfo fi = new FeatureInfo(name, URI, vid);                       \r
-//                     features.add( fi );             \r
-//             }\r
-//             \r
-//     }\r
-//     \r
-//     /**\r
-//      * Get all features installed to a project\r
-//      * \r
-//      * @param g graph\r
-//      * @param features a list of bundles\r
-//      * @throws DatabaseException\r
-//      */\r
-//     public void getProjectFeatures(Resource project, Collection<FeatureInfo> features) throws DatabaseException {\r
-//             ReadGraph g = Transaction.readGraph();\r
-//             ProjectResource PROJ = ProjectResource.getInstance(g);\r
-//             Layer0 L0 = Layer0.getInstance(g);\r
-//             \r
-//             for (Resource r : g.getObjects(project, PROJ.HasFeature)) {\r
-//                     String URI = g.getURI(r);\r
-//                     String name = g.getRelatedValue(r, L0.HasLabel);\r
-//                     String vid_ = g.getRelatedValue(r, L0.HasName);\r
-//                     VersionedId vid = (VersionedId) VersionedId.parse(vid_);\r
-//                     FeatureInfo fi = new FeatureInfo(name, URI, vid);                       \r
-//                     features.add( fi );             \r
-//             }\r
-//     }\r
-//     \r
-//     /**\r
-//      * Configure project to use a feature.\r
-//      * \r
-//      * @param g\r
-//      * @param project\r
-//      * @param featureUri feature URI\r
-//      * @throws DatabaseException\r
-//      */\r
-//     public void installFeature(Resource project, String featureUri)\r
-//     throws DatabaseException\r
-//     {\r
-//             WriteGraph g = Transaction.writeGraph();\r
-//             Resource feature = g.getResource(featureUri);\r
-//             ProjectResource PROJ = ProjectResource.getInstance(g);\r
-//             g.claim(project, PROJ.HasFeature, feature);\r
-//     }\r
-//     \r
-//     /**\r
-//      * Configure project not to use a feature.\r
-//      * \r
-//      * @param g\r
-//      * @param project\r
-//      * @param featureuri feature URI\r
-//      * @throws DatabaseException\r
-//      */\r
-//     public void uninstallFeature(Resource project, String featureUri) \r
-//     throws DatabaseException\r
-//     {\r
-//             WriteGraph g = Transaction.writeGraph();\r
-//             Resource feature = g.getResource(featureUri);\r
-//             ProjectResource PROJ = ProjectResource.getInstance(g);\r
-//             g.denyStatement(project, PROJ.HasFeature, feature);\r
-//     }\r
-       \r
-       \r
-    ///////////////////////////////////////////////////////////////////////////        \r
-    ///////////////     Transferable Graph Management    //////////////////////        \r
-    ///////////////////////////////////////////////////////////////////////////        \r
-       \r
-       /**\r
-        * Install transferable graph into database and manage install info.\r
-        * If different but exact same version is already installed, the new \r
-        * graph is merged.<p>\r
-        * \r
-        * Resource array field of tg argument is updated.\r
-        * \r
-        * @param tg transferable graph\r
-        */\r
-       public void installGraphBundle(GraphBundle tg)\r
-       throws DatabaseException, TransferableGraphException \r
-       {\r
-               Resource oldResource = getGraphBundleResource(tg.getId(), tg.getMajor());\r
-               // Install New\r
-               if (oldResource == null) {              \r
-                       IImportAdvisor advisor = new ImportAdvisor();\r
-                       long[] resourceArray = TransferableGraphs.importGraph(writeGraph(), tg.getGraph(), advisor);\r
-                       tg.setResourceArray(resourceArray);\r
-                       setGraphBundleEntry(tg);\r
-               } else\r
-               // Merge with old\r
-               {\r
-                       // Merge &\r
-                       GraphBundle oldTG = getGraphBundle(oldResource);\r
-               TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();\r
-                       long[] oldResourceArray = oldTG.getResourceArray();\r
-                   long[] newResourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResourceArray, delta);\r
-                   tg.setResourceArray(newResourceArray);\r
-                   // Manage\r
-               setGraphBundleEntry(tg);                        \r
-               }\r
-       }\r
-\r
-       /**\r
-        * A query that reads all graphs in the database  \r
-        * \r
-        * @param g graph\r
-        * @return a query for graphs\r
-        * @throws DatabaseException\r
-        */\r
-       public final Read<Set<GraphBundleRef>> GraphBundleRefQuery =\r
-               new Read<Set<GraphBundleRef>>() {\r
-                       @Override\r
-                       public Set<GraphBundleRef> perform(ReadGraph g) throws DatabaseException {\r
-                               Object oldGraph = Transaction.setGraph(g);\r
-                               try {\r
-                                       return getGraphBundleReferences();\r
-                               } finally {\r
-                                       Transaction.setGraph(oldGraph);\r
-                               }\r
-                       }\r
-               };      \r
-\r
-       \r
-       /**\r
-        * A query that reads all graphs in the database  \r
-        * \r
-        * @param g graph\r
-        * @return a query for graphs\r
-        * @throws DatabaseException\r
-        */\r
-       public final Read<Set<GraphBundle>> GraphBundleQuery =\r
-               new Read<Set<GraphBundle>>() {\r
-                       @Override\r
-                       public Set<GraphBundle> perform(ReadGraph g) throws DatabaseException {\r
-                               Object oldGraph = Transaction.setGraph(g);\r
-                               try {\r
-                                       return getGraphBundles();\r
-                               } finally {\r
-                                       Transaction.setGraph(oldGraph);\r
-                               }\r
-                       }\r
-               };      \r
-\r
-       public Set<GraphBundle> getGraphBundles() \r
-       throws DatabaseException {\r
-               ReadGraph g = Transaction.readGraph();\r
-               Set<GraphBundle> result = new HashSet<GraphBundle>();\r
-\r
-               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-               Layer0 L0 = Layer0.getInstance(g);                              \r
-               \r
-               for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {\r
-                       if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue; \r
-                       String name = g.getPossibleRelatedValue(tg, L0.HasName);\r
-                       String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);\r
-                       Integer hash = g.getPossibleRelatedValue(tg, DatabaseManagement.HasHashCode);\r
-                       //System.out.println("Found in Database: " + vid);\r
-                       //TransferableGraph1 data = g.getRelatedValue(tg, DatabaseManagement.HasFile, tg_binding);\r
-                       GraphBundle entry = new GraphBundle(name, null, vid);\r
-                       entry.resource = tg;\r
-                       entry.hashcode = hash;\r
-                       long[] resourceArray = g.getPossibleRelatedValue(tg, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);\r
-                       if (resourceArray!=null) entry.setResourceArray(resourceArray);\r
-                       result.add(entry);\r
-               }               \r
-               return result;          \r
-       }\r
-\r
-       public Set<GraphBundleRef> getGraphBundleReferences() \r
-       throws DatabaseException {\r
-               ReadGraph g = Transaction.readGraph();\r
-               Set<GraphBundleRef> result = new HashSet<GraphBundleRef>();\r
-\r
-               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-               Layer0 L0 = Layer0.getInstance(g);                              \r
-               \r
-               for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {\r
-                       if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue;\r
-                       String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);\r
-                       result.add( GraphBundleRef.of( vid ) );\r
-               }               \r
-               return result;          \r
-       }\r
-       \r
-       \r
-       /**\r
-        * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. \r
-        * \r
-        * @param id id <symbolic_name>_<version>\r
-        * @return TG resource or <tt>null</tt>\r
-        * @throws DatabaseException\r
-        */\r
-       public GraphBundle getGraphBundle(Resource r) throws DatabaseException {\r
-               ReadGraph g = Transaction.readGraph();\r
-               Layer0 L0 = Layer0.getInstance(g);\r
-               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-               \r
-               String name = g.getPossibleRelatedValue(r, L0.HasName);\r
-               String vid = g.getPossibleRelatedValue(r, DatabaseManagement.HasVersionedId);\r
-               TransferableGraph1 data = g.getRelatedValue(r, DatabaseManagement.HasFile, tg_binding);\r
-               GraphBundle entry = new GraphBundle(name, data, vid);\r
-               long[] resourceArray = g.getPossibleRelatedValue(r, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);\r
-               if (resourceArray!=null) entry.setResourceArray(resourceArray);         \r
-               return entry;\r
-       }       \r
-       \r
-       /**\r
-        * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. \r
-        * \r
-        * @param id id <symbolic_name>/<version>\r
-        * @param major major version\r
-        * @return resource or <tt>null</tt>\r
-        * @throws DatabaseException\r
-        */\r
-       public Resource getGraphBundleResource(String id, int major) throws DatabaseException {\r
-               ReadGraph g = Transaction.readGraph();\r
-               Layer0 L0 = Layer0.getInstance(g);\r
-               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-               \r
-               for (Resource r : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {\r
-                       if ( !g.isInstanceOf(r, DatabaseManagement.GraphBundle) ) continue;                     \r
-                       String vid = g.getRelatedValue(r, DatabaseManagement.HasVersionedId);\r
-                       \r
-                       Matcher m = GraphBundle.VERSIONED_ID_PATTERN.matcher(vid);\r
-                       if (!m.matches()) continue;\r
-                       \r
-                       String rid = m.group(1);\r
-                       int rmajor = Integer.valueOf( m.group(2) );\r
-                       if (rid.equals(id) && rmajor==major) return r;\r
-               }\r
-       \r
-               return null;\r
-       }\r
-\r
-       /**\r
-        * Create a GraphBundle entry into the database and attach to  \r
-        * InstalledTransferableGraphs-library.\r
-        * \r
-        * @param entry\r
-        * @param resourceArray\r
-        * @return Resource\r
-        * @throws DatabaseException\r
-        */\r
-       Resource createGraphBundle(GraphBundle entry) throws DatabaseException {\r
-               WriteGraph g = Transaction.writeGraph();\r
-               Layer0 L0 = Layer0.getInstance(g);\r
-               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-\r
-               Resource r = g.newResource();\r
-               g.claim(r, L0.InstanceOf, DatabaseManagement.GraphBundle);\r
-               g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);\r
-               g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);\r
-               g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);\r
-               g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);\r
-               g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);\r
-               g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, r);\r
-               return r;\r
-               \r
-       }\r
-\r
-       public Resource createGraphBundle(WriteOnlyGraph g, GraphBundle entry) throws DatabaseException {\r
-\r
-               Layer0 L0 = g.getService(Layer0.class);\r
-               DatabaseManagementResource DatabaseManagement = g.getService(DatabaseManagementResource.class);\r
-\r
-               Resource r = g.newResource();\r
-               g.claim(r, L0.InstanceOf, null, DatabaseManagement.GraphBundle);\r
-               g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);\r
-               g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);\r
-               g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);\r
-               g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);\r
-               g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);\r
-               g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, L0.PartOf, r);         \r
-               return r;\r
-               \r
-       }\r
-       \r
-       /**\r
-        * Set TransferableGraph info.\r
-        * \r
-        * @param entry \r
-        * @param resourceArray\r
-        * @return new or existing feature resource\r
-        * @throws DatabaseException\r
-        * @throws AssumptionException thrown if bundle exists but is not a GraphBundle \r
-        */\r
-       public Resource setGraphBundleEntry(GraphBundle entry) throws DatabaseException {\r
-               Resource r = getGraphBundleResource(entry.getId(), entry.getMajor());\r
-               \r
-               // Create a new resource\r
-               if (r==null) {\r
-                       r = createGraphBundle(entry);\r
-                       return r;\r
-               }\r
-               \r
-               // Update values of an existing resource\r
-               {\r
-                       WriteGraph g = Transaction.writeGraph();                \r
-                       Layer0 L0 = Layer0.getInstance(g);\r
-                       DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);\r
-                       g.claimLiteral(r, L0.HasName, entry.getName(), Bindings.STRING);\r
-                       g.claimLiteral(r, DatabaseManagement.HasVersionedId, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);\r
-                       g.claimLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);\r
-                       g.claimLiteral(r, DatabaseManagement.HasHashCode, entry.hashcode, Bindings.INTEGER);\r
-                       g.claimLiteral(r, DatabaseManagement.HasInstallInfo, entry.getResourceArray(), Bindings.LONG_ARRAY);\r
-                       return r;\r
-               }               \r
-       }       \r
-       \r
-}\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.project.management;
+
+import static org.simantics.db.common.utils.Transaction.writeGraph;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.regex.Matcher;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.WriteOnlyGraph;
+import org.simantics.db.common.utils.Transaction;
+import org.simantics.db.exception.AssumptionException;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.Layer0Utils;
+import org.simantics.db.request.Read;
+import org.simantics.graph.db.IImportAdvisor;
+import org.simantics.graph.db.ImportAdvisor;
+import org.simantics.graph.db.TransferableGraphException;
+import org.simantics.graph.db.TransferableGraphs;
+import org.simantics.graph.diff.Diff;
+import org.simantics.graph.diff.TransferableGraphDelta1;
+import org.simantics.graph.representation.TransferableGraph1;
+import org.simantics.layer0.DatabaseManagementResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.project.ontology.ProjectResource;
+
+/**
+ * Database Management is a utility class for managing a database.
+ * The following management operations are supported:
+ * 
+ *   o Install Builtins
+ *   o Install Layer0
+ *   o Install & Update GraphBundles
+ *   o Manage Projects (Install/Uninstall/Discover)
+ *   o Manage Features (Install/Uninstall/Discover)
+ *   o Manage GraphBundles
+ *   
+ * This utility is based on Transaction class. The active graph must be
+ * set for the current thread.
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class DatabaseManagement {
+
+       public static final String PROJECTS_URI = "http://Projects"; 
+       Binding tg_binding = Bindings.getBindingUnchecked( TransferableGraph1.class );
+
+       public DatabaseManagement() {
+       }
+
+    ///////////////////////////////////////////////////////////////////////////        
+    ///////////////           Project Managemenet        //////////////////////        
+    ///////////////////////////////////////////////////////////////////////////        
+       /**
+        * Create a new project. A new resource is created and linked to Projects 
+        * library. 
+        * 
+        * @param g
+        * @param name
+        * @param features a list of features
+        * @return resource to the project
+        * @throws DatabaseException
+        */
+       public Resource createProject(String name, Collection<String> features) throws DatabaseException {
+               
+           WriteGraph g = Transaction.writeGraph();
+           g.setClusterSet4NewResource(g.getRootLibrary());
+
+        Resource root = g.getResource(PROJECTS_URI);
+        Layer0 L0 = Layer0.getInstance(g);
+        ProjectResource PROJ = ProjectResource.getInstance(g);
+
+        Resource project = g.newResource();
+        g.claim(project, L0.InstanceOf, null, PROJ.Project);
+        g.claim(project, L0.PartOf, root);
+        g.claimLiteral(project, L0.HasName, name);
+        
+        // Create library for temporary resources
+        if(Layer0Utils.getPossibleChild(g, root, "Temp") == null) {
+            Resource tempLibrary = g.newResource();
+            g.claim(tempLibrary, L0.InstanceOf, null, L0.Library);
+            g.claimLiteral(tempLibrary, L0.HasName, "Temp");
+            g.claim(root, L0.ConsistsOf, tempLibrary);
+        }
+
+        // Create library for trash
+        if(Layer0Utils.getPossibleChild(g, root, "TrashBin") == null) {
+            Resource trashLibrary = g.newResource();
+            g.claim(trashLibrary, L0.InstanceOf, null, L0.Library);
+            g.claimLiteral(trashLibrary, L0.HasName, "TrashBin");
+            g.claim(root, L0.ConsistsOf, trashLibrary);
+        }
+
+        // Create library for document sessions
+        if(Layer0Utils.getPossibleChild(g, root, "DocumentSessions") == null) {
+            Resource documentSessions = g.newResource();
+            g.claim(documentSessions, L0.InstanceOf, null, L0.Library);
+            g.claimLiteral(documentSessions, L0.HasName, "DocumentSessions");
+            g.claim(root, L0.ConsistsOf, documentSessions);
+        }
+
+        // Link features
+        for (String feature_uri : features) {
+               Resource r = g.getResource(feature_uri);
+               g.claim(project, PROJ.HasFeature, r);
+        }
+        
+        return project;
+       }
+       
+       
+       /**
+        * Delete project. Project resource is unlinked it from the Projects library.
+        * The rest is left for garbage collection.
+        * 
+        * @param g
+        * @param projectResource
+        * @throws DatabaseException
+        */
+       public void deleteProject(Resource projectResource) throws DatabaseException {
+               WriteGraph g = Transaction.writeGraph();
+               Resource root = g.getResource(PROJECTS_URI);
+               Layer0 l0 = Layer0.getInstance(g);
+               g.denyStatement(projectResource, l0.PartOf, root);
+       }
+       
+       
+       /**
+        * A query that reads all project URIs  
+        * 
+        * @param g graph
+        * @return a query for graphs
+        * @throws DatabaseException
+        */
+       public final Read<Set<String>> ProjectURIQuery =
+               new Read<Set<String>>() {
+                       @Override
+                       public Set<String> perform(ReadGraph g) throws DatabaseException {
+                               Layer0 b = Layer0.getInstance(g);
+                               Resource root = g.getResource(PROJECTS_URI);
+                               Set<String> result = new HashSet<String>();
+                               for (Resource r : g.getObjects(root, b.ConsistsOf) )
+                                       result.add( g.getURI(r) );
+                               return result;
+                       }
+               };      
+       
+       /**
+        * A query that reads all project resources  
+        * 
+        * @param g graph
+        * @return a query for graphs
+        * @throws DatabaseException
+        */
+       public final Read<Set<Resource>> ProjectsQuery =
+               new Read<Set<Resource>>() {
+                       @Override
+                       public Set<Resource> perform(ReadGraph g) throws DatabaseException {
+                               Layer0 b = Layer0.getInstance(g);
+                               Resource root = g.getResource(PROJECTS_URI);
+                               return new HashSet<Resource>( g.getObjects(root, b.ConsistsOf) );
+                       }
+               };
+               
+               
+       /**
+        * Get a list of all projects in the database. 
+        * 
+        * @param g
+        * @return
+        * @throws DatabaseException
+        */
+       public Collection<Resource> getProjects() throws DatabaseException {
+               ReadGraph g = Transaction.readGraph();
+               Layer0 b = Layer0.getInstance(g);
+               Resource root = g.getResource(PROJECTS_URI);
+               return g.getObjects(root, b.ConsistsOf);
+       }
+
+    ///////////////////////////////////////////////////////////////////////////        
+    ///////////////           Feature Management         //////////////////////        
+    ///////////////////////////////////////////////////////////////////////////        
+       
+//     /**
+//      * Get all features in the database. 
+//      * 
+//      * @param features a collection to be filled with features
+//      */
+//     public void getFeatures(Collection<FeatureInfo> features) throws DatabaseException 
+//     {
+//             ReadGraph g = Transaction.readGraph();
+//             ProjectResource PROJ = ProjectResource.getInstance(g);
+//             Layer0 L0 = Layer0.getInstance(g);
+//
+//             for (Resource r : g.getObjects(PROJ.PublishedProjectFeatures, L0.ConsistsOf)) {
+//                     String URI = g.getURI(r);
+//                     String name = g.getRelatedValue(r, L0.HasLabel);
+//                     String vid_ = g.getRelatedValue(r, L0.HasName);
+//                     VersionedId vid = (VersionedId) VersionedId.parse(vid_);
+//                     FeatureInfo fi = new FeatureInfo(name, URI, vid);                       
+//                     features.add( fi );             
+//             }
+//             
+//     }
+//     
+//     /**
+//      * Get all features installed to a project
+//      * 
+//      * @param g graph
+//      * @param features a list of bundles
+//      * @throws DatabaseException
+//      */
+//     public void getProjectFeatures(Resource project, Collection<FeatureInfo> features) throws DatabaseException {
+//             ReadGraph g = Transaction.readGraph();
+//             ProjectResource PROJ = ProjectResource.getInstance(g);
+//             Layer0 L0 = Layer0.getInstance(g);
+//             
+//             for (Resource r : g.getObjects(project, PROJ.HasFeature)) {
+//                     String URI = g.getURI(r);
+//                     String name = g.getRelatedValue(r, L0.HasLabel);
+//                     String vid_ = g.getRelatedValue(r, L0.HasName);
+//                     VersionedId vid = (VersionedId) VersionedId.parse(vid_);
+//                     FeatureInfo fi = new FeatureInfo(name, URI, vid);                       
+//                     features.add( fi );             
+//             }
+//     }
+//     
+//     /**
+//      * Configure project to use a feature.
+//      * 
+//      * @param g
+//      * @param project
+//      * @param featureUri feature URI
+//      * @throws DatabaseException
+//      */
+//     public void installFeature(Resource project, String featureUri)
+//     throws DatabaseException
+//     {
+//             WriteGraph g = Transaction.writeGraph();
+//             Resource feature = g.getResource(featureUri);
+//             ProjectResource PROJ = ProjectResource.getInstance(g);
+//             g.claim(project, PROJ.HasFeature, feature);
+//     }
+//     
+//     /**
+//      * Configure project not to use a feature.
+//      * 
+//      * @param g
+//      * @param project
+//      * @param featureuri feature URI
+//      * @throws DatabaseException
+//      */
+//     public void uninstallFeature(Resource project, String featureUri) 
+//     throws DatabaseException
+//     {
+//             WriteGraph g = Transaction.writeGraph();
+//             Resource feature = g.getResource(featureUri);
+//             ProjectResource PROJ = ProjectResource.getInstance(g);
+//             g.denyStatement(project, PROJ.HasFeature, feature);
+//     }
+       
+       
+    ///////////////////////////////////////////////////////////////////////////        
+    ///////////////     Transferable Graph Management    //////////////////////        
+    ///////////////////////////////////////////////////////////////////////////        
+       
+       /**
+        * Install transferable graph into database and manage install info.
+        * If different but exact same version is already installed, the new 
+        * graph is merged.<p>
+        * 
+        * Resource array field of tg argument is updated.
+        * 
+        * @param tg transferable graph
+        */
+       public void installGraphBundle(GraphBundle tg)
+       throws DatabaseException, TransferableGraphException 
+       {
+               Resource oldResource = getGraphBundleResource(tg.getId(), tg.getMajor());
+               // Install New
+               if (oldResource == null) {              
+                       IImportAdvisor advisor = new ImportAdvisor();
+                       long[] resourceArray = TransferableGraphs.importGraph(writeGraph(), tg.getGraph(), advisor);
+                       tg.setResourceArray(resourceArray);
+                       setGraphBundleEntry(tg);
+               } else
+               // Merge with old
+               {
+                       // Merge &
+                       GraphBundle oldTG = getGraphBundle(oldResource);
+               TransferableGraphDelta1 delta = new Diff(oldTG.getGraph(), tg.getGraph()).diff();
+                       long[] oldResourceArray = oldTG.getResourceArray();
+                   long[] newResourceArray = TransferableGraphs.applyDelta(writeGraph(), oldResourceArray, delta);
+                   tg.setResourceArray(newResourceArray);
+                   // Manage
+               setGraphBundleEntry(tg);                        
+               }
+       }
+
+       /**
+        * A query that reads all graphs in the database  
+        * 
+        * @param g graph
+        * @return a query for graphs
+        * @throws DatabaseException
+        */
+       public final Read<Set<GraphBundleRef>> GraphBundleRefQuery =
+               new Read<Set<GraphBundleRef>>() {
+                       @Override
+                       public Set<GraphBundleRef> perform(ReadGraph g) throws DatabaseException {
+                               Object oldGraph = Transaction.setGraph(g);
+                               try {
+                                       return getGraphBundleReferences();
+                               } finally {
+                                       Transaction.setGraph(oldGraph);
+                               }
+                       }
+               };      
+
+       
+       /**
+        * A query that reads all graphs in the database  
+        * 
+        * @param g graph
+        * @return a query for graphs
+        * @throws DatabaseException
+        */
+       public final Read<Set<GraphBundle>> GraphBundleQuery =
+               new Read<Set<GraphBundle>>() {
+                       @Override
+                       public Set<GraphBundle> perform(ReadGraph g) throws DatabaseException {
+                               Object oldGraph = Transaction.setGraph(g);
+                               try {
+                                       return getGraphBundles();
+                               } finally {
+                                       Transaction.setGraph(oldGraph);
+                               }
+                       }
+               };      
+
+       public Set<GraphBundle> getGraphBundles() 
+       throws DatabaseException {
+               ReadGraph g = Transaction.readGraph();
+               Set<GraphBundle> result = new HashSet<GraphBundle>();
+
+               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+               Layer0 L0 = Layer0.getInstance(g);                              
+               
+               for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
+                       if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue; 
+                       String name = g.getPossibleRelatedValue(tg, L0.HasName);
+                       String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);
+                       Integer hash = g.getPossibleRelatedValue(tg, DatabaseManagement.HasHashCode);
+                       //System.out.println("Found in Database: " + vid);
+                       //TransferableGraph1 data = g.getRelatedValue(tg, DatabaseManagement.HasFile, tg_binding);
+                       GraphBundle entry = new GraphBundle(name, null, vid);
+                       entry.resource = tg;
+                       entry.hashcode = hash;
+                       long[] resourceArray = g.getPossibleRelatedValue(tg, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);
+                       if (resourceArray!=null) entry.setResourceArray(resourceArray);
+                       result.add(entry);
+               }               
+               return result;          
+       }
+
+       public Set<GraphBundleRef> getGraphBundleReferences() 
+       throws DatabaseException {
+               ReadGraph g = Transaction.readGraph();
+               Set<GraphBundleRef> result = new HashSet<GraphBundleRef>();
+
+               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+               Layer0 L0 = Layer0.getInstance(g);                              
+               
+               for (Resource tg : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
+                       if ( !g.isInstanceOf(tg, DatabaseManagement.GraphBundle) ) continue;
+                       String vid = g.getPossibleRelatedValue(tg, DatabaseManagement.HasVersionedId);
+                       result.add( GraphBundleRef.of( vid ) );
+               }               
+               return result;          
+       }
+       
+       
+       /**
+        * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. 
+        * 
+        * @param id id <symbolic_name>_<version>
+        * @return TG resource or <tt>null</tt>
+        * @throws DatabaseException
+        */
+       public GraphBundle getGraphBundle(Resource r) throws DatabaseException {
+               ReadGraph g = Transaction.readGraph();
+               Layer0 L0 = Layer0.getInstance(g);
+               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+               
+               String name = g.getPossibleRelatedValue(r, L0.HasName);
+               String vid = g.getPossibleRelatedValue(r, DatabaseManagement.HasVersionedId);
+               TransferableGraph1 data = g.getRelatedValue(r, DatabaseManagement.HasFile, tg_binding);
+               GraphBundle entry = new GraphBundle(name, data, vid);
+               long[] resourceArray = g.getPossibleRelatedValue(r, DatabaseManagement.HasInstallInfo, Bindings.LONG_ARRAY);
+               if (resourceArray!=null) entry.setResourceArray(resourceArray);         
+               return entry;
+       }       
+       
+       /**
+        * Get TransferableGraph resource that is attached to InstalledTransferableGraphs. 
+        * 
+        * @param id id <symbolic_name>/<version>
+        * @param major major version
+        * @return resource or <tt>null</tt>
+        * @throws DatabaseException
+        */
+       public Resource getGraphBundleResource(String id, int major) throws DatabaseException {
+               ReadGraph g = Transaction.readGraph();
+               Layer0 L0 = Layer0.getInstance(g);
+               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+               
+               for (Resource r : g.getObjects(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf)) {
+                       if ( !g.isInstanceOf(r, DatabaseManagement.GraphBundle) ) continue;                     
+                       String vid = g.getRelatedValue(r, DatabaseManagement.HasVersionedId);
+                       
+                       Matcher m = GraphBundle.VERSIONED_ID_PATTERN.matcher(vid);
+                       if (!m.matches()) continue;
+                       
+                       String rid = m.group(1);
+                       int rmajor = Integer.valueOf( m.group(2) );
+                       if (rid.equals(id) && rmajor==major) return r;
+               }
+       
+               return null;
+       }
+
+       /**
+        * Create a GraphBundle entry into the database and attach to  
+        * InstalledTransferableGraphs-library.
+        * 
+        * @param entry
+        * @param resourceArray
+        * @return Resource
+        * @throws DatabaseException
+        */
+       Resource createGraphBundle(GraphBundle entry) throws DatabaseException {
+               WriteGraph g = Transaction.writeGraph();
+               Layer0 L0 = Layer0.getInstance(g);
+               DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+
+               Resource r = g.newResource();
+               g.claim(r, L0.InstanceOf, DatabaseManagement.GraphBundle);
+               g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);
+               g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
+               g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
+               g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);
+               g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);
+               g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, r);
+               return r;
+               
+       }
+
+       public Resource createGraphBundle(WriteOnlyGraph g, GraphBundle entry) throws DatabaseException {
+
+               Layer0 L0 = g.getService(Layer0.class);
+               DatabaseManagementResource DatabaseManagement = g.getService(DatabaseManagementResource.class);
+
+               Resource r = g.newResource();
+               g.claim(r, L0.InstanceOf, null, DatabaseManagement.GraphBundle);
+               g.addLiteral(r, L0.HasName, L0.NameOf, L0.String, entry.getName(), Bindings.STRING);
+               g.addLiteral(r, DatabaseManagement.HasVersionedId, DatabaseManagement.HasVersionedId_Inverse, L0.String, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
+               g.addLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
+               g.addLiteral(r, DatabaseManagement.HasHashCode, DatabaseManagement.HasHashCode_Inverse, L0.Integer, entry.hashcode, Bindings.INTEGER);
+               g.addLiteral(r, DatabaseManagement.HasInstallInfo, DatabaseManagement.HasInstallInfo_Inverse, L0.LongArray, entry.getResourceArray(), Bindings.LONG_ARRAY);
+               g.claim(DatabaseManagement.InstalledGraphBundles, L0.ConsistsOf, L0.PartOf, r);         
+               return r;
+               
+       }
+       
+       /**
+        * Set TransferableGraph info.
+        * 
+        * @param entry 
+        * @param resourceArray
+        * @return new or existing feature resource
+        * @throws DatabaseException
+        * @throws AssumptionException thrown if bundle exists but is not a GraphBundle 
+        */
+       public Resource setGraphBundleEntry(GraphBundle entry) throws DatabaseException {
+               Resource r = getGraphBundleResource(entry.getId(), entry.getMajor());
+               
+               // Create a new resource
+               if (r==null) {
+                       r = createGraphBundle(entry);
+                       return r;
+               }
+               
+               // Update values of an existing resource
+               {
+                       WriteGraph g = Transaction.writeGraph();                
+                       Layer0 L0 = Layer0.getInstance(g);
+                       DatabaseManagementResource DatabaseManagement = DatabaseManagementResource.getInstance(g);
+                       g.claimLiteral(r, L0.HasName, entry.getName(), Bindings.STRING);
+                       g.claimLiteral(r, DatabaseManagement.HasVersionedId, entry.getId()+"/"+entry.getMajor()+"."+entry.getMinor()+"."+entry.getService()+"."+entry.getQualifier(), Bindings.STRING);
+                       g.claimLiteral(r, DatabaseManagement.HasFile, DatabaseManagement.HasFile_Inverse, L0.Graph, entry.graph, tg_binding);
+                       g.claimLiteral(r, DatabaseManagement.HasHashCode, entry.hashcode, Bindings.INTEGER);
+                       g.claimLiteral(r, DatabaseManagement.HasInstallInfo, entry.getResourceArray(), Bindings.LONG_ARRAY);
+                       return r;
+               }               
+       }       
+       
+}
+