/** * *************************************************************************** * 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.internal; import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertTrue; import static org.junit.Assert.assertFalse; import static org.mockito.BDDMockito.given; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyInt; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import java.util.List; import org.hibernate.Criteria; import org.hibernate.criterion.Projections; import org.junit.Assert; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.Matchers; import org.mockito.Mockito; import com.google.common.collect.Lists; import com.qcadoo.model.api.Entity; import com.qcadoo.model.api.types.HasManyType; import com.qcadoo.model.api.types.TreeType; import com.qcadoo.model.beans.sample.SampleParentDatabaseObject; import com.qcadoo.model.beans.sample.SampleSimpleDatabaseObject; import com.qcadoo.model.beans.sample.SampleTreeDatabaseObject; import com.qcadoo.model.internal.api.FieldHookDefinition; import com.qcadoo.model.internal.types.HasManyEntitiesType; import com.qcadoo.model.internal.types.TreeEntitiesType; import com.qcadoo.model.internal.validators.UniqueValidator; public final class DataAccessServiceCopyTest extends DataAccessTest { private static final String BELONGS_TO_SIMPLE = "belongsToSimple"; private static final String NAME = "name"; private static final String SIMPLE_1 = "simple1"; private static final String SIMPLE_2 = "simple1"; private static final String SIMPLE_3 = "simple1"; private static final String SIMPLE_4 = "simple1"; @Test public void shouldCopyEntity() throws Exception { // given SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(13L); simpleDatabaseObject.setName("Mr T"); simpleDatabaseObject.setAge(66); given(session.get(any(Class.class), Matchers.anyInt())).willReturn(simpleDatabaseObject); // when List<Entity> entities = dataDefinition.copy(new Long[] { 13L }); // then verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals(66, entities.get(0).getField("age")); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); } @Test public void shouldCopyEntityWithUniqueField() throws Exception { // given FieldHookDefinition fieldHook = new UniqueValidator(); // fieldHook.initialize(dataDefinition, fieldDefinitionName); fieldDefinitionName.withValidator(fieldHook); SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(13L); simpleDatabaseObject.setName("Mr T"); simpleDatabaseObject.setAge(66); given(criteria.setProjection(Projections.rowCount()).uniqueResult()).willReturn(0); given(session.get(any(Class.class), Matchers.anyInt())).willReturn(simpleDatabaseObject); // when List<Entity> entities = dataDefinition.copy(new Long[] { 13L }); // then verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals(66, entities.get(0).getField("age")); Assert.assertEquals("Mr T(1)", entities.get(0).getField(NAME)); } @Test public void shouldCopyEntityWithUniqueField2() throws Exception { // given FieldHookDefinition fieldHook = new UniqueValidator(); // fieldHook.initialize(dataDefinition, fieldDefinitionName); fieldDefinitionName.withValidator(fieldHook); SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(13L); simpleDatabaseObject.setName("Mr T(1)"); simpleDatabaseObject.setAge(66); given(hibernateService.getTotalNumberOfEntities(Mockito.any(Criteria.class))).willReturn(1, 0); given(session.get(any(Class.class), Matchers.anyInt())).willReturn(simpleDatabaseObject); // when List<Entity> entities = dataDefinition.copy(new Long[] { 13L }); // then verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals(66, entities.get(0).getField("age")); Assert.assertEquals("Mr T(3)", entities.get(0).getField(NAME)); } @Test public void shouldCopyEntityWithUniqueFieldWhenNull() throws Exception { // given FieldHookDefinition fieldHook = new UniqueValidator(); // fieldHook.initialize(dataDefinition, fieldDefinitionName); fieldDefinitionName.withValidator(fieldHook); SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(13L); simpleDatabaseObject.setName(null); simpleDatabaseObject.setAge(66); given(hibernateService.getTotalNumberOfEntities(Mockito.any(Criteria.class))).willReturn(0); given(session.get(any(Class.class), Matchers.anyInt())).willReturn(simpleDatabaseObject); // when List<Entity> entities = dataDefinition.copy(new Long[] { 13L }); // then verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals(66, entities.get(0).getField("age")); Assert.assertEquals(null, entities.get(0).getField(NAME)); } @Test public void shouldCopyEntityWithoutHasManyField() throws Exception { // given SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(12L); simpleDatabaseObject.setName("Mr T"); simpleDatabaseObject.setAge(66); SampleParentDatabaseObject parentDatabaseObject = new SampleParentDatabaseObject(); parentDatabaseObject.setId(13L); parentDatabaseObject.setName("Mr T"); given(criteria.setProjection(Projections.rowCount()).uniqueResult()).willReturn(1, 0); given(session.get(Mockito.eq(SampleSimpleDatabaseObject.class), Mockito.eq(12L))).willReturn(simpleDatabaseObject); given(session.get(Mockito.eq(SampleParentDatabaseObject.class), Mockito.eq(13L))).willReturn(parentDatabaseObject); given(criteria.list()).willReturn(Lists.newArrayList(simpleDatabaseObject)); // when List<Entity> entities = parentDataDefinition.copy(new Long[] { 13L }); // then verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); verify(session, times(1)).save(Mockito.any()); verify(session, never()).get(Mockito.eq(SampleSimpleDatabaseObject.class), anyInt()); } @SuppressWarnings({ "rawtypes", "unchecked" }) @Test public void shouldCopyEntityWithHasManyField() throws Exception { // given parentFieldDefinitionHasMany.withType(new HasManyEntitiesType("simple", "entity", "belongsTo", HasManyType.Cascade.DELETE, true, dataDefinitionService)); SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(12L); simpleDatabaseObject.setName("Mr T"); simpleDatabaseObject.setAge(66); SampleParentDatabaseObject parentDatabaseObject = new SampleParentDatabaseObject(); parentDatabaseObject.setId(13L); parentDatabaseObject.setName("Mr T"); given(hibernateService.getTotalNumberOfEntities(Mockito.any(Criteria.class))).willReturn(1, 0); given(session.get(Mockito.eq(SampleSimpleDatabaseObject.class), Mockito.eq(12L))).willReturn(simpleDatabaseObject); given(session.get(Mockito.eq(SampleParentDatabaseObject.class), Mockito.eq(13L))).willReturn(parentDatabaseObject); given(hibernateService.list(Mockito.any(Criteria.class))).willReturn((List) Lists.newArrayList(simpleDatabaseObject)); // when List<Entity> entities = parentDataDefinition.copy(new Long[] { 13L }); // then assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); verify(session, times(2)).save(Mockito.any()); verify(session, never()).get(Mockito.eq(SampleSimpleDatabaseObject.class), anyInt()); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void shouldCopyEntityWithManyToManyField() throws Exception { // given SampleSimpleDatabaseObject simpleDatabaseObject = new SampleSimpleDatabaseObject(); simpleDatabaseObject.setId(12L); simpleDatabaseObject.setName("Mr T"); simpleDatabaseObject.setAge(30); SampleParentDatabaseObject parentDatabaseObject = new SampleParentDatabaseObject(); parentDatabaseObject.setId(13L); parentDatabaseObject.setName("Mr T"); given(hibernateService.getTotalNumberOfEntities(Mockito.any(Criteria.class))).willReturn(1, 0); given(session.get(Mockito.eq(SampleSimpleDatabaseObject.class), Mockito.eq(12L))).willReturn(simpleDatabaseObject); given(session.get(Mockito.eq(SampleParentDatabaseObject.class), Mockito.eq(13L))).willReturn(parentDatabaseObject); given(hibernateService.list(Mockito.any(Criteria.class))).willReturn((List) Lists.newArrayList(simpleDatabaseObject)); // when List<Entity> entities = parentDataDefinition.copy(new Long[] { 13L }); // then assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); verify(session).save(Mockito.any()); verify(session, never()).get(Mockito.eq(SampleSimpleDatabaseObject.class), anyInt()); } @Test public void shouldCopyEntityWithoutTreeField() throws Exception { // given SampleTreeDatabaseObject treeDatabaseObject = new SampleTreeDatabaseObject(); treeDatabaseObject.setId(12L); treeDatabaseObject.setName("Mr T"); SampleParentDatabaseObject parentDatabaseObject = new SampleParentDatabaseObject(); parentDatabaseObject.setId(13L); parentDatabaseObject.setName("Mr T"); given(criteria.setProjection(Projections.rowCount()).uniqueResult()).willReturn(1, 0); given(session.get(Mockito.eq(SampleSimpleDatabaseObject.class), Mockito.eq(12L))).willReturn(treeDatabaseObject); given(session.get(Mockito.eq(SampleParentDatabaseObject.class), Mockito.eq(13L))).willReturn(parentDatabaseObject); given(criteria.list()).willReturn(Lists.newArrayList(treeDatabaseObject)); // when List<Entity> entities = parentDataDefinition.copy(new Long[] { 13L }); // then assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); verify(session, times(1)).save(Mockito.any()); verify(session, never()).get(Mockito.eq(SampleSimpleDatabaseObject.class), anyInt()); } @SuppressWarnings({ "unchecked", "rawtypes" }) @Test public void shouldCopyEntityWithTreeField() throws Exception { // given parentFieldDefinitionTree.withType(new TreeEntitiesType("tree", "entity", "owner", TreeType.Cascade.DELETE, true, dataDefinitionService)); SampleTreeDatabaseObject treeDatabaseObject = new SampleTreeDatabaseObject(); treeDatabaseObject.setId(12L); treeDatabaseObject.setName("Mr T"); SampleParentDatabaseObject parentDatabaseObject = new SampleParentDatabaseObject(); parentDatabaseObject.setId(13L); parentDatabaseObject.setName("Mr T"); given(hibernateService.getTotalNumberOfEntities(Mockito.any(Criteria.class))).willReturn(1, 0); given(session.get(Mockito.eq(SampleSimpleDatabaseObject.class), Mockito.eq(12L))).willReturn(treeDatabaseObject); given(session.get(Mockito.eq(SampleParentDatabaseObject.class), Mockito.eq(13L))).willReturn(parentDatabaseObject); given(hibernateService.list(Mockito.any(Criteria.class))).willReturn((List) Lists.newArrayList(treeDatabaseObject)); // when List<Entity> entities = parentDataDefinition.copy(new Long[] { 13L }); // then assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); Assert.assertEquals("Mr T", entities.get(0).getField(NAME)); verify(session, times(2)).save(Mockito.any()); verify(session, never()).get(Mockito.eq(SampleSimpleDatabaseObject.class), anyInt()); } @Test public void shouldCopyEntityWithoutInfinityCycleWith2Entities() { // given SampleSimpleDatabaseObject simpleDatabaseObject1 = new SampleSimpleDatabaseObject(); simpleDatabaseObject1.setId(1L); simpleDatabaseObject1.setName(SIMPLE_1); SampleSimpleDatabaseObject simpleDatabaseObject2 = new SampleSimpleDatabaseObject(); simpleDatabaseObject2.setId(2L); simpleDatabaseObject2.setName(SIMPLE_2); simpleDatabaseObject1.setBelongsToSimple(simpleDatabaseObject2); simpleDatabaseObject2.setBelongsToSimple(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject2); // when List<Entity> entities = null; try { entities = dataDefinition.copy(new Long[] { simpleDatabaseObject1.getId() }); } catch (StackOverflowError e) { Assert.fail(); } // then final ArgumentCaptor<SampleSimpleDatabaseObject> argCaptor = ArgumentCaptor.forClass(SampleSimpleDatabaseObject.class); verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); verify(session, times(1)).save(argCaptor.capture()); final SampleSimpleDatabaseObject savedObject = argCaptor.getValue(); assertEquals(SIMPLE_1, savedObject.getName()); assertFalse(simpleDatabaseObject1.getId().equals(savedObject.getId())); assertEquals(SIMPLE_2, savedObject.getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject2.getId(), savedObject.getBelongsToSimple().getId()); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); final Entity entityCopy = entities.get(0); Assert.assertEquals(SIMPLE_1, entityCopy.getField(NAME)); Assert.assertEquals(SIMPLE_2, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getField(NAME)); Assert.assertEquals(Long.valueOf(2L), entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getId()); assertFalse(simpleDatabaseObject1.getId().equals(entityCopy.getId())); } @Test public void shouldCopyEntityWithoutInfinityCycleWith3Entities() { // given SampleSimpleDatabaseObject simpleDatabaseObject1 = new SampleSimpleDatabaseObject(); simpleDatabaseObject1.setId(1L); simpleDatabaseObject1.setName(SIMPLE_1); SampleSimpleDatabaseObject simpleDatabaseObject2 = new SampleSimpleDatabaseObject(); simpleDatabaseObject2.setId(2L); simpleDatabaseObject2.setName(SIMPLE_2); SampleSimpleDatabaseObject simpleDatabaseObject3 = new SampleSimpleDatabaseObject(); simpleDatabaseObject3.setId(3L); simpleDatabaseObject3.setName(SIMPLE_3); simpleDatabaseObject1.setBelongsToSimple(simpleDatabaseObject2); simpleDatabaseObject2.setBelongsToSimple(simpleDatabaseObject3); simpleDatabaseObject3.setBelongsToSimple(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject2); stubSessionGet(simpleDatabaseObject3); // when List<Entity> entities = null; try { entities = dataDefinition.copy(new Long[] { simpleDatabaseObject1.getId() }); } catch (StackOverflowError e) { Assert.fail(); } // then final ArgumentCaptor<SampleSimpleDatabaseObject> argCaptor = ArgumentCaptor.forClass(SampleSimpleDatabaseObject.class); verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); verify(session, times(1)).save(argCaptor.capture()); final SampleSimpleDatabaseObject savedObject = argCaptor.getValue(); assertEquals(SIMPLE_1, savedObject.getName()); assertFalse(simpleDatabaseObject1.getId().equals(savedObject.getId())); assertEquals(SIMPLE_2, savedObject.getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject2.getId(), savedObject.getBelongsToSimple().getId()); assertEquals(SIMPLE_3, savedObject.getBelongsToSimple().getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject3.getId(), savedObject.getBelongsToSimple().getBelongsToSimple().getId()); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); final Entity entityCopy = entities.get(0); Assert.assertEquals(SIMPLE_1, entityCopy.getField(NAME)); Assert.assertEquals(SIMPLE_2, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getField(NAME)); Assert.assertEquals(SIMPLE_3, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getBelongsToField(BELONGS_TO_SIMPLE) .getField(NAME)); Assert.assertEquals(Long.valueOf(2L), entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getId()); assertFalse(simpleDatabaseObject1.getId().equals(entityCopy.getId())); } @Test public void shouldCopyEntityWithoutInfinityCycleWith4Entities() { // given SampleSimpleDatabaseObject simpleDatabaseObject1 = new SampleSimpleDatabaseObject(); simpleDatabaseObject1.setId(1L); simpleDatabaseObject1.setName(SIMPLE_1); SampleSimpleDatabaseObject simpleDatabaseObject2 = new SampleSimpleDatabaseObject(); simpleDatabaseObject2.setId(2L); simpleDatabaseObject2.setName(SIMPLE_2); SampleSimpleDatabaseObject simpleDatabaseObject3 = new SampleSimpleDatabaseObject(); simpleDatabaseObject3.setId(3L); simpleDatabaseObject3.setName(SIMPLE_3); SampleSimpleDatabaseObject simpleDatabaseObject4 = new SampleSimpleDatabaseObject(); simpleDatabaseObject4.setId(4L); simpleDatabaseObject4.setName(SIMPLE_4); simpleDatabaseObject1.setBelongsToSimple(simpleDatabaseObject2); simpleDatabaseObject2.setBelongsToSimple(simpleDatabaseObject3); simpleDatabaseObject3.setBelongsToSimple(simpleDatabaseObject4); simpleDatabaseObject4.setBelongsToSimple(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject1); stubSessionGet(simpleDatabaseObject2); stubSessionGet(simpleDatabaseObject3); stubSessionGet(simpleDatabaseObject4); // when List<Entity> entities = null; try { entities = dataDefinition.copy(new Long[] { simpleDatabaseObject1.getId() }); } catch (StackOverflowError e) { Assert.fail(); } // then final ArgumentCaptor<SampleSimpleDatabaseObject> argCaptor = ArgumentCaptor.forClass(SampleSimpleDatabaseObject.class); verify(session, times(1)).save(Mockito.any(SampleSimpleDatabaseObject.class)); verify(session, times(1)).save(argCaptor.capture()); final SampleSimpleDatabaseObject savedObject = argCaptor.getValue(); assertEquals(SIMPLE_1, savedObject.getName()); assertFalse(simpleDatabaseObject1.getId().equals(savedObject.getId())); assertEquals(SIMPLE_2, savedObject.getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject2.getId(), savedObject.getBelongsToSimple().getId()); assertEquals(SIMPLE_3, savedObject.getBelongsToSimple().getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject3.getId(), savedObject.getBelongsToSimple().getBelongsToSimple().getId()); assertEquals(SIMPLE_4, savedObject.getBelongsToSimple().getBelongsToSimple().getBelongsToSimple().getName()); assertEquals(simpleDatabaseObject4.getId(), savedObject.getBelongsToSimple().getBelongsToSimple().getBelongsToSimple() .getId()); assertEquals(1, entities.size()); assertTrue(entities.get(0).isValid()); final Entity entityCopy = entities.get(0); Assert.assertEquals(SIMPLE_1, entityCopy.getField(NAME)); Assert.assertEquals(SIMPLE_2, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getField(NAME)); Assert.assertEquals(SIMPLE_3, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getBelongsToField(BELONGS_TO_SIMPLE) .getField(NAME)); Assert.assertEquals(SIMPLE_4, entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getBelongsToField(BELONGS_TO_SIMPLE) .getBelongsToField(BELONGS_TO_SIMPLE).getField(NAME)); Assert.assertEquals(Long.valueOf(2L), entityCopy.getBelongsToField(BELONGS_TO_SIMPLE).getId()); assertFalse(simpleDatabaseObject1.getId().equals(entityCopy.getId())); } private void stubSessionGet(final SampleSimpleDatabaseObject sampleSimpleDatabaseObject) { given(session.get(sampleSimpleDatabaseObject.getClass(), sampleSimpleDatabaseObject.getId())).willReturn( sampleSimpleDatabaseObject); given(session.load(sampleSimpleDatabaseObject.getClass(), sampleSimpleDatabaseObject.getId())).willReturn( sampleSimpleDatabaseObject); } }