--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.backup.db</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ds.core.builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8\r
+org.eclipse.jdt.core.compiler.compliance=1.8\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.8\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Modelled Backup Provider
+Bundle-SymbolicName: org.simantics.backup.db
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.backup.db.Activator
+Require-Bundle: org.simantics,
+ org.simantics.backup.ontology,
+ org.simantics.backup
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Bundle-ActivationPolicy: lazy
+Service-Component: OSGI-INF/component.xml
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.simantics.backup.db.modelled">\r
+ <implementation class="org.simantics.backup.db.ModelledBackupProvider"/>\r
+ <service>\r
+ <provide interface="org.simantics.backup.IBackupProvider"/>\r
+ </service>\r
+</scr:component>\r
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = META-INF/,\\r
+ .,\\r
+ scl/,\\r
+ OSGI-INF/component.xml\r
--- /dev/null
+import "Simantics/DB"\r
+\r
+importJava "org.simantics.backup.IBackupProvider" where\r
+ data IBackupProvider\r
+\r
+importJava "org.simantics.backup.db.ModelledBackup" where\r
+ modelledBackup :: \r
+ (<e> ()) -> \r
+ (String -> Integer -> <e> (() -> <e> Maybe String)) -> \r
+ (<e> ()) -> \r
+ (String -> Integer -> <e> ()) -> \r
+ <Proc> IBackupProvider\r
+ \r
+importJava "org.simantics.backup.BackupProviderService" where\r
+ backup :: String -> Integer -> <Proc> ()
\ No newline at end of file
--- /dev/null
+package org.simantics.backup.db;\r
+\r
+import org.osgi.framework.BundleActivator;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator implements BundleActivator {\r
+\r
+ private static BundleContext context;\r
+\r
+ static BundleContext getContext() {\r
+ return context;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext bundleContext) throws Exception {\r
+ Activator.context = bundleContext;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext bundleContext) throws Exception {\r
+ Activator.context = null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.backup.db;\r
+\r
+import java.nio.file.Path;\r
+import java.util.concurrent.Callable;\r
+import java.util.concurrent.Future;\r
+import java.util.concurrent.FutureTask;\r
+\r
+import org.simantics.backup.BackupException;\r
+import org.simantics.backup.IBackupProvider;\r
+import org.simantics.scl.runtime.function.Function1;\r
+import org.simantics.scl.runtime.function.Function2;\r
+import org.simantics.scl.runtime.tuple.Tuple0;\r
+\r
+public class ModelledBackup implements IBackupProvider {\r
+\r
+ private final Function1<Tuple0, Object> lockFunc;\r
+ private final Function2<String, Integer, Function1<Tuple0, String>> backupFunc;\r
+ private final Function1<Tuple0, Object> unlockFunc;\r
+ private final Function2<String, Integer, Object> restoreFunc;\r
+\r
+ private ModelledBackup(\r
+ Function1<Tuple0, Object> lockFunc,\r
+ Function2<String, Integer, Function1<Tuple0, String>> backupFunc,\r
+ Function1<Tuple0, Object> unlockFunc,\r
+ Function2<String, Integer, Object> restoreFunc) {\r
+ this.lockFunc = lockFunc;\r
+ this.backupFunc = backupFunc;\r
+ this.unlockFunc = unlockFunc;\r
+ this.restoreFunc = restoreFunc;\r
+ }\r
+\r
+ @Override\r
+ public void lock() {\r
+ lockFunc.apply(Tuple0.INSTANCE);\r
+ }\r
+\r
+ @Override\r
+ public Future<BackupException> backup(Path targetPath, int revision) {\r
+\r
+ final Function1<Tuple0, String> fn = backupFunc.apply(targetPath.toString(), revision);\r
+ \r
+ final FutureTask<BackupException> futureTask = new FutureTask<BackupException>(new Callable<BackupException>() {\r
+ @Override\r
+ public BackupException call() throws Exception {\r
+ try {\r
+ String error = fn.apply(Tuple0.INSTANCE);\r
+ if (error != null) {\r
+ return new BackupException(error);\r
+ } else {\r
+ return null;\r
+ }\r
+ } catch (Throwable t) {\r
+ return new BackupException(t);\r
+ }\r
+ }\r
+ });\r
+ \r
+ Thread thread = new Thread(futureTask, "Backup Provider Thread " + backupFunc.toString());\r
+ thread.start();\r
+\r
+ return futureTask;\r
+ }\r
+\r
+ @Override\r
+ public void unlock() {\r
+ unlockFunc.apply(Tuple0.INSTANCE);\r
+ }\r
+\r
+ @Override\r
+ public void restore(Path fromPath, int revision) {\r
+ restoreFunc.apply(fromPath.toString(), revision);\r
+ }\r
+\r
+ public static IBackupProvider modelledBackup(\r
+ Function1<Tuple0, Object> lockFunc,\r
+ Function2<String, Integer, Function1<Tuple0, String>> backupFunc,\r
+ Function1<Tuple0, Object> unlockFunc,\r
+ Function2<String, Integer, Object> restoreFunc) {\r
+\r
+ return new ModelledBackup(lockFunc, backupFunc, unlockFunc, restoreFunc);\r
+ }\r
+}\r
--- /dev/null
+package org.simantics.backup.db;\r
+\r
+import java.nio.file.Path;\r
+import java.util.ArrayList;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.concurrent.Callable;\r
+import java.util.concurrent.ExecutionException;\r
+import java.util.concurrent.Future;\r
+import java.util.concurrent.FutureTask;\r
+\r
+import org.eclipse.core.runtime.CoreException;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.MultiStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.simantics.Simantics;\r
+import org.simantics.backup.Activator;\r
+import org.simantics.backup.BackupException;\r
+import org.simantics.backup.Backups;\r
+import org.simantics.backup.IBackupProvider;\r
+import org.simantics.backup.ontology.BackupResource;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.UniqueRead;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.adapter.Instances;\r
+import org.simantics.db.layer0.util.Layer0Utils;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+\r
+public class ModelledBackupProvider implements IBackupProvider {\r
+ \r
+ List<IBackupProvider> modelledBackups = new ArrayList<>();\r
+\r
+ public ModelledBackupProvider() {\r
+ // Should this be on the constructor or can there be dynamic ontologies?\r
+ this.modelledBackups = getModelledBackups();\r
+ }\r
+ \r
+ @Override\r
+ public void lock() throws BackupException {\r
+ Backups.lock(modelledBackups);\r
+ }\r
+\r
+ @Override\r
+ public Future<BackupException> backup(Path targetPath, int revision) throws BackupException {\r
+ final List<Future<BackupException>> backups = new ArrayList<>();\r
+ final List<Exception> exceptions = new ArrayList<>(backups.size());\r
+ for (IBackupProvider modelledBackup : modelledBackups) {\r
+ try {\r
+ Future<BackupException> future = modelledBackup.backup(targetPath, revision);\r
+ backups.add(future);\r
+ } catch (BackupException e) {\r
+ exceptions.add(e);\r
+ }\r
+ }\r
+ FutureTask<BackupException> task = new FutureTask<>(new Callable<BackupException>() {\r
+\r
+ @Override\r
+ public BackupException call() throws Exception {\r
+ for (Future<BackupException> f : backups) {\r
+ try {\r
+ Exception exception = f.get();\r
+ if (exception != null)\r
+ exceptions.add(exception);\r
+ } catch (InterruptedException | ExecutionException e) {\r
+ exceptions.add(e);\r
+ }\r
+ }\r
+ BackupException problem = null;\r
+ // Throw BackupException if any of the backup operations failed.\r
+ if (!exceptions.isEmpty()) {\r
+ IStatus[] ss = exceptions.stream()\r
+ .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))\r
+ .toArray(IStatus[]::new);\r
+ problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,\r
+ "Backup operation(s) failed to complete.", null)));\r
+ }\r
+ return problem;\r
+ }\r
+ });\r
+ new Thread(task).run();\r
+ return task;\r
+ }\r
+\r
+ @Override\r
+ public void unlock() throws BackupException {\r
+ Backups.unlock(modelledBackups);\r
+ }\r
+\r
+ @Override\r
+ public void restore(Path fromPath, int revision) throws BackupException {\r
+ for (IBackupProvider modelledBackup : modelledBackups) {\r
+ modelledBackup.restore(fromPath, revision);\r
+ }\r
+ }\r
+\r
+ \r
+ private List<IBackupProvider> getModelledBackups() {\r
+ List<IBackupProvider> modelledProviders = new ArrayList<>(0);\r
+ try {\r
+ modelledProviders = Simantics.getSession().syncRequest(new UniqueRead<List<IBackupProvider>>() {\r
+\r
+ @Override\r
+ public List<IBackupProvider> perform(ReadGraph graph) throws DatabaseException {\r
+ BackupResource BACKUP = BackupResource.getInstance(graph);\r
+ Instances query = graph.adapt(BACKUP.ModelledBackupProvider, Instances.class);\r
+\r
+ HashSet<Resource> providers = new HashSet<>();\r
+ \r
+ List<Resource> ontologies = Layer0Utils.listOntologies(graph);\r
+ for (Resource ontology : ontologies) {\r
+ for(Resource provider : query.find(graph, ontology)) {\r
+ providers.add(provider);\r
+ }\r
+ }\r
+ List<IBackupProvider> modelledBackups = new ArrayList<>();\r
+ for (Resource provider : providers) {\r
+ Variable variable = Variables.getVariable(graph, provider);\r
+ IBackupProvider modelledBackup = variable.getPropertyValue(graph, "instance");\r
+ modelledBackups.add(modelledBackup);\r
+ }\r
+ \r
+ return modelledBackups;\r
+ }\r
+ });\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ return modelledProviders;\r
+ }\r
+\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.backup.ontology</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.simantics.graph.builder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ <nature>org.simantics.graph.nature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7\r
+org.eclipse.jdt.core.compiler.compliance=1.7\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.7\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Simantics Backup Ontology
+Bundle-SymbolicName: org.simantics.backup.ontology
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.backup.ontology.Activator
+Require-Bundle: org.eclipse.core.runtime,
+ org.simantics.layer0,
+ org.simantics.structural.ontology;bundle-version="1.2.0"
+Bundle-RequiredExecutionEnvironment: JavaSE-1.7
+Bundle-ActivationPolicy: lazy
+Export-Package: org.simantics.backup.ontology
--- /dev/null
+source.. = src/\r
+output.. = bin/\r
+bin.includes = plugin.xml,\\r
+ META-INF/,\\r
+ .,\\r
+ graph.tg\r
--- /dev/null
+L0 = <http://www.simantics.org/Layer0-1.1>\r
+STR = <http://www.simantics.org/Structural-1.2>\r
+\r
+BACKUP = <http://www.simantics.org/Backup-1.0> : L0.Ontology\r
+ @L0.new\r
+ L0.HasResourceClass "org.simantics.backup.ontology.BackupResource"\r
+\r
+BACKUP.SCLMain : L0.SCLModule\r
+ L0.SCLModule.definition _ : L0.String\r
+ @L0.loadString "scl/SCLMain.scl"\r
+\r
+BACKUP.ModelledBackupProvider <T L0.Entity\r
+ --> BACKUP.ModelledBackupProvider.instance ==> "IBackupProvider" <R L0.HasProperty : L0.FunctionalRelation \r
+\r
+BACKUP.modelledBackupProvider : L0.Template\r
+ @template %subject %expression\r
+ %subject : BACKUP.ModelledBackupProvider\r
+ BACKUP.ModelledBackupProvider.instance _ : STR.SCLValue\r
+ L0.SCLValue.expression %expression\r
+ L0.HasValueType "IBackupProvider"\r
+\r
--- /dev/null
+include "Simantics/Backup"
\ No newline at end of file
--- /dev/null
+package org.simantics.backup.ontology;\r
+\r
+import org.osgi.framework.BundleActivator;\r
+import org.osgi.framework.BundleContext;\r
+\r
+public class Activator implements BundleActivator {\r
+\r
+ private static BundleContext context;\r
+\r
+ static BundleContext getContext() {\r
+ return context;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)\r
+ */\r
+ public void start(BundleContext bundleContext) throws Exception {\r
+ Activator.context = bundleContext;\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)\r
+ */\r
+ public void stop(BundleContext bundleContext) throws Exception {\r
+ Activator.context = null;\r
+ }\r
+\r
+}\r
--- /dev/null
+package org.simantics.backup.ontology;\r
+\r
+import org.simantics.db.RequestProcessor;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.service.QueryControl;\r
+\r
+public class BackupResource {\r
+ \r
+ public final Resource ModelledBackupProvider;\r
+ public final Resource ModelledBackupProvider_instance;\r
+ public final Resource ModelledBackupProvider_instance_Inverse;\r
+ public final Resource SCLMain;\r
+ public final Resource modelledBackupProvider;\r
+ \r
+ public static class URIs {\r
+ public static final String ModelledBackupProvider = "http://www.simantics.org/Backup-1.0/ModelledBackupProvider";\r
+ public static final String ModelledBackupProvider_instance = "http://www.simantics.org/Backup-1.0/ModelledBackupProvider/instance";\r
+ public static final String ModelledBackupProvider_instance_Inverse = "http://www.simantics.org/Backup-1.0/ModelledBackupProvider/instance/Inverse";\r
+ public static final String SCLMain = "http://www.simantics.org/Backup-1.0/SCLMain";\r
+ public static final String modelledBackupProvider = "http://www.simantics.org/Backup-1.0/modelledBackupProvider";\r
+ }\r
+ \r
+ public static Resource getResourceOrNull(ReadGraph graph, String uri) {\r
+ try {\r
+ return graph.getResource(uri);\r
+ } catch(DatabaseException e) {\r
+ System.err.println(e.getMessage());\r
+ return null;\r
+ }\r
+ }\r
+ \r
+ public BackupResource(ReadGraph graph) {\r
+ ModelledBackupProvider = getResourceOrNull(graph, URIs.ModelledBackupProvider);\r
+ ModelledBackupProvider_instance = getResourceOrNull(graph, URIs.ModelledBackupProvider_instance);\r
+ ModelledBackupProvider_instance_Inverse = getResourceOrNull(graph, URIs.ModelledBackupProvider_instance_Inverse);\r
+ SCLMain = getResourceOrNull(graph, URIs.SCLMain);\r
+ modelledBackupProvider = getResourceOrNull(graph, URIs.modelledBackupProvider);\r
+ }\r
+ \r
+ public static BackupResource getInstance(ReadGraph graph) {\r
+ Session session = graph.getSession();\r
+ BackupResource ret = session.peekService(BackupResource.class);\r
+ if(ret == null) {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ ret = new BackupResource(qc.getIndependentGraph(graph));\r
+ session.registerService(BackupResource.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+ public static BackupResource getInstance(RequestProcessor session) throws DatabaseException {\r
+ BackupResource ret = session.peekService(BackupResource.class);\r
+ if(ret == null) {\r
+ ret = session.syncRequest(new Read<BackupResource>() {\r
+ public BackupResource perform(ReadGraph graph) throws DatabaseException {\r
+ QueryControl qc = graph.getService(QueryControl.class);\r
+ return new BackupResource(qc.getIndependentGraph(graph));\r
+ }\r
+ });\r
+ session.registerService(BackupResource.class, ret);\r
+ }\r
+ return ret;\r
+ }\r
+ \r
+}\r
+\r