diff --git a/data-upgrade-app-center/pom.xml b/data-upgrade-app-center/pom.xml new file mode 100644 index 00000000..856d5181 --- /dev/null +++ b/data-upgrade-app-center/pom.xml @@ -0,0 +1,39 @@ + + + + 4.0.0 + + org.exoplatform.addons.upgrade + upgrade + 7.0.x-maintenance-SNAPSHOT + + data-upgrade-app-center + jar + eXo Add-on:: Data Upgrade Add-on - App center + + 0.84 + + + + io.meeds.commons + commons-component-upgrade + provided + + + io.meeds.app-center + app-center-services + compile + + + \ No newline at end of file diff --git a/data-upgrade-app-center/src/main/java/org/exoplatform/upgrade/CleanFavoriteApplications.java b/data-upgrade-app-center/src/main/java/org/exoplatform/upgrade/CleanFavoriteApplications.java new file mode 100644 index 00000000..92ce2c0a --- /dev/null +++ b/data-upgrade-app-center/src/main/java/org/exoplatform/upgrade/CleanFavoriteApplications.java @@ -0,0 +1,97 @@ +package org.exoplatform.upgrade; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.exoplatform.commons.api.persistence.ExoTransactional; +import org.exoplatform.commons.persistence.impl.EntityManagerService; +import org.exoplatform.commons.upgrade.UpgradeProductPlugin; +import org.exoplatform.container.xml.InitParams; +import org.exoplatform.services.log.ExoLogger; +import org.exoplatform.services.log.Log; + +import io.meeds.appcenter.entity.ApplicationEntity; +import io.meeds.appcenter.entity.FavoriteApplicationEntity; +import jakarta.persistence.EntityManager; +import jakarta.persistence.Query; + +public class CleanFavoriteApplications extends UpgradeProductPlugin { + + private static final Log log = ExoLogger.getLogger(CleanFavoriteApplications.class.getName()); + + private EntityManagerService entityManagerService; + + public CleanFavoriteApplications(InitParams initParams, EntityManagerService entityManagerService) { + super(initParams); + this.entityManagerService = entityManagerService; + } + + @Override + public void processUpgrade(String oldVersion, String newVersion) { + long startupTime = System.currentTimeMillis(); + EntityManager entityManager = this.entityManagerService.getEntityManager(); + List duplicatedFavoriteAppsEntityList = getDuplicatedFavoriteAppsEntityList(entityManager); + if (duplicatedFavoriteAppsEntityList.isEmpty()) { + return; + } + log.info("Start upgrade of cleaning for favorite applications, {} favorite applications should be deleted", + duplicatedFavoriteAppsEntityList.size()); + Set uniqueUserNames = new HashSet<>(); + duplicatedFavoriteAppsEntityList.forEach(favoriteApplicationEntity -> uniqueUserNames.add((String) favoriteApplicationEntity[2])); + log.info("{} favorite applications duplicated for {} users", duplicatedFavoriteAppsEntityList.size(), uniqueUserNames.size()); + int favoriteApplicationCount = cleanFavoriteApps(entityManager, duplicatedFavoriteAppsEntityList); + log.info("End upgrade : Deleted {} favorite applications done it took {} ms", + favoriteApplicationCount, + System.currentTimeMillis() - startupTime); + } + + private List getDuplicatedFavoriteAppsEntityList(EntityManager entityManager) { + String selectQuery = "SELECT * FROM AC_FAVORITE_APPLICATION favoriteApp " + + "WHERE (favoriteApp.APPLICATION_ID, favoriteApp.USER_NAME) IN (" + + " SELECT favoriteApplication.APPLICATION_ID, favoriteApplication.USER_NAME " + + " FROM AC_FAVORITE_APPLICATION favoriteApplication " + + " GROUP BY favoriteApplication.APPLICATION_ID, favoriteApplication.USER_NAME " + " HAVING COUNT(*) > 1)"; + Query nativeQuery = entityManager.createNativeQuery(selectQuery); + return nativeQuery.getResultList(); + } + + protected int cleanFavoriteApps(EntityManager entityManager, List duplicatedFavoriteApplicationsEntityList) { + List duplicatedFavoriteAppsEntityList = + toFavoriteAppsEntityList(duplicatedFavoriteApplicationsEntityList); + List favoriteAppsEntityList = new ArrayList<>(); + int favoriteAppCount = 0; + for (FavoriteApplicationEntity favoriteApplicationEntity : duplicatedFavoriteAppsEntityList) { + FavoriteApplicationEntity favoriteAppEntityOfIdNull = + new FavoriteApplicationEntity(0L, + favoriteApplicationEntity.getApplication(), + favoriteApplicationEntity.getUserName(), + favoriteApplicationEntity.getOrder()); + if (favoriteAppsEntityList.contains(favoriteAppEntityOfIdNull)) { + deleteFavoriteApplication(entityManager, favoriteApplicationEntity.getId()); + favoriteAppCount += 1; + } else { + favoriteAppsEntityList.add(favoriteAppEntityOfIdNull); + } + } + return favoriteAppCount; + } + + List toFavoriteAppsEntityList(List objects) { + List favoriteAppsEntityList = new ArrayList<>(); + objects.forEach(object -> { + ApplicationEntity applicationEntity = new ApplicationEntity(); + applicationEntity.setId((Long) object[1]); + favoriteAppsEntityList.add(new FavoriteApplicationEntity((Long) object[0], applicationEntity, (String) object[2], null)); + }); + return favoriteAppsEntityList; + } + + @ExoTransactional + protected void deleteFavoriteApplication(EntityManager entityManager, Long favoriteApplicationId) { + String deleteQuery = "DELETE FROM AC_FAVORITE_APPLICATION WHERE ID = " + favoriteApplicationId; + Query query = entityManager.createNativeQuery(deleteQuery); + query.executeUpdate(); + } +} diff --git a/data-upgrade-app-center/src/main/resources/conf/portal/configuration.xml b/data-upgrade-app-center/src/main/resources/conf/portal/configuration.xml new file mode 100644 index 00000000..26380e50 --- /dev/null +++ b/data-upgrade-app-center/src/main/resources/conf/portal/configuration.xml @@ -0,0 +1,62 @@ + + + + + + org.exoplatform.commons.upgrade.UpgradeProductService + + CleanFavoriteApplications + addUpgradePlugin + org.exoplatform.upgrade.CleanFavoriteApplications + Remove duplicated favorite applications for all users + + + product.group.id + The groupId of the product + org.exoplatform.platform + + + plugin.upgrade.target.version + The plugin target version of selected groupId + 7.0.0 + + + plugin.execution.order + The plugin execution order + 10 + + + plugin.upgrade.execute.once + The plugin must be executed only once + true + + + plugin.upgrade.async.execution + The plugin will be executed in an asynchronous mode + true + + + + + diff --git a/data-upgrade-app-center/src/test/java/org/exoplatform/upgrade/CleanFavoriteApplicationsTest.java b/data-upgrade-app-center/src/test/java/org/exoplatform/upgrade/CleanFavoriteApplicationsTest.java new file mode 100644 index 00000000..992fe83b --- /dev/null +++ b/data-upgrade-app-center/src/test/java/org/exoplatform/upgrade/CleanFavoriteApplicationsTest.java @@ -0,0 +1,69 @@ +package org.exoplatform.upgrade; + +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.*; + +import java.util.List; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import org.exoplatform.commons.persistence.impl.EntityManagerService; +import org.exoplatform.container.xml.InitParams; + +import jakarta.persistence.EntityManager; +import jakarta.persistence.Query; + +public class CleanFavoriteApplicationsTest { + + @Mock + private EntityManagerService entityManagerService; + + @Mock + private EntityManager entityManager; + + @Mock + private Query query; + + private CleanFavoriteApplications cleanFavoriteApplications; + + @Before + public void setUp() { + MockitoAnnotations.openMocks(this); + InitParams initParams = new InitParams(); + cleanFavoriteApplications = new CleanFavoriteApplications(initParams, entityManagerService); + when(entityManagerService.getEntityManager()).thenReturn(entityManager); + } + + @Test + public void processUpgradeCleanDuplicatedFavoriteApps() { + List results = List.of(new Object[] { 1L, 100L, "user1" }, + new Object[] { 2L, 100L, "user1" }, + new Object[] { 3L, 101L, "test" }, + new Object[] { 4L, 101L, "test" }); + + when(entityManager.createNativeQuery(anyString())).thenReturn(query); + when(query.getResultList()).thenReturn(results); + when(query.executeUpdate()).thenReturn(2); + + cleanFavoriteApplications.processUpgrade("v1", "v1"); + + verify(entityManager, times(3)).createNativeQuery(anyString()); + verify(query, times(2)).executeUpdate(); + verify(entityManagerService, times(1)).getEntityManager(); + } + + @Test + public void processUpgradeNoDuplicatedFavoriteApps() { + List results = List.of(new Object[] { 1L, 100L, "user1" }, new Object[] { 2L, 101L, "test" }); + + when(entityManager.createNativeQuery(anyString())).thenReturn(query); + when(query.getResultList()).thenReturn(results); + + cleanFavoriteApplications.processUpgrade("v1", "v1"); + + verify(query, never()).executeUpdate(); + } +} diff --git a/pom.xml b/pom.xml index a0a39f73..e1d96f4e 100644 --- a/pom.xml +++ b/pom.xml @@ -30,6 +30,7 @@ data-upgrade-processes-permissions data-upgrade-move-folders data-upgrade-recordings-permissions + data-upgrade-app-center data-upgrade-packaging