1 package com.atlassian.activeobjects.internal;
2
3 import com.atlassian.activeobjects.external.ActiveObjects;
4 import com.atlassian.activeobjects.external.ActiveObjectsUpgradeTask;
5 import com.atlassian.activeobjects.external.ModelVersion;
6 import com.atlassian.sal.api.transaction.TransactionCallback;
7 import com.google.common.base.Supplier;
8 import com.google.common.collect.ImmutableList;
9 import org.slf4j.Logger;
10 import org.slf4j.LoggerFactory;
11
12 import java.util.Collections;
13 import java.util.Comparator;
14 import java.util.List;
15
16 import static com.google.common.base.Preconditions.checkNotNull;
17 import static com.google.common.collect.Lists.newArrayList;
18
19 public final class ActiveObjectUpgradeManagerImpl implements ActiveObjectUpgradeManager {
20 private final Logger logger = LoggerFactory.getLogger(this.getClass());
21
22 private final ModelVersionManager versionManager;
23
24 public ActiveObjectUpgradeManagerImpl(ModelVersionManager versionManager) {
25 this.versionManager = checkNotNull(versionManager);
26 }
27
28 @Override
29 public void upgrade(Prefix tableNamePrefix, List<ActiveObjectsUpgradeTask> upgradeTasks, final Supplier<ActiveObjects> ao) {
30 ModelVersion currentModelVersion = versionManager.getCurrent(tableNamePrefix);
31
32 logger.info("Starting upgrade of data model, current version is {}", currentModelVersion);
33
34 for (final ActiveObjectsUpgradeTask task : sortAndVerify(upgradeTasks)) {
35 if (currentModelVersion.isOlderThan(task.getModelVersion())) {
36 currentModelVersion = upgrade(tableNamePrefix, task, ao.get(), currentModelVersion);
37 }
38 }
39 logger.info("Finished upgrading, model is up to date at version {}", currentModelVersion);
40 }
41
42 private List<ActiveObjectsUpgradeTask> sortAndVerify(List<ActiveObjectsUpgradeTask> upgradeTasks) {
43 return verify(sort(upgradeTasks));
44 }
45
46 List<ActiveObjectsUpgradeTask> verify(List<ActiveObjectsUpgradeTask> sorted) {
47 ModelVersion mv = null;
48 for (ActiveObjectsUpgradeTask task : sorted) {
49 if (mv != null && mv.isSame(task.getModelVersion())) {
50 throw new IllegalStateException("There are more than one upgrade tasks with model version " + mv);
51 }
52 mv = task.getModelVersion();
53 }
54 return sorted;
55 }
56
57 private List<ActiveObjectsUpgradeTask> sort(List<ActiveObjectsUpgradeTask> upgradeTasks) {
58 final List<ActiveObjectsUpgradeTask> tasks = newArrayList(upgradeTasks);
59 Collections.sort(tasks, new ActiveObjectsUpgradeTaskComparator());
60 return ImmutableList.copyOf(tasks);
61 }
62
63 private ModelVersion upgrade(final Prefix tableNamePrefix, final ActiveObjectsUpgradeTask task, final ActiveObjects activeObjects, final ModelVersion currentModelVersion) {
64 return activeObjects.executeInTransaction(new TransactionCallback<ModelVersion>() {
65 @Override
66 public ModelVersion doInTransaction() {
67 logger.debug("Upgrading data model with task {}, current version of model is {}", task.getClass().getName(), currentModelVersion);
68 task.upgrade(currentModelVersion, activeObjects);
69
70 final ModelVersion updatedVersion = task.getModelVersion();
71 versionManager.update(tableNamePrefix, updatedVersion);
72 logger.debug("Upgraded data model to version {}", updatedVersion);
73 return updatedVersion;
74 }
75 });
76 }
77
78 private static class ActiveObjectsUpgradeTaskComparator implements Comparator<ActiveObjectsUpgradeTask> {
79 @Override
80 public int compare(ActiveObjectsUpgradeTask o1, ActiveObjectsUpgradeTask o2) {
81 return o1.getModelVersion().compareTo(o2.getModelVersion());
82 }
83 }
84 }