package com.constellio.model.services.schemas; import static com.constellio.model.entities.schemas.MetadataTransiency.TRANSIENT_EAGER; import static com.constellio.model.entities.schemas.MetadataTransiency.TRANSIENT_LAZY; import static com.constellio.model.entities.schemas.Schemas.TITLE; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.from; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.spy; import java.util.ArrayList; import java.util.List; import org.joda.time.LocalDateTime; import org.junit.Before; import org.junit.Test; 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.schemas.Metadata; import com.constellio.model.entities.schemas.MetadataSchemaTypes; import com.constellio.model.entities.schemas.MetadataTransiency; import com.constellio.model.entities.schemas.ModificationImpact; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.search.SearchServices; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.constellio.sdk.tests.ConstellioTest; import com.constellio.sdk.tests.TestRecord; public class ModificationImpactCalculatorAcceptTest extends ConstellioTest { List<Metadata> alreadyReindexedMetadata; RecordServices recordServices; MetadataSchemasManager schemasManager; //ModificationImpactCalculator impactCalculator; ModificationImpactCalculatorAcceptSetup schemas = new ModificationImpactCalculatorAcceptSetup(); ModificationImpactCalculatorAcceptSetup.ZeSchemaMetadatas zeSchema = schemas.new ZeSchemaMetadatas(); ModificationImpactCalculatorAcceptSetup.AnotherSchemaMetadatas anotherSchemaType = schemas.new AnotherSchemaMetadatas(); ModificationImpactCalculatorAcceptSetup.ThirdSchemaMetadatas thirdSchemaType = schemas.new ThirdSchemaMetadatas(); String aString = aString(); String aNewString = aString(); LocalDateTime aDate = aDateTime(); LocalDateTime aNewDate = aDateTime(); SearchServices searchServices; @Before public void setUp() throws Exception { searchServices = spy(getModelLayerFactory().newSearchServices()); alreadyReindexedMetadata = new ArrayList<>(); schemasManager = getModelLayerFactory().getMetadataSchemasManager(); recordServices = spy(getModelLayerFactory().newRecordServices()); } private ModificationImpactCalculator newImpactCalculator() { MetadataSchemaTypes types = getModelLayerFactory().getMetadataSchemasManager().getSchemaTypes(zeCollection); List<Taxonomy> taxonomies = getModelLayerFactory().getTaxonomiesManager().getEnabledTaxonomies(zeCollection); return new ModificationImpactCalculator(types, taxonomies, searchServices, recordServices); } @Test public void givenUnsavedRecordWhenCalculatingModificationImpactThenNothing() throws Exception { defineSchemasManager().using(schemas.withStringAndDateMetadataUsedForCopyAndCalculationInOtherSchemas()); Record newRecord = newRecordWithAStringAndADate(); List<ModificationImpact> impacts = newImpactCalculator().findTransactionImpact(new Transaction(newRecord), false); assertThat(impacts).isEmpty(); } @Test public void givenSavedWithModificationsInMetadataNotUsedInOtherSchemasWhenCalculatingModificationImpactThenNothing() throws Exception { defineSchemasManager().using(schemas.withStringAndDateMetadataUsedForCopyAndCalculationInOtherSchemas()); Record record = newRecordWithAStringAndADate(); recordServices.update(record); record.set(zeSchema.booleanMetadata(), true); List<ModificationImpact> impacts = newImpactCalculator().findTransactionImpact(new Transaction(record), false); assertThat(impacts).isEmpty(); } @Test public void givenRecordWithModificationsInMetadatasUsedInOtherSchemasWhenCalculatingModificationImpactHandlingInSameTransactionThenRequireReindexations() throws Exception { defineSchemasManager().using(schemas.withStringAndDateMetadataUsedForCopyAndCalculationInOtherSchemas()); Record record = newRecordWithAStringAndADate(); Record anotherSchemaRecord = newAnotherSchemaRecordUsing(record); Record thirdSchemaRecord = newThirdSchemaRecordUsing(record); recordServices.execute(new Transaction(thirdSchemaRecord, anotherSchemaRecord, record)); record.set(zeSchema.stringMetadata(), aNewString); record.set(zeSchema.dateTimeMetadata(), aNewDate); List<ModificationImpact> impacts = newImpactCalculator().findTransactionImpact(new Transaction(record), false); assertThat(impacts).hasSize(2); ModificationImpact anotherSchemaImpact; ModificationImpact thirdSchemaImpact; if (impacts.get(0).getMetadataToReindex().iterator().next().getCode().startsWith("another")) { anotherSchemaImpact = impacts.get(0); thirdSchemaImpact = impacts.get(1); } else { anotherSchemaImpact = impacts.get(1); thirdSchemaImpact = impacts.get(0); } LogicalSearchCondition anotherSchemaCondition = from(anotherSchemaType.type()) .whereAny(asList(anotherSchemaType.reference1ToZeSchema(), anotherSchemaType.reference2ToZeSchema())) .isIn(asList(record)).andWhere(Schemas.IDENTIFIER) .isNotIn(asList(record.getId())); assertThat(anotherSchemaImpact).isEqualTo( new ModificationImpact(anotherSchemaType.type(), anotherSchemaType.metadataUsingZeSchemaDateAndString(), anotherSchemaCondition, 1, null)); LogicalSearchCondition thirdSchemaCondition = from(thirdSchemaType.type()) .whereAny(asList(thirdSchemaType.referenceToZeSchema())).isIn(asList(record)) .andWhere(Schemas.IDENTIFIER) .isNotIn(asList(record.getId())); assertThat(thirdSchemaImpact).isEqualTo( new ModificationImpact(thirdSchemaType.type(), thirdSchemaType.metadataUsingZeSchemaDateAndString(), thirdSchemaCondition, 1, null)); } @Test public void givenRecordWithModificationsInMetadatasUsedInOtherSchemasWhenCalculatingModificationImpactHandlingInFutureTransactionsThenRequireReindexations() throws Exception { defineSchemasManager().using(schemas.withStringAndDateMetadataUsedForCopyAndCalculationInOtherSchemas()); Record record = newRecordWithAStringAndADate(); Record anotherSchemaRecord = newAnotherSchemaRecordUsing(record); Record thirdSchemaRecord = newThirdSchemaRecordUsing(record); recordServices.execute(new Transaction(thirdSchemaRecord, anotherSchemaRecord, record)); record.set(zeSchema.stringMetadata(), aNewString); record.set(zeSchema.dateTimeMetadata(), aNewDate); List<ModificationImpact> impacts = newImpactCalculator().findTransactionImpact(new Transaction(record), true); assertThat(impacts).hasSize(2); ModificationImpact anotherSchemaImpact; ModificationImpact thirdSchemaImpact; if (impacts.get(0).getMetadataToReindex().iterator().next().getCode().startsWith("another")) { anotherSchemaImpact = impacts.get(0); thirdSchemaImpact = impacts.get(1); } else { anotherSchemaImpact = impacts.get(1); thirdSchemaImpact = impacts.get(0); } LogicalSearchCondition anotherSchemaCondition = from(anotherSchemaType.type()) .whereAny(asList(anotherSchemaType.reference1ToZeSchema(), anotherSchemaType.reference2ToZeSchema())) .isIn(asList(record)); assertThat(anotherSchemaImpact).isEqualTo( new ModificationImpact(anotherSchemaType.type(), anotherSchemaType.metadataUsingZeSchemaDateAndString(), anotherSchemaCondition, 1, null)); LogicalSearchCondition thirdSchemaCondition = from(thirdSchemaType.type()) .whereAny(asList(thirdSchemaType.referenceToZeSchema())).isIn(asList(record)); assertThat(thirdSchemaImpact).isEqualTo( new ModificationImpact(thirdSchemaType.type(), thirdSchemaType.metadataUsingZeSchemaDateAndString(), thirdSchemaCondition, 1, null)); } @Test public void givenLazyTransientCalculatedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCalculatedInAnotherSchema(TRANSIENT_LAZY)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.referenceFromAnotherSchemaToZeSchema(), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitleLengthPlusTwo())).isEqualTo(17.0); recordServices.update(record("chat").set(TITLE, "Édouard")); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitleLengthPlusTwo())).isEqualTo(9.0); } @Test public void givenEagerTransientCalculatedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCalculatedInAnotherSchema(MetadataTransiency.TRANSIENT_EAGER)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.referenceFromAnotherSchemaToZeSchema(), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitleLengthPlusTwo())).isEqualTo(17.0); recordServices.update(record("chat").set(TITLE, "Édouard")); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitleLengthPlusTwo())).isEqualTo(9.0); } @Test public void givenLazyTransientCopiedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCopiedInAnotherSchema(TRANSIENT_LAZY)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.referenceFromAnotherSchemaToZeSchema(), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(15.0); recordServices.update(record("chat").set(TITLE, "Édouard")); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(7.0); } @Test public void givenEagerTransientCopiedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCopiedInAnotherSchema(MetadataTransiency.TRANSIENT_EAGER)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.referenceFromAnotherSchemaToZeSchema(), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(15.0); recordServices.update(record("chat").set(TITLE, "Édouard")); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(7.0); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenLazyTransientReferenceMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCopiedInAnotherSchema(TRANSIENT_LAZY) .withReferenceFromAnotherSchemaToZeSchemaComputedFromStringMetadata(TRANSIENT_LAZY)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(15.0); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), "chat2")); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(7.0); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenEagerTransientReferenceMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withComputedTitleSizeCopiedInAnotherSchema(MetadataTransiency.TRANSIENT_EAGER) .withReferenceFromAnotherSchemaToZeSchemaComputedFromStringMetadata(MetadataTransiency.TRANSIENT_EAGER)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), "chat")); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(15.0); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), "chat2")); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(7.0); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenLazyTransientMultivalueReferenceMetadataUsedByCalculatedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withTransientMultivalueReferenceUsedByCalculatedMetadata(TRANSIENT_LAZY)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(zeSchema, "chat3").set(TITLE, "Tomcat")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), asList("chat", "chat2"))); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitlesLength())).isEqualTo(asList(15.0, 7.0)); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), asList("chat2", "chat3"))); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitlesLength())).isEqualTo(asList(7.0, 6.0)); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenEagerTransientMultivalueReferenceMetadataUsedByCalculatedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withTransientMultivalueReferenceUsedByCalculatedMetadata(TRANSIENT_EAGER)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(zeSchema, "chat3").set(TITLE, "Tomcat")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), asList("chat", "chat2"))); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitlesLength())).isEqualTo(asList(15.0, 7.0)); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), asList("chat2", "chat3"))); assertThat(record("record").get(anotherSchemaType.calculatedZeSchemaTitlesLength())).isEqualTo(asList(7.0, 6.0)); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenLazyTransientMultivalueReferenceMetadataUsedByCopiedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withTransientMultivalueReferenceUsedByCopiedMetadata(TRANSIENT_LAZY)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(zeSchema, "chat3").set(TITLE, "Tomcat")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), asList("chat", "chat2"))); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(asList(15.0, 7.0)); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), asList("chat2", "chat3"))); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(asList(7.0, 6.0)); } //TODO Disabled test since the impact modification do a search on the reference metadata @Test public void givenEagerTransientMultivalueReferenceMetadataUsedByCopiedMetadataThenModificationPropagated() throws Exception { defineSchemasManager().using(schemas.withTransientMultivalueReferenceUsedByCopiedMetadata(TRANSIENT_EAGER)); Transaction tx = new Transaction(); tx.add(new TestRecord(zeSchema, "chat").set(TITLE, "Vodka Framboise")); tx.add(new TestRecord(zeSchema, "chat2").set(TITLE, "Édouard")); tx.add(new TestRecord(zeSchema, "chat3").set(TITLE, "Tomcat")); tx.add(new TestRecord(anotherSchemaType, "record").set(anotherSchemaType.metadata("aString"), asList("chat", "chat2"))); recordServices.execute(tx); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(asList(15.0, 7.0)); recordServices.update(record("record").set(anotherSchemaType.metadata("aString"), asList("chat2", "chat3"))); assertThat(record("record").get(anotherSchemaType.copiedZeSchemaTitleLength())).isEqualTo(asList(7.0, 6.0)); } private Record newAnotherSchemaRecordUsing(Record record) { Record newRecord = recordServices.newRecordWithSchema(anotherSchemaType.instance()); newRecord.set(anotherSchemaType.reference1ToZeSchema(), record); return newRecord; } private Record newThirdSchemaRecordUsing(Record record) { Record newRecord = recordServices.newRecordWithSchema(thirdSchemaType.instance()); newRecord.set(thirdSchemaType.referenceToZeSchema(), record); return newRecord; } private Record newRecordWithAStringAndADate() { Record newRecord = recordServices.newRecordWithSchema(zeSchema.instance()); newRecord.set(zeSchema.stringMetadata(), aString); newRecord.set(zeSchema.dateTimeMetadata(), aDate); return newRecord; } }