View Javadoc
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  }