[ONOS-7458] Convert application state on read in ApplicationStore

Change-Id: I0877296fce8ac78748b57a88ba190b7ba233c0a9
diff --git a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
index 5e2ec0d..e03b645 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/app/DistributedApplicationStore.java
@@ -44,6 +44,8 @@
 import org.onosproject.app.ApplicationIdStore;
 import org.onosproject.core.CoreService;
 import org.onosproject.core.DefaultApplication;
+import org.onosproject.core.Version;
+import org.onosproject.core.VersionService;
 import org.onosproject.security.Permission;
 import org.onosproject.store.cluster.messaging.ClusterCommunicationService;
 import org.onosproject.store.cluster.messaging.MessageSubject;
@@ -51,13 +53,13 @@
 import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.MapEvent;
 import org.onosproject.store.service.MapEventListener;
+import org.onosproject.store.service.RevisionType;
 import org.onosproject.store.service.Serializer;
 import org.onosproject.store.service.StorageException;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.Topic;
 import org.onosproject.store.service.Versioned;
 import org.onosproject.store.service.DistributedPrimitive.Status;
-import org.onosproject.upgrade.UpgradeService;
 import org.slf4j.Logger;
 
 import java.io.ByteArrayInputStream;
@@ -132,7 +134,7 @@
     protected ApplicationIdStore idStore;
 
     @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
-    protected UpgradeService upgradeService;
+    protected VersionService versionService;
 
     private final InternalAppsListener appsListener = new InternalAppsListener();
     private final Consumer<Application> appActivator = new AppActivator();
@@ -170,6 +172,9 @@
                 .withSerializer(Serializer.using(KryoNamespaces.API,
                         InternalApplicationHolder.class,
                         InternalState.class))
+                .withVersion(versionService.version())
+                .withRevisionType(RevisionType.PROPAGATE)
+                .withCompatibilityFunction(this::convertApplication)
                 .build();
 
         appActivationTopic = storageService.getTopic("onos-apps-activation-topic",
@@ -189,39 +194,44 @@
         apps.addStatusChangeListener(statusChangeListener);
         coreAppId = getId(CoreService.CORE_APP_NAME);
 
-        upgradeExistingApplications();
+        activateExistingApplications();
         log.info("Started");
     }
 
     /**
-     * Upgrades application versions for existing applications that are stored on disk after an upgrade.
+     * Converts the versions of stored applications propagated from the prior version to the local application versions.
      */
-    private void upgradeExistingApplications() {
+    private InternalApplicationHolder convertApplication(InternalApplicationHolder appHolder, Version version) {
+        // Load the application description from disk. If the version doesn't match the persisted
+        // version, update the stored application with the new version.
+        ApplicationDescription appDesc = getApplicationDescription(appHolder.app.id().name());
+        if (!appDesc.version().equals(appHolder.app().version())) {
+            Application newApplication = DefaultApplication.builder(appHolder.app())
+                .withVersion(appDesc.version())
+                .build();
+            return new InternalApplicationHolder(
+                newApplication, appHolder.state, appHolder.permissions);
+        }
+        return appHolder;
+    }
+
+    /**
+     * Activates applications that should be activated according to the distributed store.
+     */
+    private void activateExistingApplications() {
         getApplicationNames().forEach(appName -> {
             // Only update the application version if the application has already been installed.
             ApplicationId appId = getId(appName);
             if (appId != null) {
-                Application application = getApplication(appId);
-                if (application != null) {
-                    InternalApplicationHolder appHolder = Versioned.valueOrNull(apps.get(application.id()));
+                ApplicationDescription appDesc = getApplicationDescription(appName);
+                InternalApplicationHolder appHolder = Versioned.valueOrNull(apps.get(appId));
 
-                    // Load the application description from disk. If the version doesn't match the persisted
-                    // version, update the stored application with the new version.
-                    ApplicationDescription appDesc = getApplicationDescription(appName);
-                    if (!appDesc.version().equals(application.version())) {
-                        Application newApplication = DefaultApplication.builder(application)
-                                .withVersion(appDesc.version())
-                                .build();
-                        InternalApplicationHolder newHolder = new InternalApplicationHolder(
-                                newApplication, appHolder.state, appHolder.permissions);
-                        apps.put(newApplication.id(), newHolder);
-                    }
-
-                    // If the application was activated in the previous version, set the local state to active.
-                    if (appHolder.state == ACTIVATED) {
-                        setActive(appName);
-                        updateTime(appName);
-                    }
+                // If the application has already been activated, set the local state to active.
+                if (appHolder != null
+                    && appDesc.version().equals(appHolder.app().version())
+                    && appHolder.state == ACTIVATED) {
+                    setActive(appName);
+                    updateTime(appName);
                 }
             }
         });