From 439d3cddbffe3647c16bb117697cd038825817da Mon Sep 17 00:00:00 2001 From: erickgonzalez Date: Tue, 30 Jul 2024 16:49:44 -0600 Subject: [PATCH] #27816 include in 23.10.24 LTS --- dotCMS/hotfix_tracking.md | 1 + .../dotcms/datagen/TemplateLayoutDataGen.java | 76 +- .../factories/MultiTreeAPITest.java | 1555 ++++++- .../templates/business/TemplateAPITest.java | 3874 ++++++++++++++++- .../com/dotcms/rest/api/v1/page/PageForm.java | 190 +- .../dotcms/rest/api/v1/page/PageResource.java | 5 - .../rest/api/v1/page/PageResourceHelper.java | 109 +- .../api/v1/template/TemplateLayoutView.java | 131 - .../api/v1/template/TemplateResource.java | 93 +- .../dotmarketing/factories/MultiTreeAPI.java | 107 +- .../factories/MultiTreeAPIImpl.java | 296 +- .../templates/business/TemplateAPI.java | 17 + .../templates/business/TemplateAPIImpl.java | 497 ++- .../templates/design/bean/LayoutChanges.java | 106 + .../templates/design/bean/TemplateLayout.java | 14 + 15 files changed, 6147 insertions(+), 924 deletions(-) create mode 100644 dotCMS/src/main/java/com/dotmarketing/portlets/templates/design/bean/LayoutChanges.java diff --git a/dotCMS/hotfix_tracking.md b/dotCMS/hotfix_tracking.md index 04c572f78a08..391e81ddddd0 100644 --- a/dotCMS/hotfix_tracking.md +++ b/dotCMS/hotfix_tracking.md @@ -135,3 +135,4 @@ This maintenance release includes the following code fixes: 128. https://github.com/dotCMS/core/issues/26477 : Search filter can't find/filter images #26477 129. https://github.com/dotCMS/core/issues/27297 : Edit Page: Edit Contentlet Dialog Language Support #27297 130. https://github.com/dotCMS/core/issues/26413 : Template Builder: Container Layout Editing Issue #26413 +131. https://github.com/dotCMS/core/issues/27816 : Content Displacement Bug when Editing Template #27816 \ No newline at end of file diff --git a/dotCMS/src/integration-test/java/com/dotcms/datagen/TemplateLayoutDataGen.java b/dotCMS/src/integration-test/java/com/dotcms/datagen/TemplateLayoutDataGen.java index 6ffd14474aa1..3445fcbe6842 100644 --- a/dotCMS/src/integration-test/java/com/dotcms/datagen/TemplateLayoutDataGen.java +++ b/dotCMS/src/integration-test/java/com/dotcms/datagen/TemplateLayoutDataGen.java @@ -5,12 +5,18 @@ import com.dotmarketing.portlets.containers.model.FileAssetContainer; import com.dotmarketing.portlets.templates.design.bean.*; +import javax.swing.*; import java.util.*; public class TemplateLayoutDataGen { - final Map> containersIds = new HashMap<>(); + private List rows; + + private List currentColumns; + + private Map> containersIds = new HashMap<>(); final Map> containersIdsInSidebar = new HashMap<>(); + private int currentColumnWidthPercent = 100; public static TemplateLayoutDataGen get(){ return new TemplateLayoutDataGen(); @@ -45,16 +51,11 @@ public TemplateLayoutDataGen withContainerInSidebar(final String identifier, fin } public TemplateLayout next() { - final List containers = createContainerUUIDS(containersIds); - final List containersInSidebar = createContainerUUIDS(containersIdsInSidebar); - - final List columns = new ArrayList<>(); - columns.add(new TemplateLayoutColumn(containers, 100, 1, null)); - final List rows = new ArrayList<>(); - rows.add(new TemplateLayoutRow(columns, null)); + final List containersInSidebar = createContainerUUIDS(containersIdsInSidebar); + final List innerRows = rows == null ? getDefaultRow() : getRows(); - final Body body = new Body(rows); + final Body body = new Body(innerRows); final TemplateLayout templateLayout = new TemplateLayout(); templateLayout.setBody(body); @@ -63,7 +64,25 @@ public TemplateLayout next() { return templateLayout; } - + + private List getRows() { + createNewRow(); + return rows; + } + + private List getDefaultRow() { + final List rows = new ArrayList<>(); + + final List containers = createContainerUUIDS(containersIds); + + final List columns = new ArrayList<>(); + columns.add(new TemplateLayoutColumn(containers, 100, 1, null)); + + rows.add(new TemplateLayoutRow(columns, null)); + + return rows; + } + private static List createContainerUUIDS(Map> containersIds) { final List containers = new ArrayList<>(); @@ -86,4 +105,39 @@ public TemplateLayoutDataGen withContainer(final Container container, final Stri public TemplateLayoutDataGen withContainer(final Container container) { return withContainer(container, null); } -} + + public TemplateLayoutDataGen addRow() { + + if (rows == null) { + rows = new ArrayList<>(); + currentColumns = new ArrayList<>(); + } else { + createNewRow(); + } + + return this; + } + + private void createNewRow() { + addNewColumn(); + + rows.add(new TemplateLayoutRow(currentColumns, null)); + currentColumns = new ArrayList<>(); + } + + public TemplateLayoutDataGen addColumn(final int widthPercent) { + if (containersIds != null && !containersIds.isEmpty()) { + addNewColumn(); + } + + currentColumnWidthPercent = widthPercent; + return this; + } + + private void addNewColumn() { + final List containers = createContainerUUIDS(containersIds); + currentColumns.add(new TemplateLayoutColumn(containers, currentColumnWidthPercent, 1, null)); + + containersIds = new HashMap<>(); + } +} \ No newline at end of file diff --git a/dotCMS/src/integration-test/java/com/dotmarketing/factories/MultiTreeAPITest.java b/dotCMS/src/integration-test/java/com/dotmarketing/factories/MultiTreeAPITest.java index 74e202341eb7..36d00ce60846 100644 --- a/dotCMS/src/integration-test/java/com/dotmarketing/factories/MultiTreeAPITest.java +++ b/dotCMS/src/integration-test/java/com/dotmarketing/factories/MultiTreeAPITest.java @@ -4,7 +4,6 @@ import com.dotcms.contenttype.model.type.ContentType; import com.dotcms.datagen.*; import com.dotcms.experiments.model.Experiment; -import com.dotcms.experiments.model.ExperimentVariant; import com.dotcms.rendering.velocity.directive.ParseContainer; import com.dotcms.util.IntegrationTestInitService; import com.dotcms.util.transform.TransformerLocator; @@ -14,7 +13,6 @@ import com.dotmarketing.beans.MultiTree; import com.dotmarketing.business.APILocator; import com.dotmarketing.business.CacheLocator; -import com.dotmarketing.business.Ruleable; import com.dotmarketing.common.db.DotConnect; import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; @@ -28,31 +26,23 @@ import com.dotmarketing.portlets.personas.model.Persona; import com.dotmarketing.portlets.structure.model.Structure; import com.dotmarketing.portlets.templates.design.bean.ContainerUUID; +import com.dotmarketing.portlets.templates.design.bean.LayoutChanges; import com.dotmarketing.portlets.templates.design.bean.TemplateLayout; import com.dotmarketing.portlets.templates.model.Template; import com.dotmarketing.startup.runonce.Task04315UpdateMultiTreePK; +import com.dotmarketing.util.Config; import com.dotmarketing.util.Logger; import com.dotmarketing.util.UUIDGenerator; import com.google.common.collect.HashBasedTable; import com.google.common.collect.Sets; import com.google.common.collect.Table; -import com.liferay.portal.model.User; -import graphql.AssertException; -import io.vavr.API; -import java.util.ArrayList; -import java.util.Collection; +import java.util.*; + import org.jetbrains.annotations.NotNull; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.*; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; import java.util.stream.Collectors; import static com.dotcms.util.CollectionsUtils.list; @@ -60,7 +50,7 @@ import static org.junit.Assert.*; public class MultiTreeAPITest extends IntegrationTestBase { - + private static final String CONTAINER = "CONTAINER"; private static final String PAGE = "PAGE"; @@ -72,10 +62,10 @@ public class MultiTreeAPITest extends IntegrationTestBase { @BeforeClass public static void initData() throws Exception { IntegrationTestInitService.getInstance().init(); - // testUpgradeTask(); + // testUpgradeTask(); buildInitalData(); } - + public static void testUpgradeTask() throws Exception { Task04315UpdateMultiTreePK task = Task04315UpdateMultiTreePK.class.getDeclaredConstructor().newInstance(); task.executeUpgrade(); @@ -150,15 +140,15 @@ public void testDeletes() throws Exception { deleteInitialData(); buildInitalData() ; List all = APILocator.getMultiTreeAPI().getAllMultiTrees(); - + List list = APILocator.getMultiTreeAPI().getMultiTrees(PAGE); deleteInitialData(); assertTrue("multiTree deletes", APILocator.getMultiTreeAPI().getAllMultiTrees().size() < all.size() ); assertTrue("multiTree deletes", APILocator.getMultiTreeAPI().getAllMultiTrees().size() == all.size() - list.size() ); } - - + + @Test public void testReorder() throws Exception { deleteInitialData(); @@ -245,22 +235,22 @@ public void testReorderWithVariant() throws Exception { assertTrue("multiTree reorders", ((Map) arrayList_3.get(3)).get("child").equals("CONTENTLET3")); assertTrue("multiTree reorders", ((Map) arrayList_3.get(4)).get("child").equals("CONTENTLET4")); } - + @Test public void findByChild() throws Exception { deleteInitialData(); buildInitalData() ; - + List list = APILocator.getMultiTreeAPI().getMultiTreesByChild(CONTENTLET + "0"); - + assertTrue("getByChild returns all results", list.size() == runs ); - - - + + + } - - - + + + @AfterClass public static void deleteInitialData() throws Exception { @@ -271,11 +261,11 @@ public static void deleteInitialData() throws Exception { } } - - - - - + + + + + @Test public void testSaveMultiTree() throws Exception { MultiTree mt = new MultiTree() @@ -284,40 +274,40 @@ public void testSaveMultiTree() throws Exception { .setContentlet("NEW_ONE") .setTreeOrder(0) .setInstanceId(RELATION_TYPE + 0); - + APILocator.getMultiTreeAPI().saveMultiTree(mt); - + MultiTree mt2 = APILocator.getMultiTreeAPI().getMultiTree(mt.getHtmlPage(), mt.getContainer(), mt.getContentlet(), mt.getRelationType()); assertTrue("multiTree save and get equals", mt.equals(mt2)); } - - - - - - + + + + + + @Test public void testLegacyMultiTreeSave() throws Exception { - + long time = System.currentTimeMillis(); - + MultiTree multiTree = new MultiTree(); multiTree.setHtmlPage( PAGE+time); multiTree.setContainer( CONTAINER +time); multiTree.setContentlet( CONTENTLET +time); multiTree.setTreeOrder( 1 ); APILocator.getMultiTreeAPI().saveMultiTree( multiTree ); - - + + MultiTree mt2 = APILocator.getMultiTreeAPI().getMultiTree(PAGE+time, CONTAINER +time, CONTENTLET +time, Container.LEGACY_RELATION_TYPE); - + assertTrue("multiTree save without relationtype and get equals", multiTree.equals(mt2)); } - - + + @Test public void testGetPageMultiTrees() throws Exception { final Template template = new TemplateDataGen().nextPersisted(); @@ -334,12 +324,12 @@ public void testGetPageMultiTrees() throws Exception { multiTree.setInstanceId("abc"); multiTree.setPersonalization(DOT_PERSONALIZATION_DEFAULT); multiTree.setTreeOrder( 1 ); - + //delete out any previous relation APILocator.getMultiTreeAPI().deleteMultiTree(multiTree); CacheLocator.getMultiTreeCache().clearCache(); Table> trees= APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - + Table> cachedTrees= APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); Logger.info(this, "\n\n**** cachedTrees: " + cachedTrees); @@ -349,14 +339,14 @@ public void testGetPageMultiTrees() throws Exception { CacheLocator.getMultiTreeCache().removePageMultiTrees(page.getIdentifier(), VariantAPI.DEFAULT_VARIANT.name()); trees= APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - + // cache flush forced a cache reload, so different objects in memory assert(trees!=cachedTrees); - + // but the objects should contain the same data assert(trees.equals(cachedTrees)); - // there is no container entry + // there is no container entry assert(!(cachedTrees.rowKeySet().contains(container.getIdentifier()))); @@ -364,7 +354,7 @@ public void testGetPageMultiTrees() throws Exception { APILocator.getMultiTreeAPI().saveMultiTree( multiTree ); Table> addedTrees= APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); assert(cachedTrees!=addedTrees); - + // did we get a new object from the cache? Assert.assertNotNull(cachedTrees); Assert.assertNotNull(addedTrees); @@ -372,88 +362,88 @@ public void testGetPageMultiTrees() throws Exception { Logger.info(this, "\n\n**** addedTrees: " + addedTrees); assertNotEquals(cachedTrees, addedTrees); assert(addedTrees.rowKeySet().contains(container.getIdentifier())); - + // check cache flush on delete APILocator.getMultiTreeAPI().deleteMultiTree(multiTree ); Table> deletedTrees= APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - + // did we get a new object from the cache? assert(!(addedTrees.equals(deletedTrees))); assert(!(deletedTrees.rowKeySet().contains(container.getIdentifier()))); } - - - /** - * This test makes sure that if you have a container that accepts 1 contentlet, then that container - * will take 1 contentlet for each persona and not just 1 contentlet in total. See: - * https://github.com/dotCMS/core/issues/17181 - * - * @throws Exception - */ - @Test - public void test_personalize_page_respects_max_contentlet_value_per_persona() throws Exception { - - final Template template = new TemplateDataGen().body("body").nextPersisted(); - final Folder folder = new FolderDataGen().nextPersisted(); - final HTMLPageAsset page = new HTMLPageDataGen(folder, template).nextPersisted(); - final Structure structure = new StructureDataGen().nextPersisted(); - final Container container = new ContainerDataGen().maxContentlets(1).withStructure(structure, "").nextPersisted(); - final Contentlet content1 = new ContentletDataGen(structure.getInode()).nextPersisted(); - final Contentlet content2 = new ContentletDataGen(structure.getInode()).nextPersisted(); - - final Persona persona = new PersonaDataGen().keyTag(UUIDGenerator.shorty()).nextPersisted(); - final String uniqueId = UUIDGenerator.shorty(); - - MultiTree multiTree = new MultiTree(); - multiTree.setHtmlPage(page); - multiTree.setContainer(container); - multiTree.setContentlet(content1); - multiTree.setInstanceId(uniqueId); - multiTree.setPersonalization(DOT_PERSONALIZATION_DEFAULT); - multiTree.setTreeOrder(1); - APILocator.getMultiTreeAPI().saveMultiTree(multiTree); - - multiTree = new MultiTree(); - multiTree.setHtmlPage(page); - multiTree.setContainer(container); - multiTree.setContentlet(content2); - multiTree.setInstanceId(uniqueId); - multiTree.setPersonalization(persona.getKeyTag()); - multiTree.setTreeOrder(1); - APILocator.getMultiTreeAPI().saveMultiTree(multiTree); - - Table> pageContents = APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - - for (final String containerId : pageContents.rowKeySet()) { - assertEquals("containers match. Saved:" + container.getIdentifier() + ", got:" + containerId, containerId, container.getIdentifier()); - - for (final String uuid : pageContents.row(containerId).keySet()) { - assertEquals("containers uuids match. Saved:" + uniqueId + ", got:" + uuid, uniqueId, uuid); - final Set personalizedContentletSet = pageContents.get(containerId, uniqueId); - - assertTrue("container should have 2 personalized contents - got :" + personalizedContentletSet.size(), - personalizedContentletSet.size() == 2); - assertTrue("container should have contentlet for keyTag:" + DOT_PERSONALIZATION_DEFAULT, personalizedContentletSet - .contains(new PersonalizedContentlet(content1.getIdentifier(), DOT_PERSONALIZATION_DEFAULT))); - assertTrue("container should have contentlet for persona:" + persona.getKeyTag(), - personalizedContentletSet.contains(new PersonalizedContentlet(content2.getIdentifier(), persona.getKeyTag()))); - } - - } - - } + + + /** + * This test makes sure that if you have a container that accepts 1 contentlet, then that container + * will take 1 contentlet for each persona and not just 1 contentlet in total. See: + * https://github.com/dotCMS/core/issues/17181 + * + * @throws Exception + */ + @Test + public void test_personalize_page_respects_max_contentlet_value_per_persona() throws Exception { + + final Template template = new TemplateDataGen().body("body").nextPersisted(); + final Folder folder = new FolderDataGen().nextPersisted(); + final HTMLPageAsset page = new HTMLPageDataGen(folder, template).nextPersisted(); + final Structure structure = new StructureDataGen().nextPersisted(); + final Container container = new ContainerDataGen().maxContentlets(1).withStructure(structure, "").nextPersisted(); + final Contentlet content1 = new ContentletDataGen(structure.getInode()).nextPersisted(); + final Contentlet content2 = new ContentletDataGen(structure.getInode()).nextPersisted(); + + final Persona persona = new PersonaDataGen().keyTag(UUIDGenerator.shorty()).nextPersisted(); + final String uniqueId = UUIDGenerator.shorty(); + + MultiTree multiTree = new MultiTree(); + multiTree.setHtmlPage(page); + multiTree.setContainer(container); + multiTree.setContentlet(content1); + multiTree.setInstanceId(uniqueId); + multiTree.setPersonalization(DOT_PERSONALIZATION_DEFAULT); + multiTree.setTreeOrder(1); + APILocator.getMultiTreeAPI().saveMultiTree(multiTree); + + multiTree = new MultiTree(); + multiTree.setHtmlPage(page); + multiTree.setContainer(container); + multiTree.setContentlet(content2); + multiTree.setInstanceId(uniqueId); + multiTree.setPersonalization(persona.getKeyTag()); + multiTree.setTreeOrder(1); + APILocator.getMultiTreeAPI().saveMultiTree(multiTree); + + Table> pageContents = APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); + + for (final String containerId : pageContents.rowKeySet()) { + assertEquals("containers match. Saved:" + container.getIdentifier() + ", got:" + containerId, containerId, container.getIdentifier()); + + for (final String uuid : pageContents.row(containerId).keySet()) { + assertEquals("containers uuids match. Saved:" + uniqueId + ", got:" + uuid, uniqueId, uuid); + final Set personalizedContentletSet = pageContents.get(containerId, uniqueId); + + assertTrue("container should have 2 personalized contents - got :" + personalizedContentletSet.size(), + personalizedContentletSet.size() == 2); + assertTrue("container should have contentlet for keyTag:" + DOT_PERSONALIZATION_DEFAULT, personalizedContentletSet + .contains(new PersonalizedContentlet(content1.getIdentifier(), DOT_PERSONALIZATION_DEFAULT))); + assertTrue("container should have contentlet for persona:" + persona.getKeyTag(), + personalizedContentletSet.contains(new PersonalizedContentlet(content2.getIdentifier(), persona.getKeyTag()))); + } + + } + + } @Test public void testMultiTreeForContainerStructure() throws Exception { //THIS USES THE INDEX WHICH IS SOMETIMES NOT THERE LOCALLY //final Contentlet contentlet = APILocator.getContentletAPIImpl().findAllContent(0,1).get(0); - + Map map = new DotConnect().setSQL("select * from contentlet_version_info").setMaxRows(1).loadObjectResults().get(0); final Contentlet contentlet = APILocator.getContentletAPIImpl().find(map.get("working_inode").toString(), APILocator.systemUser(), false); - - + + //Create a MultiTree and relate it to that Contentlet MultiTree mt = new MultiTree() @@ -491,20 +481,20 @@ public void testMultiTreesSave() throws Exception { final String parent1 = PAGE + time; MultiTree multiTree1 = new MultiTree() - .setHtmlPage(parent1 ) - .setContainer( CONTAINER +time) - .setContentlet( CONTENTLET +time) - .setInstanceId("1") - .setTreeOrder( 1 ); + .setHtmlPage(parent1 ) + .setContainer( CONTAINER +time) + .setContentlet( CONTENTLET +time) + .setInstanceId("1") + .setTreeOrder( 1 ); long time2 = time + 1; MultiTree multiTree2 = new MultiTree() - .setHtmlPage( parent1 ) - .setContainer( CONTAINER + time2) - .setContentlet( CONTENTLET + time2) - .setInstanceId("1") - .setTreeOrder( 2 ); + .setHtmlPage( parent1 ) + .setContainer( CONTAINER + time2) + .setContentlet( CONTENTLET + time2) + .setInstanceId("1") + .setTreeOrder( 2 ); APILocator.getMultiTreeAPI().saveMultiTrees( parent1, VariantAPI.DEFAULT_VARIANT.name(), list(multiTree1, multiTree2) ); @@ -604,9 +594,9 @@ public void testMultiTreesSaveAndPersonalizationForPage() throws Exception { final Container container = new ContainerDataGen().withStructure(structure, "").nextPersisted(); final Contentlet content = new ContentletDataGen(structure.getInode()).nextPersisted(); - - - + + + final MultiTreeAPI multiTreeAPI = new MultiTreeAPIImpl(); final String personalization = "dot:persona:somepersona"; @@ -986,14 +976,14 @@ public void shouldReplaceVariantAndPersonalizationMultiTree() throws Exception { assertEquals(variantA.name(), multiTree.getVariantId()); assertEquals(DOT_PERSONALIZATION_DEFAULT, multiTree.getPersonalization()); } else { - throw new AssertException("Contentlet not expected"); + throw new AssertionError("Contentlet not expected"); } } } /** * Method to Test: {@link MultiTreeAPI#getMultiTreesByVariant(String, String)} (String, String)} - * When: Create a Page with {@link MultiTree} is different {@link Variant} and call the + * When: Create a Page with {@link MultiTree} is different {@link Variant} and call the * {@link MultiTreeAPI#getMultiTreesByVariant(String, String)} method just for a specific {@link Variant} * Should: Return just the {@link MultiTree} for that {@link Variant} */ @@ -1388,13 +1378,13 @@ public void shouldReplaceEnglishMultiTree() throws Exception { final String uniqueId = UUIDGenerator.shorty(); new MultiTreeDataGen() - .setPage(page) - .setContainer(container) - .setContentlet(enContentlet) - .setInstanceID(uniqueId) - .setPersonalization(DOT_PERSONALIZATION_DEFAULT) - .setTreeOrder(1) - .nextPersisted(); + .setPage(page) + .setContainer(container) + .setContentlet(enContentlet) + .setInstanceID(uniqueId) + .setPersonalization(DOT_PERSONALIZATION_DEFAULT) + .setTreeOrder(1) + .nextPersisted(); new MultiTreeDataGen() .setPage(page) @@ -1552,10 +1542,10 @@ public void testEmptyContainersInAdvancedTemplate() throws DotDataException, Dot final Table> pageMultiTrees = APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - pageMultiTrees.rowKeySet().contains(container.getIdentifier()); - pageMultiTrees.rowKeySet().contains(emptyContainer.getIdentifier()); - pageMultiTrees.rowKeySet().contains(fileAssetContainer.getIdentifier()); - pageMultiTrees.rowKeySet().contains(emptyFileAssetContainer.getIdentifier()); + assertTrue(pageMultiTrees.rowKeySet().contains(container.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(emptyContainer.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(fileAssetContainer.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(emptyFileAssetContainer.getIdentifier())); } /** @@ -1593,10 +1583,10 @@ public void testEmptyContainersInDrawedTemplate() throws DotDataException, DotSe final Table> pageMultiTrees = APILocator.getMultiTreeAPI().getPageMultiTrees(page, false); - pageMultiTrees.rowKeySet().contains(container.getIdentifier()); - pageMultiTrees.rowKeySet().contains(emptyContainer.getIdentifier()); - pageMultiTrees.rowKeySet().contains(fileAssetContainer.getIdentifier()); - pageMultiTrees.rowKeySet().contains(emptyFileAssetContainer.getIdentifier()); + assertTrue(pageMultiTrees.rowKeySet().contains(container.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(emptyContainer.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(fileAssetContainer.getIdentifier())); + assertTrue(pageMultiTrees.rowKeySet().contains(emptyFileAssetContainer.getIdentifier())); } private void createContentAndMultiTree(Container container, FileAssetContainer fileAssetContainer, HTMLPageAsset page) { @@ -1982,18 +1972,18 @@ public void multiTreesByVariant() throws DotDataException { assertEquals(3, multiTreeList.size()); multiTreeList.stream().map(MultiTree::getContentlet).forEach(contentletId -> - assertTrue(contentlet_1_variant_1.getIdentifier().equals(contentletId) - || contentlet_2_variant_1.getIdentifier().equals(contentletId) - || contentlet_3_variant_1.getIdentifier().equals(contentletId)) + assertTrue(contentlet_1_variant_1.getIdentifier().equals(contentletId) + || contentlet_2_variant_1.getIdentifier().equals(contentletId) + || contentlet_3_variant_1.getIdentifier().equals(contentletId)) ); final List multiTreeList_2 = APILocator.getMultiTreeAPI().getMultiTrees(variant_2); assertEquals(3, multiTreeList_2.size()); multiTreeList_2.stream().map(MultiTree::getContentlet).forEach(contentletId -> - assertTrue(contentlet_1_variant_2.getIdentifier().equals(contentletId) - || contentlet_2_variant_2.getIdentifier().equals(contentletId) - || contentlet_3_variant_2.getIdentifier().equals(contentletId)) + assertTrue(contentlet_1_variant_2.getIdentifier().equals(contentletId) + || contentlet_2_variant_2.getIdentifier().equals(contentletId) + || contentlet_3_variant_2.getIdentifier().equals(contentletId)) ); } @@ -2701,7 +2691,7 @@ public void copyFromSpecificVariantToSpecificVariantNotDefaultPeronalizations() @NotNull private static List getContentsId(final String personaKey, final HTMLPageAsset page, - final Variant variant) throws DotDataException { + final Variant variant) throws DotDataException { final List contents = new DotConnect().setSQL( "SELECT child FROM multi_tree WHERE variant_id = ? AND parent1 = ? AND personalization = ?") .addParam(variant.name()) @@ -2913,4 +2903,1249 @@ public void deletePersonalizationSpecificVariant() throws DotDataException { assertEquals(1, APILocator.getMultiTreeAPI().getAllContentletReferencesCount(contentlet_4.getIdentifier())); assertEquals(1, APILocator.getMultiTreeAPI().getAllContentletReferencesCount(contentlet_5.getIdentifier())); } -} + + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have a Page with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you move the last instance to be the first one + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : Add to the instance 2 + * - Contentlet_2 : Add to the instance 3 + * - Contentlet_3 : Add to the instance 4 + * - Contentlet_5 : Add to the instance 4 + * - Contentlet_4 : Add to the instance 1 + * + * @throws DotDataException + */ + @Test + public void moveContainerUpdateMultiTrees() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + createMultiTrees(page, container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .change(container.getIdentifier(), "4", "1") + .change(container.getIdentifier(), "1", "2") + .change(container.getIdentifier(), "2", "3") + .change(container.getIdentifier(), "3", "4") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(5, multiTreesFromDB.size()); + + final Map> groupedByInstanceId = multiTreesFromDB.stream() + .collect(Collectors.groupingBy(MultiTree::getRelationType)); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId){ + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "2": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_1.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "4": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(MultiTree::getContentlet) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have a Page with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you move the instance 2 and 3 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 3 + * - Contentlet_3 : Add to the instance 2 + * - Contentlet_5 : Add to the instance 2 + * - Contentlet_4 : Add to the instance 4 + * + * @throws DotDataException + */ + @Test + public void moveJustTwoContainerUpdateMultiTrees() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + createMultiTrees(page, container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .change(container.getIdentifier(), "2", "3") + .change(container.getIdentifier(), "3", "2") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(5, multiTreesFromDB.size()); + + final Map> groupedByInstanceId = multiTreesFromDB.stream() + .collect(Collectors.groupingBy(MultiTree::getRelationType)); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId){ + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_1.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "2": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(MultiTree::getContentlet) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "4": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have a Page with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you remove the instance 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : removed + * - Contentlet_2 : Add to the instance 1 + * - Contentlet_3 : Add to the instance 2 + * - Contentlet_5 : Add to the instance 2 + * - Contentlet_4 : Add to the instance 3 + * + * @throws DotDataException + */ + @Test + public void removeContainerUpdateMultiTrees() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + createMultiTrees(page, container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container.getIdentifier(), "1") + .change(container.getIdentifier(), "2", "1") + .change(container.getIdentifier(), "3", "2") + .change(container.getIdentifier(), "4", "3") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(4, multiTreesFromDB.size()); + + final Map> groupedByInstanceId = multiTreesFromDB.stream() + .collect(Collectors.groupingBy(MultiTree::getRelationType)); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId){ + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "2": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(multiTree -> multiTree.getContentlet()) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } + + + private static void createMultiTrees(final HTMLPageAsset page, + Container container, Contentlet... contentlets) { + + final Contentlet contentlet_1 = contentlets[0]; + final Contentlet contentlet_2 = contentlets[1]; + final Contentlet contentlet_3 = contentlets[2]; + final Contentlet contentlet_4 = contentlets[3]; + final Contentlet contentlet_5 = contentlets[4]; + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("1") + .setContentlet(contentlet_1) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("2") + .setContentlet(contentlet_2) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("3") + .setContentlet(contentlet_3) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("3") + .setContentlet(contentlet_5) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("4") + .setContentlet(contentlet_4) + .nextPersisted(); + } + + private Map>> getMultiTreeByPageOrderByInstanceId(final String pageId, + final ArrayList> multiTreeResult, + final int multiTreeCurrentIndex) { + int innerMultiCurrentIndex = multiTreeCurrentIndex; + final Map>> multiTreesFromDB = new HashMap<>(); + + while (innerMultiCurrentIndex < multiTreeResult.size()) { + Map multiTreeMap = multiTreeResult.get(innerMultiCurrentIndex); + + if (pageId.equals(multiTreeMap.get("parent1").toString())) { + String relationType = multiTreeMap.get("relation_type").toString(); + innerMultiCurrentIndex++; + + List> contentlets = multiTreesFromDB.get(relationType); + + if (contentlets == null) { + contentlets = new ArrayList<>(); + + } + contentlets.add(multiTreeMap); + multiTreesFromDB.put(relationType, contentlets); + } else { + break; + } + } + + return multiTreesFromDB; + } + + private List>getMultiTreeByPageOrder(final String pageId, + final ArrayList> multiTreeResult, + final int multiTreeCurrentIndex) { + int innerMultiCurrentIndex = multiTreeCurrentIndex; + final List> multiTreesFromDB = new ArrayList<>(); + + while (innerMultiCurrentIndex < multiTreeResult.size()) { + Map multiTreeMap = multiTreeResult.get(innerMultiCurrentIndex); + + if (pageId.equals(multiTreeMap.get("parent1").toString())) { + innerMultiCurrentIndex++; + multiTreesFromDB.add(multiTreeMap); + } else { + break; + } + } + + return multiTreesFromDB; + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have 10 Page with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you move last the instance to be the first one + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : Add to the instance 2 + * - Contentlet_2 : Add to the instance 3 + * - Contentlet_3 : Add to the instance 4 + * - Contentlet_5 : Add to the instance 4 + * - Contentlet_4 : Add to the instance 1 + * + * @throws DotDataException + */ + @Test + public void moveContainerUpdateMultiTreesOnMultiplePages() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .change(container.getIdentifier(), "4", "1") + .change(container.getIdentifier(), "1", "2") + .change(container.getIdentifier(), "2", "3") + .change(container.getIdentifier(), "3", "4") + .build(); + + final int pagesNumber = 20; + final HTMLPageAsset[] pages = new HTMLPageAsset[pagesNumber]; + + for (int i = 0; i < pagesNumber; i++) { + pages[i] = new HTMLPageDataGen(host, template).nextPersisted(); + createMultiTrees(pages[i], container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + } + + final List pageIds = Arrays.stream(pages) + .map(page -> page.getIdentifier()) + .sorted(String::compareTo) + .collect(Collectors.toList()); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, pageIds); + + final String getMultiTreeQuery = "SELECT parent1,parent2,child,relation_type FROM multi_tree WHERE parent1 in (?" + + new String(new char[pageIds.size() - 1]).replace("\0", ", ?") + ") order by parent1"; + + final DotConnect dotConnect = new DotConnect().setSQL(getMultiTreeQuery); + + pageIds.stream().forEach(pageId -> dotConnect.addParam(pageId)); + final ArrayList> multiTreeResult = dotConnect.loadResults(); + int multiTreeCurrentIndex = 0; + + for (int i = 0; i < pagesNumber; i++) { + + final Map>> groupedByInstanceId = getMultiTreeByPageOrderByInstanceId(pageIds.get(i), + multiTreeResult, multiTreeCurrentIndex); + + final int size = groupedByInstanceId.values().stream().map(List::size).reduce(0, Integer::sum); + multiTreeCurrentIndex = multiTreeCurrentIndex + size; + + assertEquals(5, size); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List> multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId) { + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).get("child")); + break; + case "2": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_1.getIdentifier(), multiTrees.get(0).get("child")); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).get("child")); + break; + case "4": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(multiTree -> multiTree.get("child").toString()) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have 100 Page with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * Should: Return the list of pages under 100 millis + * + * @throws DotDataException + */ + @Test + @Ignore + public void moveContainerUpdateMultiTreesOnMultiplePagesPerformance() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .change(container.getIdentifier(), "4", "1") + .change(container.getIdentifier(), "1", "2") + .change(container.getIdentifier(), "2", "3") + .change(container.getIdentifier(), "3", "4") + .build(); + + final int pagesNumber = 100; + final HTMLPageAsset[] pages = new HTMLPageAsset[pagesNumber]; + + for (int i = 0; i < pagesNumber; i++) { + pages[i] = new HTMLPageDataGen(host, template).nextPersisted(); + createMultiTrees(pages[i], container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + } + + final List pageIds = Arrays.stream(pages) + .map(page -> page.getIdentifier()) + .sorted(String::compareTo) + .collect(Collectors.toList()); + + long start = System.currentTimeMillis(); + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, pageIds); + long end = System.currentTimeMillis(); + + assertTrue((end - start) < 100); + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have 20 Pages with 4 containers all of them are different instances of the same containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you remove the instance 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : removed + * - Contentlet_2 : Add to the instance 1 + * - Contentlet_3 : Add to the instance 2 + * - Contentlet_5 : Add to the instance 2 + * - Contentlet_4 : Add to the instance 3 + * + * @throws DotDataException + */ + @Test + public void removeContainerUpdateMultiTreesMultiPages() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final int pagesNumber = 20; + final HTMLPageAsset[] pages = new HTMLPageAsset[pagesNumber]; + + for (int i = 0; i < pagesNumber; i++) { + pages[i] = new HTMLPageDataGen(host, template).nextPersisted(); + createMultiTrees(pages[i], container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + } + + final List pageIds = Arrays.stream(pages) + .map(page -> page.getIdentifier()) + .sorted(String::compareTo) + .collect(Collectors.toList()); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container.getIdentifier(), "1") + .change(container.getIdentifier(), "2", "1") + .change(container.getIdentifier(), "3", "2") + .change(container.getIdentifier(), "4", "3") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, pageIds); + + final String getMultiTreeQuery = "SELECT parent1,parent2,child,relation_type FROM multi_tree WHERE parent1 in (?" + + new String(new char[pageIds.size() - 1]).replace("\0", ", ?") + ") order by parent1"; + + final DotConnect dotConnect = new DotConnect().setSQL(getMultiTreeQuery); + + pageIds.stream().forEach(pageId -> dotConnect.addParam(pageId)); + + final ArrayList> multiTreeResult = dotConnect.loadResults(); + int multiTreeCurrentIndex = 0; + + for (int i = 0; i < pagesNumber; i++) { + + final Map>> groupedByInstanceId = getMultiTreeByPageOrderByInstanceId(pageIds.get(i), multiTreeResult, + multiTreeCurrentIndex); + + final int size = groupedByInstanceId.values().stream().map(List::size).reduce(0, Integer::sum); + multiTreeCurrentIndex = multiTreeCurrentIndex + size; + + assertEquals(4, size); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List> multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId) { + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).get("child").toString()); + break; + case "2": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(multiTree -> multiTree.get("child").toString()) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).get("child").toString()); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have a Page with 5 containers instances from 3 different containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1, Container 1 + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + * - Contentlet_5 : Add to the instance 2, Container 1 + * + * And you move the Inatnce 2 of the Container 1 for to be the first one + * + * Should: The Contentlets should finish as: + * + * - Contentlet_5 : Add to the instance 1, Container 1 + * - Contentlet_1 : Add to the instance 2, Container 1 + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + + * + * @throws DotDataException + */ + @Test + public void moveContainersUpdateMultiTrees() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container_1 = new ContainerDataGen().nextPersisted(); + final Container container_2 = new ContainerDataGen().nextPersisted(); + final Container container_3 = new ContainerDataGen().nextPersisted(); + + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container_1, "1") + .withContainer(container_2, "1") + .withContainer(container_2, "2") + .withContainer(container_3, "1") + .withContainer(container_1, "2") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_1) + .setInstanceID("1") + .setContentlet(contentlet_1) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_2) + .setInstanceID("1") + .setContentlet(contentlet_2) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_2) + .setInstanceID("2") + .setContentlet(contentlet_3) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_3) + .setInstanceID("1") + .setContentlet(contentlet_5) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_1) + .setInstanceID("2") + .setContentlet(contentlet_4) + .nextPersisted(); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .change(container_1.getIdentifier(), "2", "1") + .change(container_1.getIdentifier(), "1", "2") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(5, multiTreesFromDB.size()); + + for (MultiTree multiTree : multiTreesFromDB) { + if (multiTree.getContainer().equals(container_1.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_4.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_1.getIdentifier()) && multiTree.getRelationType().equals("2")) { + assertEquals(contentlet_1.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_2.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_2.getIdentifier(), multiTree.getContentlet()); + }else if (multiTree.getContainer().equals(container_2.getIdentifier()) && multiTree.getRelationType().equals("2")) { + assertEquals(contentlet_3.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_3.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_5.getIdentifier(), multiTree.getContentlet()); + }else { + throw new AssertionError("UUID not expected: Container " + multiTree.getContainer() + " UUID " + multiTree.getRelationType()); + } + } + + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have a Page with 5 containers instances from 3 different containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1, Container 1 + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + * - Contentlet_5 : Add to the instance 2, Container 1 + * + * And you remove the instance 1 of COntainer 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : Removed + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + * - Contentlet_5 : Add to the instance 2, Container 1 + * + * @throws DotDataException + */ + @Test + public void removeContainersUpdateMultiTrees() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container_1 = new ContainerDataGen().nextPersisted(); + final Container container_2 = new ContainerDataGen().nextPersisted(); + final Container container_3 = new ContainerDataGen().nextPersisted(); + + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container_1, "1") + .withContainer(container_2, "1") + .withContainer(container_2, "2") + .withContainer(container_3, "1") + .withContainer(container_1, "2") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_1) + .setInstanceID("1") + .setContentlet(contentlet_1) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_2) + .setInstanceID("1") + .setContentlet(contentlet_2) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_2) + .setInstanceID("2") + .setContentlet(contentlet_3) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_3) + .setInstanceID("1") + .setContentlet(contentlet_4) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container_1) + .setInstanceID("2") + .setContentlet(contentlet_5) + .nextPersisted(); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container_1.getIdentifier(), "1") + .change(container_1.getIdentifier(), "2", "1") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(4, multiTreesFromDB.size()); + + for (MultiTree multiTree : multiTreesFromDB) { + if (multiTree.getContainer().equals(container_1.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_5.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_2.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_2.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_2.getIdentifier()) && multiTree.getRelationType().equals("2")) { + assertEquals(contentlet_3.getIdentifier(), multiTree.getContentlet()); + } else if (multiTree.getContainer().equals(container_3.getIdentifier()) && multiTree.getRelationType().equals("1")) { + assertEquals(contentlet_4.getIdentifier(), multiTree.getContentlet()); + } else { + throw new AssertionError("UUID not expected: Container " + multiTree.getContainer() + " UUID " + multiTree.getRelationType()); + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have 20 Page with 5 containers instances from 3 different containers, + * and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1, Container 1 + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + * - Contentlet_5 : Add to the instance 2, Container 1 + * + * And you remove the instance 1 of COntainer 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : Removed + * - Contentlet_2 : Add to the instance 1, Container 2 + * - Contentlet_3 : Add to the instance 2, Container 2 + * - Contentlet_4 : Add to the instance 1, Container 3 + * - Contentlet_5 : Add to the instance 2, Container 1 + * + * @throws DotDataException + */ + @Test + public void removeContainersUpdateMultiTreesMultiPages() throws DotDataException { + final Host host = new SiteDataGen().nextPersisted(); + final Container container_1 = new ContainerDataGen().nextPersisted(); + final Container container_2 = new ContainerDataGen().nextPersisted(); + final Container container_3 = new ContainerDataGen().nextPersisted(); + + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container_1, "1") + .withContainer(container_2, "1") + .withContainer(container_2, "2") + .withContainer(container_3, "1") + .withContainer(container_1, "2") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final int pagesNumber = 20; + final HTMLPageAsset[] pages = new HTMLPageAsset[pagesNumber]; + + for (int i = 0; i < pagesNumber; i++) { + pages[i] = new HTMLPageDataGen(host, template).nextPersisted(); + + new MultiTreeDataGen() + .setPage(pages[i]) + .setContainer(container_1) + .setInstanceID("1") + .setContentlet(contentlet_1) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(pages[i]) + .setContainer(container_2) + .setInstanceID("1") + .setContentlet(contentlet_2) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(pages[i]) + .setContainer(container_2) + .setInstanceID("2") + .setContentlet(contentlet_3) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(pages[i]) + .setContainer(container_3) + .setInstanceID("1") + .setContentlet(contentlet_4) + .nextPersisted(); + + new MultiTreeDataGen() + .setPage(pages[i]) + .setContainer(container_1) + .setInstanceID("2") + .setContentlet(contentlet_5) + .nextPersisted(); + } + + final List pageIds = Arrays.stream(pages) + .map(page -> page.getIdentifier()) + .sorted(String::compareTo) + .collect(Collectors.toList()); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container_1.getIdentifier(), "1") + .change(container_1.getIdentifier(), "2", "1") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, pageIds); + + + final String getMultiTreeQuery = "SELECT parent1,parent2,child,relation_type FROM multi_tree WHERE parent1 in (?" + + new String(new char[pageIds.size() - 1]).replace("\0", ", ?") + ") order by parent1"; + + final DotConnect dotConnect = new DotConnect().setSQL(getMultiTreeQuery); + pageIds.stream().forEach(pageId -> dotConnect.addParam(pageId)); + + final ArrayList> multiTreeResult = dotConnect.loadResults(); + int multiTreeCurrentIndex = 0; + + for (int i = 0; i < pagesNumber; i++) { + + final List> multiTress = getMultiTreeByPageOrder(pageIds.get(i), multiTreeResult, + multiTreeCurrentIndex); + + multiTreeCurrentIndex += multiTress.size(); + + assertEquals(4, multiTress.size()); + + for (final Map multiTree : multiTress) { + + if (multiTree.get("parent2").equals(container_1.getIdentifier()) && multiTree.get("relation_type").equals("1")) { + assertEquals(contentlet_5.getIdentifier(), multiTree.get("child")); + } else if (multiTree.get("parent2").equals(container_2.getIdentifier()) && multiTree.get("relation_type").equals("1")) { + assertEquals(contentlet_2.getIdentifier(), multiTree.get("child")); + } else if (multiTree.get("parent2").equals(container_2.getIdentifier()) && multiTree.get("relation_type").equals("2")) { + assertEquals(contentlet_3.getIdentifier(), multiTree.get("child")); + } else if (multiTree.get("parent2").equals(container_3.getIdentifier()) && multiTree.get("relation_type").equals("1")) { + assertEquals(contentlet_4.getIdentifier(), multiTree.get("child")); + } else { + throw new AssertionError("UUID not expected: Container " + multiTree.get("parent2") + " UUID " + multiTree.get("relation_type")); + } + } + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have disabled the DELETE_ORPHANED_CONTENTS_FROM_CONTAINER flag, and You have a Page with 4 containers + * all of them are different instances of the same containers, and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you remove the instance 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : ORPHANED + * - Contentlet_2 : Add to the instance 1 + * - Contentlet_3 : Add to the instance 2 + * - Contentlet_5 : Add to the instance 2 + * - Contentlet_4 : Add to the instance 3 + * + * @throws DotDataException + */ + @Test + public void removeContainerUpdateMultiTreesWithOrphaned() throws DotDataException { + + boolean deleteOrphanedContentsFromContainer = Config.getBooleanProperty("DELETE_ORPHANED_CONTENTS_FROM_CONTAINER", true); + MultiTreeAPIImpl.setDeleteOrphanedContentsFromContainer(false); + + try { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + createMultiTrees(page, container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container.getIdentifier(), "1") + .change(container.getIdentifier(), "2", "1") + .change(container.getIdentifier(), "3", "2") + .change(container.getIdentifier(), "4", "3") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(5, multiTreesFromDB.size()); + + final Map> groupedByInstanceId = multiTreesFromDB.stream() + .collect(Collectors.groupingBy(MultiTree::getRelationType)); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId) { + case "-1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_1.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "2": + assertEquals(2, multiTrees.size()); + + List contentlets = multiTrees.stream().map(multiTree -> multiTree.getContentlet()) + .collect(Collectors.toList()); + assertTrue(contentlets.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets.contains(contentlet_5.getIdentifier())); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } finally { + MultiTreeAPIImpl.setDeleteOrphanedContentsFromContainer(deleteOrphanedContentsFromContainer); + } + } + + /** + * Method to test: {@link MultiTreeAPIImpl#updateMultiTrees(LayoutChanges, Collection)} + * When: You have enabled the DELETE_ORPHANED_CONTENTS_FROM_CONTAINER flag, and You have a Page with 4 containers + * all of them are different instances of the same containers, and you have 5 Contentlets add as follows: + * - Contentlet_1 : Add to the instance 1 + * - Contentlet_2 : Add to the instance 2 + * - Contentlet_3 : Add to the instance 3 + * - Contentlet_5 : Add to the instance 3 + * - Contentlet_4 : Add to the instance 4 + * + * And you remove the instance 1 + * + * Should: The Contentlets should finish as: + * + * - Contentlet_1 : ORPHANED + * - Contentlet_2 : Add to the instance 1 + * - Contentlet_3 : Add to the instance 2 + * - Contentlet_5 : Add to the instance 2 + * - Contentlet_4 : Add to the instance 3 + * + * Also the page had a Contentlet_6 orphaned content + * + * @throws DotDataException + */ + @Test + public void removeContainerUpdateMultiTreesWhenAlreadyExistsOrphaned() throws DotDataException { + + boolean deleteOrphanedContentsFromContainer = Config.getBooleanProperty("DELETE_ORPHANED_CONTENTS_FROM_CONTAINER", true); + MultiTreeAPIImpl.setDeleteOrphanedContentsFromContainer(false); + + try { + final Host host = new SiteDataGen().nextPersisted(); + final Container container = new ContainerDataGen().nextPersisted(); + final ContentType contentType = new ContentTypeDataGen().nextPersisted(); + final Contentlet contentlet_1 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_2 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_3 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_4 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_5 = new ContentletDataGen(contentType).nextPersisted(); + final Contentlet contentlet_6 = new ContentletDataGen(contentType).nextPersisted(); + + final TemplateLayout templateLayout = new TemplateLayoutDataGen().withContainer(container, "1") + .withContainer(container, "2") + .withContainer(container, "3") + .withContainer(container, "4") + .next(); + + final Template template = new TemplateDataGen() + .drawed(true) + .drawedBody(templateLayout) + .nextPersisted(); + + final HTMLPageAsset page = new HTMLPageDataGen(host, template).nextPersisted(); + + createMultiTrees(page, container, contentlet_1, contentlet_2, contentlet_3, contentlet_4, contentlet_5); + + new MultiTreeDataGen() + .setPage(page) + .setContainer(container) + .setInstanceID("-1") + .setContentlet(contentlet_6) + .nextPersisted(); + + + final LayoutChanges layoutChanges = new LayoutChanges.Builder() + .remove(container.getIdentifier(), "1") + .change(container.getIdentifier(), "2", "1") + .change(container.getIdentifier(), "3", "2") + .change(container.getIdentifier(), "4", "3") + .build(); + + APILocator.getMultiTreeAPI().updateMultiTrees(layoutChanges, list(page.getIdentifier())); + + final List multiTreesFromDB = APILocator.getMultiTreeAPI().getMultiTrees(page.getIdentifier()); + assertEquals(6, multiTreesFromDB.size()); + + final Map> groupedByInstanceId = multiTreesFromDB.stream() + .collect(Collectors.groupingBy(MultiTree::getRelationType)); + + for (final String intanceId : groupedByInstanceId.keySet()) { + final List multiTrees = groupedByInstanceId.get(intanceId); + + switch (intanceId) { + case "-1": + assertEquals(2, multiTrees.size()); + + List contentlets_1 = multiTrees.stream().map(multiTree -> multiTree.getContentlet()) + .collect(Collectors.toList()); + + assertTrue(contentlets_1.contains(contentlet_1.getIdentifier())); + assertTrue(contentlets_1.contains(contentlet_6.getIdentifier())); + break; + case "1": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_2.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + case "2": + assertEquals(2, multiTrees.size()); + + List contentlets_2 = multiTrees.stream().map(multiTree -> multiTree.getContentlet()) + .collect(Collectors.toList()); + assertTrue(contentlets_2.contains(contentlet_3.getIdentifier())); + assertTrue(contentlets_2.contains(contentlet_5.getIdentifier())); + break; + case "3": + assertEquals(1, multiTrees.size()); + assertEquals(contentlet_4.getIdentifier(), multiTrees.get(0).getContentlet()); + break; + default: + throw new AssertionError("UUID not expected: " + intanceId); + } + } + } finally { + MultiTreeAPIImpl.setDeleteOrphanedContentsFromContainer(deleteOrphanedContentsFromContainer); + } + } +} \ No newline at end of file diff --git a/dotCMS/src/integration-test/java/com/dotmarketing/portlets/templates/business/TemplateAPITest.java b/dotCMS/src/integration-test/java/com/dotmarketing/portlets/templates/business/TemplateAPITest.java index dd1bb6cf97ea..9579b9cf769c 100644 --- a/dotCMS/src/integration-test/java/com/dotmarketing/portlets/templates/business/TemplateAPITest.java +++ b/dotCMS/src/integration-test/java/com/dotmarketing/portlets/templates/business/TemplateAPITest.java @@ -9,18 +9,9 @@ import com.dotcms.IntegrationTestBase; import com.dotcms.content.elasticsearch.ESQueryCache; -import com.dotcms.datagen.ContainerDataGen; -import com.dotcms.datagen.HTMLPageDataGen; -import com.dotcms.datagen.LanguageDataGen; -import com.dotcms.datagen.MultiTreeDataGen; -import com.dotcms.datagen.SiteDataGen; -import com.dotcms.datagen.TemplateAsFileDataGen; -import com.dotcms.datagen.TemplateDataGen; -import com.dotcms.datagen.TestDataUtils; -import com.dotcms.datagen.TestUserUtils; -import com.dotcms.datagen.ThemeDataGen; -import com.dotcms.datagen.UserDataGen; -import com.dotcms.datagen.VariantDataGen; +import com.dotcms.contenttype.model.type.ContentType; +import com.dotcms.datagen.*; +import com.dotcms.rendering.velocity.viewtools.DotTemplateTool; import com.dotcms.util.IntegrationTestInitService; import com.dotcms.variant.VariantAPI; import com.dotcms.variant.model.Variant; @@ -39,6 +30,7 @@ import com.dotmarketing.business.VersionableAPI; import com.dotmarketing.exception.DotDataException; import com.dotmarketing.exception.DotSecurityException; +import com.dotmarketing.factories.MultiTreeAPIImpl; import com.dotmarketing.portlets.AssetUtil; import com.dotmarketing.portlets.containers.business.ContainerAPI; import com.dotmarketing.portlets.containers.model.Container; @@ -51,20 +43,20 @@ import com.dotmarketing.portlets.languagesmanager.model.Language; import com.dotmarketing.portlets.structure.model.Structure; import com.dotmarketing.portlets.templates.business.TemplateFactory.HTMLPageVersion; -import com.dotmarketing.portlets.templates.design.bean.ContainerUUID; +import com.dotmarketing.portlets.templates.design.bean.*; import com.dotmarketing.portlets.templates.model.FileAssetTemplate; import com.dotmarketing.portlets.templates.model.Template; -import com.dotmarketing.util.Constants; -import com.dotmarketing.util.Logger; -import com.dotmarketing.util.UUIDGenerator; -import com.dotmarketing.util.UtilMethods; +import com.dotmarketing.util.*; import com.liferay.portal.model.User; + +import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; + import org.awaitility.Awaitility; import org.junit.Assert; import org.junit.BeforeClass; @@ -86,7 +78,7 @@ public class TemplateAPITest extends IntegrationTestBase { @BeforeClass public static void prepare () throws Exception { - + //Setting web app environment IntegrationTestInitService.getInstance().init(); @@ -103,12 +95,12 @@ public static void prepare () throws Exception { public void getContainersUUIDFromDrawTemplateBodyTest() throws Exception { final String templateBody = " This is just test
\n" + - " #parseContainer ('f4a02846-7ca4-4e08-bf07-a61366bbacbb','1552493847863') \n" + - "

This is just test

\n" + - " #parseContainer ('/application/containers/test1/','1552493847864') \n" + - "#parseContainer('/application/containers/test2/','1552493847868')\n" + - "#parseContainer('/application/containers/test3/' ,'1552493847869' )\n" + - "#parseContainer( '/application/containers/test4/', '1552493847870')\n"; + " #parseContainer ('f4a02846-7ca4-4e08-bf07-a61366bbacbb','1552493847863') \n" + + "

This is just test

\n" + + " #parseContainer ('/application/containers/test1/','1552493847864') \n" + + "#parseContainer('/application/containers/test2/','1552493847868')\n" + + "#parseContainer('/application/containers/test3/' ,'1552493847869' )\n" + + "#parseContainer( '/application/containers/test4/', '1552493847870')\n"; final TemplateAPI templateAPI = APILocator.getTemplateAPI(); final List containerUUIDS = templateAPI.getContainersUUIDFromDrawTemplateBody(templateBody); @@ -616,7 +608,7 @@ public void testFindLiveTemplateNoNPE() throws DotDataException, DotSecurityExce APILocator.getUserAPI().getSystemUser(), false); assertNull(template); - + } catch(NullPointerException e) { Logger.error(this, "getting non-existent template should not throw an NPE", e); @@ -738,7 +730,7 @@ public void testFindTemplatesNoLayout () throws Exception { //This method should only return Templates, no Layouts List