package com.constellio.model.extensions; import static com.constellio.model.entities.schemas.Schemas.TITLE; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.verifyZeroInteractions; import org.joda.time.LocalDateTime; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.Mock; import com.constellio.model.entities.Taxonomy; import com.constellio.model.entities.records.Record; import com.constellio.model.entities.records.Transaction; import com.constellio.model.entities.records.wrappers.User; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.extensions.behaviors.RecordExtension; import com.constellio.model.extensions.events.records.RecordCreationEvent; import com.constellio.model.extensions.events.records.RecordInCreationBeforeValidationAndAutomaticValuesCalculationEvent; import com.constellio.model.extensions.events.records.RecordInModificationBeforeValidationAndAutomaticValuesCalculationEvent; import com.constellio.model.extensions.events.records.RecordLogicalDeletionEvent; import com.constellio.model.extensions.events.records.RecordModificationEvent; import com.constellio.model.extensions.events.records.RecordPhysicalDeletionEvent; import com.constellio.model.extensions.events.records.RecordRestorationEvent; import com.constellio.model.services.extensions.ModelLayerExtensions; import com.constellio.model.services.records.RecordServices; import com.constellio.sdk.tests.ConstellioTest; import com.constellio.sdk.tests.TestRecord; import com.constellio.sdk.tests.schemas.TestsSchemasSetup; import com.constellio.sdk.tests.schemas.TestsSchemasSetup.AnotherSchemaMetadatas; import com.constellio.sdk.tests.schemas.TestsSchemasSetup.ZeSchemaMetadatas; public class RecordExtensionsAcceptanceTest extends ConstellioTest { LocalDateTime shishOClock = new LocalDateTime(); String anotherCollection = "anotherCollection"; TestsSchemasSetup schemas = new TestsSchemasSetup(); ZeSchemaMetadatas zeSchema = schemas.new ZeSchemaMetadatas(); AnotherSchemaMetadatas anotherSchema = schemas.new AnotherSchemaMetadatas(); RecordServices recordServices; @Mock RecordExtension recordExtension1; @Mock RecordExtension recordExtension2; @Mock RecordExtension otherCollectionRecordExtension; Record existingZeSchemaRecord, existingAnotherSchemaRecord, logicallyDeletedZeSchemaRecord, logicallyDeletedZeSchemaChildRecord, existingZeSchemaChildRecord; @Before public void setUp() throws Exception { defineSchemasManager().using(schemas .withTwoMetadatasCopyingAnotherSchemaValuesUsingTwoDifferentReferenceMetadata(false, false, false) .withAParentReferenceFromZeSchemaToZeSchema()); givenTimeIs(shishOClock); Taxonomy taxonomy = new Taxonomy("ze taxo", "ze taxo", zeCollection, zeSchema.typeCode()); getModelLayerFactory().getTaxonomiesManager().addTaxonomy(taxonomy, getModelLayerFactory().getMetadataSchemasManager()); recordServices = getModelLayerFactory().newRecordServices(); existingAnotherSchemaRecord = new TestRecord(anotherSchema, "existingAnotherSchemaRecord").set(TITLE, "My second record"); existingZeSchemaRecord = new TestRecord(zeSchema, "existingZeSchemaRecord").set(TITLE, "My first record") .set(zeSchema.firstReferenceToAnotherSchema(), existingAnotherSchemaRecord); existingZeSchemaChildRecord = new TestRecord(zeSchema, "existingZeSchemaChildRecord").set(TITLE, "Child record") .set(zeSchema.parentReferenceFromZeSchemaToZeSchema(), existingZeSchemaRecord); logicallyDeletedZeSchemaRecord = new TestRecord(zeSchema, "logicallyDeletedZeSchemaRecord") .set(TITLE, "Parent record"); logicallyDeletedZeSchemaChildRecord = new TestRecord(zeSchema, "logicallyDeletedZeSchemaChildRecord") .set(TITLE, "Child record").set(zeSchema.parentReferenceFromZeSchemaToZeSchema(), logicallyDeletedZeSchemaRecord); recordServices.execute(new Transaction(existingZeSchemaRecord, existingAnotherSchemaRecord, logicallyDeletedZeSchemaRecord, logicallyDeletedZeSchemaChildRecord, existingZeSchemaChildRecord)); recordServices.logicallyDelete(logicallyDeletedZeSchemaRecord, User.GOD); ModelLayerExtensions extensions = getModelLayerFactory().getExtensions(); ModelLayerCollectionExtensions zeCollectionListeners = extensions.forCollection(zeCollection); ModelLayerCollectionExtensions anotherCollectionListeners = extensions.forCollection(anotherCollection); zeCollectionListeners.recordExtensions.add(1, recordExtension1); zeCollectionListeners.recordExtensions.add(2, recordExtension2); anotherCollectionListeners.recordExtensions.add(1, otherCollectionRecordExtension); givenTimeIs(shishOClock.plusDays(1)); } @After public void verifyThatOtherCollectionListenersAreNeverCalled() { verifyZeroInteractions(otherCollectionRecordExtension); } @Test public void whenCreatingARecordThenListenersCalled() throws Exception { ArgumentCaptor<RecordInCreationBeforeValidationAndAutomaticValuesCalculationEvent> recordInCreationArgs = ArgumentCaptor .forClass(RecordInCreationBeforeValidationAndAutomaticValuesCalculationEvent.class); ArgumentCaptor<RecordCreationEvent> recordCreatedArgs = ArgumentCaptor.forClass(RecordCreationEvent.class); Record record1 = new TestRecord(zeSchema, "newZeSchemaRecord").set(TITLE, "My first record"); Record record2 = new TestRecord(anotherSchema, "newOtherSchemaRecord").set(TITLE, "My second record"); recordServices.execute(new Transaction(record1, record2)); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordInCreationBeforeValidationAndAutomaticValuesCalculation( recordInCreationArgs.capture()); inOrder.verify(recordExtension2).recordInCreationBeforeValidationAndAutomaticValuesCalculation( recordInCreationArgs.capture()); inOrder.verify(recordExtension1).recordInCreationBeforeValidationAndAutomaticValuesCalculation( recordInCreationArgs.capture()); inOrder.verify(recordExtension2).recordInCreationBeforeValidationAndAutomaticValuesCalculation( recordInCreationArgs.capture()); inOrder.verify(recordExtension1).recordCreated(recordCreatedArgs.capture()); inOrder.verify(recordExtension2).recordCreated(recordCreatedArgs.capture()); inOrder.verify(recordExtension1).recordCreated(recordCreatedArgs.capture()); inOrder.verify(recordExtension2).recordCreated(recordCreatedArgs.capture()); verifyZeroInteractions(otherCollectionRecordExtension); assertThat(recordInCreationArgs.getAllValues().get(0).getRecord().getId()).isEqualTo("newOtherSchemaRecord"); assertThat(recordInCreationArgs.getAllValues().get(1).getRecord().getId()).isEqualTo("newOtherSchemaRecord"); assertThat(recordInCreationArgs.getAllValues().get(2).getRecord().getId()).isEqualTo("newZeSchemaRecord"); assertThat(recordInCreationArgs.getAllValues().get(3).getRecord().getId()).isEqualTo("newZeSchemaRecord"); assertThat(recordCreatedArgs.getAllValues().get(0).getRecord().getId()).isEqualTo("newOtherSchemaRecord"); assertThat(recordCreatedArgs.getAllValues().get(1).getRecord().getId()).isEqualTo("newOtherSchemaRecord"); assertThat(recordCreatedArgs.getAllValues().get(2).getRecord().getId()).isEqualTo("newZeSchemaRecord"); assertThat(recordCreatedArgs.getAllValues().get(3).getRecord().getId()).isEqualTo("newZeSchemaRecord"); } @Test public void whenModifyingARecordThenListenersCalled() throws Exception { ArgumentCaptor<RecordInModificationBeforeValidationAndAutomaticValuesCalculationEvent> recordInModificationArgs = ArgumentCaptor .forClass(RecordInModificationBeforeValidationAndAutomaticValuesCalculationEvent.class); ArgumentCaptor<RecordModificationEvent> recordModifiedArgs = ArgumentCaptor.forClass(RecordModificationEvent.class); existingZeSchemaRecord.set(Schemas.TITLE, "new title"); existingAnotherSchemaRecord.set(Schemas.TITLE, "an other new title"); recordServices.execute(new Transaction(existingZeSchemaRecord, existingAnotherSchemaRecord)); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordInModificationBeforeValidationAndAutomaticValuesCalculation( recordInModificationArgs.capture()); inOrder.verify(recordExtension2).recordInModificationBeforeValidationAndAutomaticValuesCalculation( recordInModificationArgs.capture()); inOrder.verify(recordExtension1).recordInModificationBeforeValidationAndAutomaticValuesCalculation( recordInModificationArgs.capture()); inOrder.verify(recordExtension2).recordInModificationBeforeValidationAndAutomaticValuesCalculation( recordInModificationArgs.capture()); inOrder.verify(recordExtension1).recordModified(recordModifiedArgs.capture()); inOrder.verify(recordExtension2).recordModified(recordModifiedArgs.capture()); inOrder.verify(recordExtension1).recordModified(recordModifiedArgs.capture()); inOrder.verify(recordExtension2).recordModified(recordModifiedArgs.capture()); verifyZeroInteractions(otherCollectionRecordExtension); assertThat(recordInModificationArgs.getAllValues().get(0).getRecord().getId()) .isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(recordInModificationArgs.getAllValues().get(0).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("anotherSchemaType_default_title"); assertThat(recordInModificationArgs.getAllValues().get(1).getRecord().getId()) .isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(recordInModificationArgs.getAllValues().get(1).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("anotherSchemaType_default_title"); assertThat(recordInModificationArgs.getAllValues().get(2).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); assertThat(recordInModificationArgs.getAllValues().get(2).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("zeSchemaType_default_title"); assertThat(recordInModificationArgs.getAllValues().get(3).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); assertThat(recordInModificationArgs.getAllValues().get(3).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("zeSchemaType_default_title"); assertThat(recordModifiedArgs.getAllValues().get(0).getRecord().getId()).isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(recordModifiedArgs.getAllValues().get(0).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("anotherSchemaType_default_title", "anotherSchemaType_default_autocomplete", "anotherSchemaType_default_modifiedOn"); assertThat(recordModifiedArgs.getAllValues().get(1).getRecord().getId()).isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(recordModifiedArgs.getAllValues().get(1).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("anotherSchemaType_default_title", "anotherSchemaType_default_autocomplete", "anotherSchemaType_default_modifiedOn"); assertThat(recordModifiedArgs.getAllValues().get(2).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); assertThat(recordModifiedArgs.getAllValues().get(2).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("zeSchemaType_default_title", "zeSchemaType_default_autocomplete", "zeSchemaType_default_modifiedOn"); assertThat(recordModifiedArgs.getAllValues().get(3).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); assertThat(recordModifiedArgs.getAllValues().get(3).getModifiedMetadatas().toMetadatasCodesList()) .containsOnly("zeSchemaType_default_title", "zeSchemaType_default_autocomplete", "zeSchemaType_default_modifiedOn"); } @Test public void whenModifyingARecordWithImpactsThenListenerCalledForImpactedRecords() throws Exception { ArgumentCaptor<RecordModificationEvent> argumentCaptor = ArgumentCaptor.forClass(RecordModificationEvent.class); recordServices.update( existingAnotherSchemaRecord.set(Schemas.TITLE, "new title").set(anotherSchema.stringMetadata(), "New value!")); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordModified(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordModified(argumentCaptor.capture()); inOrder.verify(recordExtension1).recordModified(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordModified(argumentCaptor.capture()); assertThat(argumentCaptor.getAllValues().get(0).getRecord().getId()).isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(1).getRecord().getId()).isEqualTo(existingAnotherSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(2).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(3).getRecord().getId()).isEqualTo(existingZeSchemaRecord.getId()); } @Test public void whenLogicallyDeletingARecordThenListenersCalled() throws Exception { // ReindexingServices reindexingServices = new ReindexingServices(getModelLayerFactory()); // reindexingServices.reindexCollection(zeCollection, ReindexationMode.RECALCULATE_AND_REWRITE); ArgumentCaptor<RecordLogicalDeletionEvent> argumentCaptor = ArgumentCaptor.forClass(RecordLogicalDeletionEvent.class); recordServices.logicallyDelete(existingZeSchemaRecord, User.GOD); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordLogicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordLogicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension1).recordLogicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordLogicallyDeleted(argumentCaptor.capture()); assertThat(argumentCaptor.getAllValues()).extracting("record.id").containsOnly( existingZeSchemaRecord.getId(), existingZeSchemaRecord.getId(), existingZeSchemaChildRecord.getId(), existingZeSchemaChildRecord.getId() ); } @Test public void whenRestoringARecordThenListenersCalled() throws Exception { ArgumentCaptor<RecordRestorationEvent> argumentCaptor = ArgumentCaptor.forClass(RecordRestorationEvent.class); recordServices.restore(logicallyDeletedZeSchemaRecord, User.GOD); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordRestored(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordRestored(argumentCaptor.capture()); inOrder.verify(recordExtension1).recordRestored(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordRestored(argumentCaptor.capture()); assertThat(argumentCaptor.getAllValues().get(0).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(1).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(2).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaChildRecord.getId()); assertThat(argumentCaptor.getAllValues().get(3).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaChildRecord.getId()); } @Test public void whenPhysicallyARecordThenListenersCalled() throws Exception { ArgumentCaptor<RecordPhysicalDeletionEvent> argumentCaptor = ArgumentCaptor.forClass(RecordPhysicalDeletionEvent.class); recordServices.physicallyDelete(logicallyDeletedZeSchemaRecord, User.GOD); InOrder inOrder = inOrder(recordExtension1, recordExtension2); inOrder.verify(recordExtension1).recordPhysicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordPhysicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension1).recordPhysicallyDeleted(argumentCaptor.capture()); inOrder.verify(recordExtension2).recordPhysicallyDeleted(argumentCaptor.capture()); assertThat(argumentCaptor.getAllValues().get(0).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(1).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaRecord.getId()); assertThat(argumentCaptor.getAllValues().get(2).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaChildRecord.getId()); assertThat(argumentCaptor.getAllValues().get(3).getRecord().getId()) .isEqualTo(logicallyDeletedZeSchemaChildRecord.getId()); } }