+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