1 package org.simantics.backup.db;
3 import java.nio.file.Path;
4 import java.util.ArrayList;
5 import java.util.HashSet;
7 import java.util.concurrent.Callable;
8 import java.util.concurrent.ExecutionException;
9 import java.util.concurrent.Future;
10 import java.util.concurrent.FutureTask;
12 import org.eclipse.core.runtime.CoreException;
13 import org.eclipse.core.runtime.IStatus;
14 import org.eclipse.core.runtime.MultiStatus;
15 import org.eclipse.core.runtime.Status;
16 import org.simantics.Simantics;
17 import org.simantics.backup.Activator;
18 import org.simantics.backup.BackupException;
19 import org.simantics.backup.Backups;
20 import org.simantics.backup.IBackupProvider;
21 import org.simantics.backup.ontology.BackupResource;
22 import org.simantics.db.ReadGraph;
23 import org.simantics.db.Resource;
24 import org.simantics.db.common.request.UniqueRead;
25 import org.simantics.db.exception.DatabaseException;
26 import org.simantics.db.layer0.adapter.Instances;
27 import org.simantics.db.layer0.util.Layer0Utils;
28 import org.simantics.db.layer0.variable.Variable;
29 import org.simantics.db.layer0.variable.Variables;
31 public class ModelledBackupProvider implements IBackupProvider {
33 List<IBackupProvider> modelledBackups = new ArrayList<>();
35 public ModelledBackupProvider() {
36 // Should this be on the constructor or can there be dynamic ontologies?
37 this.modelledBackups = getModelledBackups();
41 public void lock() throws BackupException {
42 Backups.lock(modelledBackups);
46 public Future<BackupException> backup(Path targetPath, int revision) throws BackupException {
47 final List<Future<BackupException>> backups = new ArrayList<>();
48 final List<Exception> exceptions = new ArrayList<>(backups.size());
49 for (IBackupProvider modelledBackup : modelledBackups) {
51 Future<BackupException> future = modelledBackup.backup(targetPath, revision);
53 } catch (BackupException e) {
57 FutureTask<BackupException> task = new FutureTask<>(new Callable<BackupException>() {
60 public BackupException call() throws Exception {
61 for (Future<BackupException> f : backups) {
63 Exception exception = f.get();
64 if (exception != null)
65 exceptions.add(exception);
66 } catch (InterruptedException | ExecutionException e) {
70 BackupException problem = null;
71 // Throw BackupException if any of the backup operations failed.
72 if (!exceptions.isEmpty()) {
73 IStatus[] ss = exceptions.stream()
74 .map(e -> new Status(IStatus.ERROR, Activator.BUNDLE_ID, e.getMessage(), e))
75 .toArray(IStatus[]::new);
76 problem = new BackupException(new CoreException(new MultiStatus(Activator.BUNDLE_ID, 0, ss,
77 "Backup operation(s) failed to complete.", null)));
82 new Thread(task).run();
87 public void unlock() throws BackupException {
88 Backups.unlock(modelledBackups);
92 public void restore(Path fromPath, int revision) throws BackupException {
93 for (IBackupProvider modelledBackup : modelledBackups) {
94 modelledBackup.restore(fromPath, revision);
99 private List<IBackupProvider> getModelledBackups() {
100 List<IBackupProvider> modelledProviders = new ArrayList<>(0);
102 modelledProviders = Simantics.getSession().syncRequest(new UniqueRead<List<IBackupProvider>>() {
105 public List<IBackupProvider> perform(ReadGraph graph) throws DatabaseException {
106 BackupResource BACKUP = BackupResource.getInstance(graph);
107 Instances query = graph.adapt(BACKUP.ModelledBackupProvider, Instances.class);
109 HashSet<Resource> providers = new HashSet<>();
111 List<Resource> ontologies = Layer0Utils.listOntologies(graph);
112 for (Resource ontology : ontologies) {
113 for(Resource provider : query.find(graph, ontology)) {
114 providers.add(provider);
117 List<IBackupProvider> modelledBackups = new ArrayList<>();
118 for (Resource provider : providers) {
119 Variable variable = Variables.getVariable(graph, provider);
120 IBackupProvider modelledBackup = variable.getPropertyValue(graph, "instance");
121 modelledBackups.add(modelledBackup);
124 return modelledBackups;
127 } catch (DatabaseException e) {
130 return modelledProviders;