package com.constellio.model.services.records;
import static com.constellio.sdk.tests.TestUtils.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import com.constellio.data.dao.managers.config.ConfigManager;
import com.constellio.model.entities.Taxonomy;
import com.constellio.model.entities.calculators.CalculatorParameters;
import com.constellio.model.entities.calculators.MetadataValueCalculator;
import com.constellio.model.entities.calculators.dependencies.Dependency;
import com.constellio.model.entities.calculators.dependencies.HierarchyDependencyValue;
import com.constellio.model.entities.calculators.dependencies.SpecialDependencies;
import com.constellio.model.entities.calculators.dependencies.SpecialDependency;
import com.constellio.model.entities.records.Record;
import com.constellio.model.entities.records.RecordUpdateOptions;
import com.constellio.model.entities.records.Transaction;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.entities.schemas.MetadataValueType;
import com.constellio.model.services.schemas.MetadataSchemasManager;
import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder;
import com.constellio.sdk.tests.ConstellioTest;
import com.constellio.sdk.tests.TestRecord;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.DocumentSchema;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.FolderSchema;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.Taxonomy1FirstSchemaType;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.Taxonomy1SecondSchemaType;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.Taxonomy2CustomSchema;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.Taxonomy2DefaultSchema;
import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.TaxonomyRecords;
public class RecordAutomaticMetadataServices_TaxonomiesRealTest extends ConstellioTest {
RecordUpdateOptions options = new RecordUpdateOptions();
TwoTaxonomiesContainingFolderAndDocumentsSetup schemas =
new TwoTaxonomiesContainingFolderAndDocumentsSetup(zeCollection);
FolderSchema folderSchema = schemas.new FolderSchema();
DocumentSchema documentSchema = schemas.new DocumentSchema();
Taxonomy1FirstSchemaType taxonomy1FirstSchema = schemas.new Taxonomy1FirstSchemaType();
Taxonomy1SecondSchemaType taxonomy1SecondSchema = schemas.new Taxonomy1SecondSchemaType();
Taxonomy2DefaultSchema taxonomy2DefaultSchema = schemas.new Taxonomy2DefaultSchema();
Taxonomy2CustomSchema taxonomy2CustomSchema = schemas.new Taxonomy2CustomSchema();
TestRecord rootFolderWithTaxonomy;
TestRecord subFolderWithTaxonomy;
TestRecord document;
TaxonomyRecords records;
RecordAutomaticMetadataServices services;
MetadataSchemasManager schemaManager;
RecordServices recordServices;
ConfigManager configManager;
@Mock RecordProvider recordProvider;
Map<Dependency, Object> values;
List<String> expectedPaths;
List<String> authorizations = new ArrayList<>();
private static String taxo1Path(Record... records) {
String collection = ""; // = "/zeCollection"
StringBuilder sb = new StringBuilder(collection + "/taxo1");
for (Record record : records) {
sb.append("/");
sb.append(record.getId());
}
return sb.toString();
}
private static String taxo2Path(Record... records) {
String collection = ""; // = "/zeCollection"
StringBuilder sb = new StringBuilder(collection + "/taxo2");
for (Record record : records) {
sb.append("/");
sb.append(record.getId());
}
return sb.toString();
}
@Before
public void setUp()
throws Exception {
authorizations.add(aString());
authorizations.add(aString());
expectedPaths = new ArrayList<>();
values = new HashMap<>();
schemaManager = getModelLayerFactory().getMetadataSchemasManager();
recordServices = getModelLayerFactory().newRecordServices();
configManager = getDataLayerFactory().getConfigManager();
defineSchemasManager().using(schemas);
MetadataSchemaTypesBuilder types = schemaManager.modify(zeCollection);
types.getSchema(taxonomy1FirstSchema.code()).create("taxo1FirstSchemaMetaWithTaxoDependency")
.setType(MetadataValueType.STRING).defineDataEntry().asCalculated(DummyCalculatorWithTaxonomyDependency.class);
types.getSchema(taxonomy1SecondSchema.code()).create("taxo1SecondSchemaMetaWithTaxoDependency")
.setType(MetadataValueType.STRING).defineDataEntry().asCalculated(DummyCalculatorWithTaxonomyDependency.class);
types.getSchema(folderSchema.code()).create("folderMetaWithTaxoDependency")
.setType(MetadataValueType.STRING).defineDataEntry().asCalculated(DummyCalculatorWithTaxonomyDependency.class);
types.getSchema(documentSchema.code()).create("documentMetaWithTaxoDependency")
.setType(MetadataValueType.STRING).defineDataEntry().asCalculated(DummyCalculatorWithTaxonomyDependency.class);
schemas.onSchemaBuilt(schemaManager.saveUpdateSchemaTypes(types));
for (Taxonomy taxonomy : schemas.getTaxonomies()) {
getModelLayerFactory().getTaxonomiesManager().addTaxonomy(taxonomy, schemaManager);
}
records = schemas.givenTaxonomyRecords(recordServices);
rootFolderWithTaxonomy = new TestRecord(folderSchema, "rootFolderWithTaxonomy");
rootFolderWithTaxonomy.set(folderSchema.taxonomy1(), records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1);
rootFolderWithTaxonomy.set(folderSchema.conceptReferenceWithoutTaxonomyRelationship(),
records.taxo1_firstTypeItem2_secondTypeItem1);
subFolderWithTaxonomy = new TestRecord(folderSchema, "subFolderWithTaxonomy");
subFolderWithTaxonomy.set(folderSchema.parent(), rootFolderWithTaxonomy);
subFolderWithTaxonomy.set(folderSchema.taxonomy1(), records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2);
subFolderWithTaxonomy.set(folderSchema.conceptReferenceWithoutTaxonomyRelationship(),
records.taxo1_firstTypeItem2_secondTypeItem2);
document = new TestRecord(documentSchema, "document");
document.set(documentSchema.parent(), subFolderWithTaxonomy);
services = new RecordAutomaticMetadataServices(schemaManager, getModelLayerFactory().getTaxonomiesManager(),
getModelLayerFactory().getSystemConfigurationsManager(), getModelLayerFactory().getModelLayerLogger(),
getModelLayerFactory().newSearchServices());
records.mockRecordProviderToReturnRecordsById(recordProvider);
records.mockRecordProviderToReturnRecordById(recordProvider, rootFolderWithTaxonomy);
records.mockRecordProviderToReturnRecordById(recordProvider, subFolderWithTaxonomy);
records.mockRecordProviderToReturnRecordById(recordProvider, document);
recordServices.execute(new Transaction(rootFolderWithTaxonomy, subFolderWithTaxonomy, document));
}
@Test
public void whenCalculatingValueForTaxonomyDependencyThenValueCalculated()
throws Exception {
Metadata calculatedMetadata = schemas
.getMetadata(taxonomy1FirstSchema.code() + "_taxo1FirstSchemaMetaWithTaxoDependency");
when(recordProvider.getRecord(records.taxo1_firstTypeItem1.getId())).thenReturn(records.taxo1_firstTypeItem1);
services.calculateValueInRecord((RecordImpl) rootFolderWithTaxonomy, calculatedMetadata,
recordProvider, schemas.getTypes(), options);
assertThat(records.taxo1_firstTypeItem1.get(calculatedMetadata)).isEqualTo("calculatedValue");
}
@Test
public void givenRootFolderWithAReferenceToAConceptWithoutTaxonomyRelationshipWhenPreparingParentPathsThenEmpty() {
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1
.updateAutomaticValue(taxonomy1SecondSchema.allAuthorizations(), authorizations);
services.addValueForTaxonomyDependency((RecordImpl) rootFolderWithTaxonomy, recordProvider, values,
SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1));
String expectedTaxonomyCode = null;
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths, new ArrayList<String>(),
expectedTaxonomyCode);
}
@Test
public void givenRootFolderUsingTaxonomiesWhenPreparingParentPathsThenReturnPathsOfTaxonomyElements() {
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1
.updateAutomaticValue(taxonomy1SecondSchema.allAuthorizations(), authorizations);
services.addValueForTaxonomyDependency((RecordImpl) rootFolderWithTaxonomy, recordProvider, values,
SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1));
String expectedTaxonomyCode = null;
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths, new ArrayList<String>(),
expectedTaxonomyCode);
}
@Test
public void givenChildFolderUsingTaxonomiesWhenPreparingParentPathsThenReturnPathsOfParentUsingIsChildOfRelationshipAndPathsOfTaxonomyElements() {
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2
.updateAutomaticValue(taxonomy1SecondSchema.allAuthorizations(), Arrays.asList("a", "b"));
rootFolderWithTaxonomy
.updateAutomaticValue(folderSchema.allAuthorizations(), Arrays.asList("c"));
services.addValueForTaxonomyDependency((RecordImpl) subFolderWithTaxonomy, recordProvider, values,
SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1, rootFolderWithTaxonomy));
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2));
String expectedTaxonomyCode = null;
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths, Arrays.asList("rootFolderWithTaxonomy"),
expectedTaxonomyCode);
}
@Test
public void givenDocumentNotUsingTaxonomiesWhenPreparingParentPathsThenReturnPathsOfParentUsingIsChildOfRelationship() {
subFolderWithTaxonomy
.updateAutomaticValue(folderSchema.allAuthorizations(), authorizations);
services.addValueForTaxonomyDependency((RecordImpl) document, recordProvider, values,
SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1, rootFolderWithTaxonomy, subFolderWithTaxonomy));
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2,
records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2, subFolderWithTaxonomy));
String expectedTaxonomyCode = null;
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths,
asList("subFolderWithTaxonomy", "rootFolderWithTaxonomy"), expectedTaxonomyCode);
}
@Test
public void givenFirstTypeTaxonomyElementWhenPreparingParentPathThenReturnPathsOfParentWithChildOfRelation() {
records.taxo1_firstTypeItem2.updateAutomaticValue(taxonomy1FirstSchema.allAuthorizations(), authorizations);
services.addValueForTaxonomyDependency((RecordImpl) records.taxo1_firstTypeItem2_firstTypeItem2, recordProvider, values,
SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2));
String expectedTaxonomyCode = "taxo1";
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths,
asList("zeCollection_taxo1_firstTypeItem2"), expectedTaxonomyCode);
}
@Test
public void givenSecondTypeTaxonomyElementWhenPreparingParentPathThenReturnPathsOfParentWithChildOfRelation() {
records.taxo1_firstTypeItem2_firstTypeItem2
.updateAutomaticValue(taxonomy1FirstSchema.allAuthorizations(), authorizations);
services.addValueForTaxonomyDependency((RecordImpl) records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem1,
recordProvider, values, SpecialDependencies.HIERARCHY);
expectedPaths.add(taxo1Path(records.taxo1_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem2));
String expectedTaxonomyCode = "taxo1";
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths,
asList("zeCollection_taxo1_firstTypeItem2_firstTypeItem2", "zeCollection_taxo1_firstTypeItem2"),
expectedTaxonomyCode);
}
@Test
public void givenRootFirstTypeTaxonomyElementWhenPreparingParentPathThenReturnTaxonomyPathAndAuthorizations() {
services.addValueForTaxonomyDependency((RecordImpl) records.taxo1_firstTypeItem2,
recordProvider, values, SpecialDependencies.HIERARCHY);
String expectedTaxonomyCode = "taxo1";
assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(expectedPaths, new ArrayList<String>(),
expectedTaxonomyCode);
}
private void assertThatValuesOnlyContainsSpecialObjectWithPathsAndTaxonomies(List<String> expectedPaths,
List<String> expectedAttachedAncestors, String expectedTaxonomyCode) {
assertThat(values).containsKey(SpecialDependencies.HIERARCHY).hasSize(1);
HierarchyDependencyValue hierarchyDependencyValue = (HierarchyDependencyValue) values.get(SpecialDependencies.HIERARCHY);
if (expectedTaxonomyCode == null) {
assertThat(hierarchyDependencyValue.getTaxonomy()).isNull();
} else {
assertThat(hierarchyDependencyValue.getTaxonomy()).isNotNull();
assertThat(hierarchyDependencyValue.getTaxonomy().getCode()).isEqualTo(expectedTaxonomyCode);
}
assertThat(hierarchyDependencyValue.getPaths()).containsAll(expectedPaths).hasSize(expectedPaths.size());
assertThat(hierarchyDependencyValue.getAttachedAncestors())
.containsOnly(expectedAttachedAncestors.toArray(new String[0]));
}
private void assertThatPathIsEqualTo(Record record, String path) {
Metadata pathMetadata = schemas.getMetadata(record.getSchemaCode() + "_path");
assertThat(record.get(pathMetadata)).isEqualTo(Arrays.asList(path));
}
private void assertThatPathIsEqualTo(Record record, List<String> paths) {
Metadata pathMetadata = schemas.getMetadata(record.getSchemaCode() + "_path");
assertThat(record.get(pathMetadata)).isEqualTo(paths);
}
public static class DummyCalculatorWithTaxonomyDependency implements MetadataValueCalculator<String> {
SpecialDependency<HierarchyDependencyValue> taxonomies = SpecialDependencies.HIERARCHY;
@Override
public String calculate(CalculatorParameters parameters) {
return "calculatedValue";
}
@Override
public String getDefaultValue() {
return null;
}
@Override
public MetadataValueType getReturnType() {
return MetadataValueType.STRING;
}
@Override
public boolean isMultiValue() {
return false;
}
@Override
public List<? extends Dependency> getDependencies() {
return Arrays.asList(taxonomies);
}
}
}