package com.constellio.model.services.taxonomies; import static com.constellio.model.entities.security.global.AuthorizationAddRequest.authorizationInCollection; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; 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.records.wrappers.User; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.entities.security.Authorization; import com.constellio.model.entities.security.Role; import com.constellio.model.services.batch.controller.BatchProcessController; import com.constellio.model.services.batch.manager.BatchProcessesManager; import com.constellio.model.services.records.RecordServices; import com.constellio.model.services.records.RecordServicesException; import com.constellio.model.services.schemas.MetadataSchemasManager; import com.constellio.model.services.schemas.builders.MetadataSchemaTypesBuilder; import com.constellio.model.services.search.StatusFilter; import com.constellio.model.services.search.query.ReturnedMetadatasFilter; import com.constellio.model.services.security.AuthorizationsServices; import com.constellio.model.services.security.roles.RolesManager; import com.constellio.model.services.security.roles.RolesManagerRuntimeException; import com.constellio.model.services.users.UserServices; 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; import com.constellio.sdk.tests.setups.TwoTaxonomiesContainingFolderAndDocumentsSetup.UserSchema; public class ConceptNodesTaxonomiesSearchServicesAcceptanceTest extends ConstellioTest { String TAXO1 = "taxo1"; String TAXO2 = "taxo2"; TwoTaxonomiesContainingFolderAndDocumentsSetup schemas = new TwoTaxonomiesContainingFolderAndDocumentsSetup(zeCollection); Taxonomy1FirstSchemaType taxonomy1FirstSchema = schemas.new Taxonomy1FirstSchemaType(); Taxonomy1SecondSchemaType taxonomy1SecondSchema = schemas.new Taxonomy1SecondSchemaType(); Taxonomy2DefaultSchema taxonomy2DefaultSchema = schemas.new Taxonomy2DefaultSchema(); Taxonomy2CustomSchema taxonomy2CustomSchema = schemas.new Taxonomy2CustomSchema(); FolderSchema folderSchema = schemas.new FolderSchema(); DocumentSchema documentSchema = schemas.new DocumentSchema(); UserServices userServices; AuthorizationsServices authorizationsServices; BatchProcessesManager batchProcessesManager; BatchProcessController batchProcessController; RolesManager roleManager; TaxonomiesManager taxonomiesManager; TaxonomyRecords records; MetadataSchemasManager schemasManager; RecordServices recordServices; ConceptNodesTaxonomySearchServices services; TaxonomiesSearchOptions options; Record folder; Record subFolder; Record document; UserSchema userSchema; String ZE_ROLE = "zeRoleCode"; User bob; User chuck; @Before public void setUp() throws Exception { userServices = getModelLayerFactory().newUserServices(); schemasManager = getModelLayerFactory().getMetadataSchemasManager(); recordServices = getModelLayerFactory().newRecordServices(); authorizationsServices = getModelLayerFactory().newAuthorizationsServices(); roleManager = getModelLayerFactory().getRolesManager(); taxonomiesManager = getModelLayerFactory().getTaxonomiesManager(); options = new TaxonomiesSearchOptions(); options.setReturnedMetadatasFilter(ReturnedMetadatasFilter.all()); batchProcessesManager = getModelLayerFactory().getBatchProcessesManager(); batchProcessesManager.initialize(); defineSchemasManager().using(schemas); userSchema = schemas.getUserSchema(); Transaction transaction = new Transaction(); bob = wrapUser(addUserRecord(transaction, "bob", null)); recordServices.execute(transaction); transaction = new Transaction(); chuck = wrapUser(addUserRecord(transaction, "chuck", null)); recordServices.execute(transaction); for (Taxonomy taxonomy : schemas.getTaxonomies()) { getModelLayerFactory().getTaxonomiesManager().addTaxonomy(taxonomy, schemasManager); } taxonomiesManager.setPrincipalTaxonomy(schemas.getTaxo1(), schemasManager); records = schemas.givenTaxonomyRecords(recordServices); MetadataSchemaTypesBuilder types = schemasManager.modify("zeCollection"); services = new ConceptNodesTaxonomySearchServices(getModelLayerFactory()); } private void givenFoldersAndDocuments() throws RecordServicesException { folder = new TestRecord(folderSchema, "folder"); folder.set(folderSchema.taxonomy1(), records.taxo1_firstTypeItem2_secondTypeItem2); folder.set(folderSchema.taxonomy2(), asList(records.taxo2_defaultSchemaItem2_customSchemaItem1, records.taxo2_defaultSchemaItem2_defaultSchemaItem2_customSchemaItem2)); subFolder = new TestRecord(folderSchema, "subFolder"); subFolder.set(folderSchema.parent(), folder); subFolder.set(folderSchema.taxonomy2(), asList(records.taxo2_defaultSchemaItem2_customSchemaItem2)); document = new TestRecord(documentSchema, "document"); document.set(documentSchema.parent(), folder); recordServices.execute(new Transaction(folder, subFolder, document)); } @Test public void whenGetRootRecordsThenReturnOnlyRecordsOfGivenTaxonomy() throws Exception { givenFoldersAndDocuments(); getDataLayerFactory().getDataLayerLogger().setPrintAllQueriesLongerThanMS(0); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); List<Record> taxonomy2RootRecords = services.getRootConcept(records.taxo2_defaultSchemaItem1.getCollection(), "taxo2", options); assertThat(taxonomy1RootRecords).extracting("id") .containsOnly(records.taxo1_firstTypeItem1.getId(), records.taxo1_firstTypeItem2.getId()); assertThat(taxonomy2RootRecords).extracting("id") .containsOnly(records.taxo2_defaultSchemaItem1.getId(), records.taxo2_defaultSchemaItem2.getId()); } @Test public void whenGetChildrenOfTaxonomyRecordsThenReturnOnlyChildrenRecords() throws Exception { givenFoldersAndDocuments(); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); List<Record> taxonomy1FirstTypeItem2SecondItem2RecordChildren = services.getChildConcept( records.taxo1_firstTypeItem2_secondTypeItem2, options); List<Record> taxonomy2RecordChildren = services.getChildConcept(records.taxo2_defaultSchemaItem2_defaultSchemaItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).extracting("id").containsOnly( records.taxo1_firstTypeItem2_firstTypeItem1.getId(), records.taxo1_firstTypeItem2_firstTypeItem2.getId(), records.taxo1_firstTypeItem2_secondTypeItem1.getId(), records.taxo1_firstTypeItem2_secondTypeItem2.getId()); assertThat(taxonomy1FirstTypeItem2SecondItem2RecordChildren).extracting("id").containsOnly( records.taxo1_firstTypeItem2_secondTypeItem2_secondTypeItem1.getId(), records.taxo1_firstTypeItem2_secondTypeItem2_secondTypeItem2.getId(), folder.getId()); assertThat(taxonomy2RecordChildren).extracting("id").containsOnly( records.taxo2_defaultSchemaItem2_defaultSchemaItem2_customSchemaItem1.getId(), records.taxo2_defaultSchemaItem2_defaultSchemaItem2_customSchemaItem2.getId()); } @Test public void whenGetParentOfTaxonomyRecordThenObtainValidParentId() throws Exception { assertThat(records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2.getParentId()) .isEqualTo(records.taxo1_firstTypeItem2_firstTypeItem2.getId()); assertThat(records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2_secondTypeItem1.getParentId()) .isEqualTo(records.taxo1_firstTypeItem2_firstTypeItem2_secondTypeItem2.getId()); assertThat(records.taxo2_defaultSchemaItem2_defaultSchemaItem2.getParentId()) .isEqualTo(records.taxo2_defaultSchemaItem2.getId()); assertThat(records.taxo2_defaultSchemaItem2_defaultSchemaItem2_customSchemaItem1.getParentId()) .isEqualTo(records.taxo2_defaultSchemaItem2_defaultSchemaItem2.getId()); } @Test public void whenGetChildrenOfNonTaxonomyRecordsThenReturnChildrenUsingChildOfMetadata() throws Exception { givenFoldersAndDocuments(); List<Record> folderRecordChildren = services.getChildConcept(folder, options); List<Record> subFolderRecordChildren = services.getChildConcept(subFolder, options); List<Record> documentRecordChildren = services.getChildConcept(document, options); assertThat(folderRecordChildren).extracting("id").containsOnly(subFolder.getId(), document.getId()); assertThat(subFolderRecordChildren).isEmpty(); assertThat(documentRecordChildren).isEmpty(); } // @Test public void givenDeletedRecordWhenGetRootRecordsWithDefaultSearchOptionsThenReturnOnlyNotDeletedRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).extracting("id").containsOnly(records.taxo1_firstTypeItem2.getId()); } @Test public void givenDeletedRecordWhenGetRootRecordsWithActivesSearchOptionsThenReturnOnlyNotDeletedRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(StatusFilter.ACTIVES); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem2); } @Test public void givenDeletedRecordWhenGetRootRecordsWithDeletedSearchOptionsThenReturnOnlyDeletedRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(StatusFilter.DELETED); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem1); } @Test public void givenDeletedRecordWhenGetRootRecordsWithAllSearchOptionsThenReturnTwoRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(StatusFilter.ALL); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem1, records.taxo1_firstTypeItem2); } @Test public void givenDeletedRecordWhenGetRootRecordsWithStartRowAndAllSearchOptionsThenReturnOnlyOneRecord() throws Exception { givenFoldersAndDocuments(); options = new TaxonomiesSearchOptions(10, 1, StatusFilter.ALL); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem2); } @Test public void givenDeletedRecordWhenGetRootRecordsWithNumberOfRowsAndAllSearchOptionsThenReturnOnlyOneRecord() throws Exception { givenFoldersAndDocuments(); options = new TaxonomiesSearchOptions(1, 0, StatusFilter.ALL); List<Record> taxonomy1RootRecords = services.getRootConcept(records.taxo1_firstTypeItem1.getCollection(), "taxo1", options); assertThat(taxonomy1RootRecords).usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem1); } @Test public void givenDeletedRecordsWhenGetChildrenOfTaxonomyRecordsWithDefaultSearchOptionsThenReturnOnlyNotDeletedChildrenRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem2_secondTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).usingElementComparatorOnFields("id") .containsOnly(records.taxo1_firstTypeItem2_firstTypeItem1, records.taxo1_firstTypeItem2_firstTypeItem2, records.taxo1_firstTypeItem2_secondTypeItem2); } @Test public void givenDeletedRecordsWhenGetChildrenOfTaxonomyRecordsWithAllSearchOptionsThenReturnAllChildrenRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem2_secondTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(StatusFilter.ALL); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).usingElementComparatorOnFields("id") .containsOnly(records.taxo1_firstTypeItem2_firstTypeItem1, recordToDelete, records.taxo1_firstTypeItem2_firstTypeItem2, records.taxo1_firstTypeItem2_secondTypeItem2); } @Test public void givenDeletedRecordsWhenGetChildrenOfTaxonomyRecordsWithDeletedSearchOptionsThenReturnOnlyDeletedChildrenRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem2_secondTypeItem1; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(StatusFilter.DELETED); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).usingElementComparatorOnFields("id") .usingElementComparatorOnFields("id").containsOnly(recordToDelete); } @Test public void givenDeletedRecordsWhenGetChildrenOfTaxonomyRecordsWithStartRowAndAllSearchOptionsThenReturnThreeChildrenRecords() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem2_secondTypeItem2; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(10, 0, StatusFilter.ALL); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).hasSize(4); assertThat(taxonomy1FirstTypeItem2RecordChildren) .usingElementComparatorOnFields("id").containsOnly(records.taxo1_firstTypeItem2_firstTypeItem2, records.taxo1_firstTypeItem2_firstTypeItem1, records.taxo1_firstTypeItem2_secondTypeItem1, recordToDelete); } @Test public void givenDeletedRecordsWhenGetChildrenOfTaxonomyRecordsWithNumberOfRowsAndAllSearchOptionsThenReturnTwo() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = records.taxo1_firstTypeItem2_secondTypeItem2; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options = new TaxonomiesSearchOptions(2, 0, StatusFilter.ALL); List<Record> taxonomy1FirstTypeItem2RecordChildren = services.getChildConcept(records.taxo1_firstTypeItem2, options); assertThat(taxonomy1FirstTypeItem2RecordChildren).hasSize(2); } @Test public void givenDeletedSubFolderWhenGetChildrenOfNonTaxonomyRecordsWithDefaultSearchOptionsThenReturnOnlyDocument() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = subFolder; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); List<Record> folderRecordChildren = services.getChildConcept(folder, options); assertThat(folderRecordChildren).extracting("id").containsOnly(document.getId()); } @Test public void givenDeletedSubFolderWhenGetChildrenOfNonTaxonomyRecordsWithAllSearchOptionsThenReturnSubFolderAndDocument() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = subFolder; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options.setIncludeStatus(StatusFilter.ALL); List<Record> folderRecordChildren = services.getChildConcept(folder, options); assertThat(folderRecordChildren).extracting("id").containsOnly(subFolder.getId(), document.getId()); } @Test public void givenDeletedSubFolderWhenGetChildrenOfNonTaxonomyRecordsWithDeletedSearchOptionsThenReturnOnlySubFolder() throws Exception { givenFoldersAndDocuments(); Record recordToDelete = subFolder; givenAuthorizationsToChuck(recordToDelete); recordServices.logicallyDelete(recordToDelete, chuck); assertThat(recordToDelete.get(Schemas.LOGICALLY_DELETED_STATUS)).isEqualTo(true); options.setIncludeStatus(StatusFilter.DELETED); List<Record> folderRecordChildren = services.getChildConcept(folder, options); assertThat(folderRecordChildren).extracting("id").containsOnly(subFolder.getId()); } // ------------------------------------------------ private void givenAuthorizationsToChuck(Record record) throws RolesManagerRuntimeException, InterruptedException { List<String> roles = asList(Role.WRITE, Role.DELETE); addAuthorizationWithoutDetaching(roles, asList(chuck.getId()), asList(record.getId())); waitForBatchProcess(); } private Record addUserRecord(Transaction transaction, String id, List<Record> groups) { Record record = new TestRecord(userSchema, id); record.set(userSchema.username(), id); record.set(userSchema.groups(), groups); transaction.addUpdate(record); return record; } private Authorization addAuthorizationWithoutDetaching(List<String> roles, List<String> grantedToPrincipals, List<String> grantedOnRecords) { String id = authorizationsServices.add(authorizationInCollection(zeCollection).giving(roles) .forPrincipalsIds(grantedToPrincipals).on(grantedOnRecords.get(0))); return authorizationsServices.getAuthorization(zeCollection, id); } private List<String> recordIdsWithAuthorizations(List<TaxonomySearchRecord> results) { List<String> ids = new ArrayList<>(); for (TaxonomySearchRecord record : results) { if (record.isLinkable()) { ids.add(record.getRecord().getId()); } } return ids; } private List<String> recordIdsWithoutAuthorizations(List<TaxonomySearchRecord> results) { List<String> ids = new ArrayList<>(); for (TaxonomySearchRecord record : results) { if (!record.isLinkable()) { ids.add(record.getRecord().getId()); } } return ids; } }