/**
* ***************************************************************************
* Copyright (c) 2010 Qcadoo Limited
* Project: Qcadoo Framework
* Version: 1.4
*
* This file is part of Qcadoo.
*
* 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.
*
* 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.
*
* 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 static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Set;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import com.google.common.base.Function;
import com.google.common.collect.Collections2;
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.EntityList;
import com.qcadoo.model.api.EntityOpResult;
public class HasManyIntegrationTest extends IntegrationTest {
// http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html#performance-collections
private static final String FIELD_COMPONENTS = "components";
private static final String FIELD_PARTS = "parts";
private DataDefinition productDataDefinition, machineDataDefinition, componentDataDefinition, partDataDefinition;
private static final Function<Entity, Long> EXTRACT_ID = new Function<Entity, Long>() {
@Override
public Long apply(final Entity entity) {
return entity.getId();
}
};
@Before
public final void init() {
productDataDefinition = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, ENTITY_NAME_PRODUCT);
machineDataDefinition = dataDefinitionService.get(PLUGIN_MACHINES_NAME, ENTITY_NAME_MACHINE);
componentDataDefinition = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, ENTITY_NAME_COMPONENT);
partDataDefinition = dataDefinitionService.get(PLUGIN_PRODUCTS_NAME, ENTITY_NAME_PART);
}
private void checkComponents(final Entity entity, final Entity... expectedEntities) {
checkHasManyField(entity, FIELD_COMPONENTS, expectedEntities);
}
private void checkParts(final Entity entity, final Entity... expectedEntities) {
checkHasManyField(entity, FIELD_PARTS, expectedEntities);
}
private void checkHasManyField(final Entity entity, final String fieldName, final Entity... expectedEntities) {
EntityList entities = entity.getHasManyField(fieldName);
Set<Long> ids = Sets.newHashSet(Collections2.transform(entity.getHasManyField(fieldName), EXTRACT_ID));
assertEquals(expectedEntities.length, entities.size());
for (Entity expectedEntity : expectedEntities) {
assertTrue("missing " + expectedEntity, ids.contains(expectedEntity.getId()));
}
}
@Test
@Ignore
public void shouldSaveHasManyField() throws Exception {
// given
Entity product = productDataDefinition.save(createProduct("asd", "asd"));
Entity machine = machineDataDefinition.save(createMachine("asd"));
Entity component1 = componentDataDefinition.save(createComponent("name1", product, machine));
Entity component2 = componentDataDefinition.save(createComponent("name2", product, machine));
// when
product = fromDb(product);
// then
checkComponents(product, component1, component2);
}
@Test
public final void shouldPerformCascadeDeletion() {
// given
Entity product = productDataDefinition.save(createProduct("someName", "someNumber"));
Entity part1 = partDataDefinition.save(createPart("part1", product));
Entity part2 = partDataDefinition.save(createPart("part2", product));
Entity part3 = partDataDefinition.save(createPart("part3", null));
product = fromDb(product);
// when
EntityOpResult result = productDataDefinition.delete(product.getId());
// then
assertTrue(result.isSuccessfull());
assertNull(fromDb(product));
assertNull(fromDb(part1));
assertNull(fromDb(part2));
assertNotNull(fromDb(part3));
}
@Test
public final void shouldPerformOrphansDeletion() {
// given
Entity product = productDataDefinition.save(createProduct("someName", "someNumber"));
Entity part1 = partDataDefinition.save(createPart("part1", product));
Entity part2 = partDataDefinition.save(createPart("part2", product));
Entity part3 = partDataDefinition.save(createPart("part3", null));
product = fromDb(product);
checkParts(product, part1, part2);
// when
product.setField(FIELD_PARTS, Lists.newArrayList(part2, part3));
Entity savedProduct = productDataDefinition.save(product);
// then
assertTrue(savedProduct.isValid());
assertNull(fromDb(part1));
checkParts(savedProduct, part2, part3);
checkParts(fromDb(product), part2, part3);
}
@Test
public final void shouldOnDeleteHookRejectCascadeNullification() {
// given
Entity component = createComponent("component", null, null);
component.setField("deletionIsAllowed", false);
component = componentDataDefinition.save(component);
Entity part1 = partDataDefinition.save(createComponentPart("part1", component));
Entity part2 = partDataDefinition.save(createComponentPart("part2", component));
Entity part3 = partDataDefinition.save(createComponentPart("part3", null));
component = fromDb(component);
// when
EntityOpResult result = componentDataDefinition.delete(component.getId());
// then
assertFalse(result.isSuccessfull());
Entity componentFromDb = fromDb(component);
assertNotNull(componentFromDb);
checkParts(componentFromDb, part1, part2);
Entity part1fromDb = fromDb(part1);
assertNotNull(part1fromDb);
assertNotNull(part1fromDb.getField("component"));
Entity part2fromDb = fromDb(part2);
assertNotNull(part2fromDb);
assertNotNull(part2fromDb.getField("component"));
Entity part3fromDb = fromDb(part3);
assertNotNull(part3fromDb);
assertNull(part3fromDb.getField("component"));
}
@Test
public final void shouldPerformCascadeNullification() {
// given
Entity component = createComponent("component", null, null);
component.setField("deletionIsAllowed", true);
component = componentDataDefinition.save(component);
Entity part1 = partDataDefinition.save(createComponentPart("part1", component));
Entity part2 = partDataDefinition.save(createComponentPart("part2", component));
Entity part3 = partDataDefinition.save(createComponentPart("part3", null));
component = fromDb(component);
// when
EntityOpResult result = componentDataDefinition.delete(component.getId());
// then
assertTrue(result.isSuccessfull());
assertNull(fromDb(component));
Entity part1fromDb = fromDb(part1);
assertNotNull(part1fromDb);
assertNull(part1fromDb.getField("component"));
Entity part2fromDb = fromDb(part2);
assertNotNull(part2fromDb);
assertNull(part2fromDb.getField("component"));
Entity part3fromDb = fromDb(part3);
assertNotNull(part3fromDb);
assertNull(part3fromDb.getField("component"));
}
@Test
public final void shouldPerformOrphansNullification() {
// given
Entity component = createComponent("component", null, null);
component.setField("deletionIsAllowed", true);
component = componentDataDefinition.save(component);
Entity part1 = partDataDefinition.save(createComponentPart("part1", component));
Entity part2 = partDataDefinition.save(createComponentPart("part2", component));
Entity part3 = partDataDefinition.save(createComponentPart("part3", null));
component = fromDb(component);
// when
component.setField(FIELD_PARTS, Lists.newArrayList(part2, part3));
Entity savedComponent = componentDataDefinition.save(component);
// then
assertTrue(savedComponent.isValid());
checkParts(fromDb(savedComponent), part2, part3);
Entity part1fromDb = fromDb(part1);
assertNotNull(part1fromDb);
assertNull(part1fromDb.getField("component"));
}
}