X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.project%2Fsrc%2Forg%2Fsimantics%2Fproject%2Fmanagement%2FDatabaseManagement.java;fp=bundles%2Forg.simantics.project%2Fsrc%2Forg%2Fsimantics%2Fproject%2Fmanagement%2FDatabaseManagement.java;h=ed041450f0d05030ec99c21bf2c58e1ec0d87ca7;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.project/src/org/simantics/project/management/DatabaseManagement.java b/bundles/org.simantics.project/src/org/simantics/project/management/DatabaseManagement.java new file mode 100644 index 000000000..ed041450f --- /dev/null +++ b/bundles/org.simantics.project/src/org/simantics/project/management/DatabaseManagement.java @@ -0,0 +1,524 @@ +/******************************************************************************* + * 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 + */ +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 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> ProjectURIQuery = + new Read>() { + @Override + public Set perform(ReadGraph g) throws DatabaseException { + Layer0 b = Layer0.getInstance(g); + Resource root = g.getResource(PROJECTS_URI); + Set result = new HashSet(); + 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> ProjectsQuery = + new Read>() { + @Override + public Set perform(ReadGraph g) throws DatabaseException { + Layer0 b = Layer0.getInstance(g); + Resource root = g.getResource(PROJECTS_URI); + return new HashSet( g.getObjects(root, b.ConsistsOf) ); + } + }; + + + /** + * Get a list of all projects in the database. + * + * @param g + * @return + * @throws DatabaseException + */ + public Collection 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 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 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.

+ * + * 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> GraphBundleRefQuery = + new Read>() { + @Override + public Set 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> GraphBundleQuery = + new Read>() { + @Override + public Set perform(ReadGraph g) throws DatabaseException { + Object oldGraph = Transaction.setGraph(g); + try { + return getGraphBundles(); + } finally { + Transaction.setGraph(oldGraph); + } + } + }; + + public Set getGraphBundles() + throws DatabaseException { + ReadGraph g = Transaction.readGraph(); + Set result = new HashSet(); + + 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 getGraphBundleReferences() + throws DatabaseException { + ReadGraph g = Transaction.readGraph(); + Set result = new HashSet(); + + 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 _ + * @return TG resource or null + * @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 / + * @param major major version + * @return resource or null + * @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; + } + } + +} +