/** * *************************************************************************** * Copyright (c) 2010 Qcadoo Limited * Project: Qcadoo Framework * Version: 1.4 * <p> * This file is part of Qcadoo. * <p> * Qcadoo is free software; you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation; either version 3 of the License, * or (at your option) any later version. * <p> * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Affero General Public License for more details. * <p> * You should have received a copy of the GNU Affero General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA * *************************************************************************** */ package com.qcadoo.model.integration; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.qcadoo.model.api.DataDefinition; import com.qcadoo.model.api.Entity; import com.qcadoo.model.api.EntityOpResult; import com.qcadoo.model.internal.ProxyEntity; import junit.framework.Assert; import org.junit.Test; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; import static org.junit.Assert.*; public class ManyToManyIntegrationTest extends IntegrationTest { // http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-collections @Test @SuppressWarnings("unchecked") public void shouldSaveManyToManyField() throws Exception { // given DataDefinition productDataDefinition = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, ENTITY_NAME_PRODUCT); DataDefinition partDataDefinition = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, ENTITY_NAME_PART); Entity firstProduct = productDataDefinition.save(createProduct("asd", "00001")); Entity secondProduct = productDataDefinition.save(createProduct("fgh", "00002")); Entity thirdProduct = productDataDefinition.save(createProduct("jkl", "00003")); Entity firstPart = fromDb(save(createPart("qwe", firstProduct, Lists.newArrayList(firstProduct, secondProduct)))); Entity secondPart = fromDb(save(createPart("rty", secondProduct, Lists.newArrayList(firstProduct, thirdProduct)))); Entity thirdPart = fromDb(save(createPart("uiop", thirdProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct)))); // when firstProduct = productDataDefinition.get(firstProduct.getId()); secondProduct = productDataDefinition.get(secondProduct.getId()); thirdProduct = productDataDefinition.get(thirdProduct.getId()); // then Collection<Entity> firstProductParts = (Collection<Entity>) firstProduct.getField("partsManyToMany"); assertNotNull(firstProductParts); assertEquals(3, firstProductParts.size()); checkProxyCollection(firstProductParts, Lists.newArrayList(firstPart, secondPart, thirdPart)); Collection<Entity> secondProductParts = (Collection<Entity>) secondProduct.getField("partsManyToMany"); assertNotNull(secondProductParts); assertEquals(2, secondProductParts.size()); checkProxyCollection(secondProductParts, Lists.newArrayList(firstPart, thirdPart)); Collection<Entity> thirdProductParts = (Collection<Entity>) thirdProduct.getField("partsManyToMany"); assertNotNull(thirdProductParts); assertEquals(2, thirdProductParts.size()); checkProxyCollection(thirdProductParts, Lists.newArrayList(secondPart, thirdPart)); } private void checkProxyCollection(final Collection<Entity> proxyEntitiesSet, final List<Entity> entitiesList) { Set<Entity> loadedEntities = Sets.newHashSet(); for (Entity proxyEntity : proxyEntitiesSet) { assertTrue(proxyEntity instanceof ProxyEntity); assertTrue(proxyEntity.isValid()); loadedEntities.add(fromDb(proxyEntity)); } assertEquals(entitiesList.size(), loadedEntities.size()); assertTrue(loadedEntities.containsAll(entitiesList)); } @Test public void shouldGeteManyToManyFieldReturnDistinctCollection() throws Exception { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity firstPart = fromDb(save(createPart("qwe", firstProduct, Lists.newArrayList(firstProduct, firstProduct, firstProduct)))); firstProduct = fromDb(firstProduct); // when List<Entity> firstProductParts = firstProduct.getManyToManyField("partsManyToMany"); // then assertEquals(1, firstProductParts.size()); assertEquals(firstPart, fromDb(firstProductParts.get(0))); } @Test public void shouldEntityWithManyToManyFieldHashCodeDoNotMakeInfinityCycle() throws Exception { // given Entity firstProduct = save(createProduct("asd", "00001")); save(createPart("qwe", firstProduct, Lists.newArrayList(firstProduct))); firstProduct = fromDb(firstProduct); // when try { firstProduct.hashCode(); } catch (StackOverflowError e) { Assert.fail(); } } @Test public void shouldEntityWithManyToManyFieldEqualsDoNotMakeInfinityCycleAndReturnTue() throws Exception { // given Entity product = createProduct("asd", "00001"); product.setField("partsManyToMany", Lists.newArrayList(createPart("qwe", product, Lists.newArrayList(product)))); Entity otherProduct = createProduct("asd", "00001"); otherProduct.setField("partsManyToMany", Lists.newArrayList(createPart("qwe", otherProduct, Lists.newArrayList(otherProduct)))); // when try { Assert.assertEquals(product, otherProduct); } catch (StackOverflowError e) { Assert.fail(); } } @Test public void shouldCopyManyToManyField() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity firstPart = fromDb(save(createPart("qwe", firstProduct, Lists.newArrayList(firstProduct, secondProduct)))); Entity secondPart = fromDb(save(createPart("rty", secondProduct, Lists.newArrayList(firstProduct, thirdProduct)))); Entity thirdPart = fromDb(save(createPart("uiop", thirdProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct)))); // when Entity copyFirstProduct = firstProduct.getDataDefinition().copy(firstProduct.getId()).get(0); copyFirstProduct = fromDb(copyFirstProduct); Entity copyFirstPart = firstPart.getDataDefinition().copy(firstPart.getId()).get(0); copyFirstPart = fromDb(copyFirstPart); // then Collection<Entity> firstProductParts = copyFirstProduct.getManyToManyField("partsManyToMany"); assertNotNull(firstProductParts); assertEquals(3, firstProductParts.size()); checkProxyCollection(firstProductParts, Lists.newArrayList(firstPart, secondPart, thirdPart)); Collection<Entity> firstPartsCopied = copyFirstPart.getManyToManyField("products"); assertNotNull(firstPartsCopied); assertEquals(0, firstPartsCopied.size()); } @Test public final void shouldPerformCascadeDeletion() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity anotherProduct = save(createProduct("qwertyuiop", "00004")); Entity firstPart = save(createPart("qwe", anotherProduct, Lists.newArrayList(firstProduct, secondProduct))); Entity secondPart = save(createPart("rty", anotherProduct, Lists.newArrayList(firstProduct, thirdProduct))); Entity thirdPart = save(createPart("uiop", anotherProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct))); // when EntityOpResult result = delete(secondProduct); // then Assert.assertTrue(result.isSuccessfull()); Assert.assertNull(fromDb(firstPart)); Assert.assertNotNull(fromDb(secondPart)); Assert.assertNull(fromDb(thirdPart)); Assert.assertNotNull(fromDb(firstProduct)); Assert.assertNull(fromDb(secondProduct)); Assert.assertNotNull(fromDb(thirdProduct)); } @Test public final void shouldPerformCascadeDeletionDeeplyVariant() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity anotherProduct = save(createProduct("qwertyuiop", "00004")); Entity firstPart = save(createPart("qwe", anotherProduct, Lists.newArrayList(firstProduct, secondProduct))); Entity secondPart = save(createPart("rty", anotherProduct, Lists.newArrayList(firstProduct, thirdProduct))); Entity thirdPart = save(createPart("uiop", anotherProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct))); Entity factory1 = createFactory("factory1"); factory1.setField("parentPart", firstPart); factory1.setField("deletionIsProhibited", false); factory1 = save(factory1); firstPart = fromDb(firstPart); // when EntityOpResult result = delete(secondProduct); // then Assert.assertTrue(result.isSuccessfull()); Assert.assertNull(fromDb(firstPart)); Assert.assertNotNull(fromDb(secondPart)); Assert.assertNull(fromDb(thirdPart)); Assert.assertNull(fromDb(factory1)); Assert.assertNotNull(fromDb(firstProduct)); Assert.assertNull(fromDb(secondProduct)); Assert.assertNotNull(fromDb(thirdProduct)); } @Test public final void shouldOnDeleteHookRejectCascadeDeletion() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity anotherProduct = save(createProduct("qwertyuiop", "00004")); Entity firstPart = save(createPart("qwe", anotherProduct, Lists.newArrayList(firstProduct, secondProduct))); Entity secondPart = save(createPart("rty", anotherProduct, Lists.newArrayList(firstProduct, thirdProduct))); Entity thirdPart = save(createPart("uiop", anotherProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct))); thirdPart.setField("deletionIsProhibited", true); thirdPart = save(thirdPart); // when EntityOpResult result = delete(secondProduct); // then Assert.assertFalse(result.isSuccessfull()); Assert.assertNotNull(fromDb(firstPart)); Assert.assertNotNull(fromDb(secondPart)); Assert.assertNotNull(fromDb(thirdPart)); Assert.assertNotNull(fromDb(firstProduct)); Assert.assertNotNull(fromDb(secondProduct)); Assert.assertNotNull(fromDb(thirdProduct)); } @Test public final void shouldOnDeleteHookRejectCascadeDeletionDeeplyVariant() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity anotherProduct = save(createProduct("qwertyuiop", "00004")); Entity firstPart = save(createPart("qwe", anotherProduct, Lists.newArrayList(firstProduct, secondProduct))); Entity secondPart = save(createPart("rty", anotherProduct, Lists.newArrayList(firstProduct, thirdProduct))); Entity thirdPart = save(createPart("uiop", anotherProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct))); Entity factory1 = createFactory("factory1"); factory1.setField("parentPart", firstPart); factory1.setField("deletionIsProhibited", true); factory1 = save(factory1); firstPart = fromDb(firstPart); // when EntityOpResult result = delete(secondProduct); // then Assert.assertFalse(result.isSuccessfull()); Assert.assertNotNull(fromDb(firstPart)); Assert.assertNotNull(fromDb(secondPart)); Assert.assertNotNull(fromDb(thirdPart)); Assert.assertNotNull(fromDb(factory1)); Assert.assertNotNull(fromDb(firstProduct)); Assert.assertNotNull(fromDb(secondProduct)); Assert.assertNotNull(fromDb(thirdProduct)); } @Test public final void shouldPerformCascadeNullification() { // given Entity firstProduct = save(createProduct("asd", "00001")); Entity secondProduct = save(createProduct("fgh", "00002")); Entity thirdProduct = save(createProduct("jkl", "00003")); Entity anotherProduct = save(createProduct("qwertyuiop", "00004")); Entity firstPart = save(createPart("qwe", anotherProduct, Lists.newArrayList(firstProduct, secondProduct))); Entity secondPart = save(createPart("rty", anotherProduct, Lists.newArrayList(firstProduct, thirdProduct))); Entity thirdPart = save(createPart("uiop", anotherProduct, Lists.newArrayList(firstProduct, secondProduct, thirdProduct))); // when delete(secondPart); // then Entity firstProductFromDb = fromDb(firstProduct); Assert.assertNotNull(firstProductFromDb); Collection<Entity> firstProductParts = firstProductFromDb.getManyToManyField("partsManyToMany"); Assert.assertEquals(2, firstProductParts.size()); Assert.assertTrue(firstProductParts.contains(fromDb(firstPart))); Assert.assertFalse(firstProductParts.contains(fromDb(secondPart))); Assert.assertTrue(firstProductParts.contains(fromDb(thirdPart))); Entity secondProductFromDb = fromDb(secondProduct); Assert.assertNotNull(secondProductFromDb); Collection<Entity> secondProductParts = secondProductFromDb.getManyToManyField("partsManyToMany"); Assert.assertEquals(2, secondProductParts.size()); Assert.assertTrue(secondProductParts.contains(fromDb(firstPart))); Assert.assertFalse(secondProductParts.contains(fromDb(secondPart))); Assert.assertTrue(secondProductParts.contains(fromDb(thirdPart))); Entity thirdProductFromDb = fromDb(thirdProduct); Assert.assertNotNull(thirdProductFromDb); Collection<Entity> thirdProductParts = thirdProductFromDb.getManyToManyField("partsManyToMany"); Assert.assertEquals(1, thirdProductParts.size()); Assert.assertFalse(thirdProductParts.contains(fromDb(firstPart))); Assert.assertFalse(thirdProductParts.contains(fromDb(secondPart))); Assert.assertTrue(thirdProductParts.contains(fromDb(thirdPart))); Assert.assertNotNull(fromDb(firstPart)); Assert.assertNull(fromDb(secondPart)); Assert.assertNotNull(fromDb(thirdPart)); } @Test public void shouldLoadLazyLoading() { // given Entity product1 = save(createProduct("name-lazy-1", "number-lazy-1")); Entity vEntity = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, "versionableEntity").create(); vEntity.setField("name", "name-vEntity-1"); vEntity.setField("number", "number-vEntity-1"); vEntity.setField("products", Arrays.asList(product1, fromDb(save(createProduct("name-lazy-2", "number-lazy-2"))), fromDb(save(createProduct("name-lazy-3", "number-lazy-3"))))); vEntity = save(vEntity); // when Entity vEntityDb = fromDb(vEntity); Entity product1Db = fromDb(product1); // then Assert.assertEquals(3, vEntityDb.getManyToManyField("products").size()); Assert.assertEquals(1, product1Db.getManyToManyField("lazyManyToMany").size()); Assert.assertTrue(vEntity.getManyToManyField("products").contains(product1Db)); } }