package com.constellio.app.modules.rm.services.events; import com.constellio.app.modules.rm.services.RMSchemasRecordsServices; import com.constellio.app.modules.rm.services.borrowingServices.BorrowingType; import com.constellio.app.modules.rm.wrappers.Folder; import com.constellio.data.utils.TimeProvider; import com.constellio.model.entities.CorePermissions; import com.constellio.model.entities.records.Record; import com.constellio.model.entities.records.wrappers.Event; import com.constellio.model.entities.records.wrappers.EventType; import com.constellio.model.entities.records.wrappers.User; import com.constellio.model.entities.schemas.Metadata; import com.constellio.model.entities.schemas.Schemas; import com.constellio.model.entities.security.Authorization; import com.constellio.model.services.factories.ModelLayerFactory; import com.constellio.model.services.search.SearchServices; import com.constellio.model.services.search.query.logical.LogicalSearchQuery; import com.constellio.model.services.search.query.logical.LogicalSearchValueCondition; import com.constellio.model.services.search.query.logical.condition.LogicalSearchCondition; import com.constellio.model.services.security.AuthorizationsServices; import org.apache.commons.lang.StringUtils; import org.joda.time.LocalDateTime; import java.util.ArrayList; import java.util.List; import static com.constellio.model.entities.records.wrappers.Event.EVENT_PRINCIPAL_PATH; import static com.constellio.model.services.contents.ContentFactory.checkedOut; import static com.constellio.model.services.search.query.logical.LogicalSearchQueryOperators.*; public class RMEventsSearchServices { private ModelLayerFactory modelLayerFactory; private RMSchemasRecordsServices schemas; public RMEventsSearchServices(ModelLayerFactory modelLayerFactory, String collection) { this.modelLayerFactory = modelLayerFactory; this.schemas = new RMSchemasRecordsServices(collection, modelLayerFactory); } public List<Event> findLoggedUsers(User currentUser) { return findNotCanceledEventsPerUser(currentUser, EventType.OPEN_SESSION, EventType.CLOSE_SESSION); } public LogicalSearchQuery newFindOpenedSessionsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.OPEN_SESSION, startDate, endDate); } //by range date public LogicalSearchQuery newFindCreatedDocumentsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.CREATE_DOCUMENT, startDate, endDate); } public LogicalSearchQuery newFindDeletedDocumentsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.DELETE_DOCUMENT, startDate, endDate); } public LogicalSearchQuery newFindModifiedDocumentsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.MODIFY_DOCUMENT, startDate, endDate); } public LogicalSearchQuery newFindBorrowedDocumentsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.BORROW_DOCUMENT, startDate, endDate); } public LogicalSearchQuery newFindReturnedDocumentsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.RETURN_DOCUMENT, startDate, endDate); } public List<Event> findCurrentlyBorrowedDocuments(User currentUser) { return findNotCanceledEventsPerUser(currentUser, EventType.BORROW_DOCUMENT, EventType.RETURN_DOCUMENT); } public LogicalSearchQuery newFindCurrentlyBorrowedDocumentsQuery(User currentUser) { return new LogicalSearchQuery(from(schemas.documentSchemaType()).where(schemas.documentContent()).is(checkedOut())) .filteredWithUser(currentUser).sortAsc(Schemas.TITLE); } public LogicalSearchQuery newFindCurrentlyBorrowedFoldersQuery(User currentUser) { return new LogicalSearchQuery(from(schemas.folder.schemaType()) .where(schemas.folder.borrowed()).isTrue() .andWhere(schemas.folder.borrowingType()).is(BorrowingType.BORROW)) .filteredWithUser(currentUser).sortAsc(Schemas.TITLE); } public LogicalSearchQuery newFindCurrentlyBorrowedFoldersByUser(User currentUser, String userId) { LogicalSearchCondition condition = from(schemas.folder.schemaType()) .where(schemas.folder.borrowed()).isTrue() .andWhere(schemas.folder.borrowingType()).is(BorrowingType.BORROW) .andWhere(schemas.folder.borrowUserEntered()).is(userId); return new LogicalSearchQuery(condition).filteredWithUser(currentUser).sortAsc(Schemas.TITLE); } public LogicalSearchQuery newFindLateBorrowedFoldersByUserAndDateRangeQuery(User currentUser, String userId) { LogicalSearchCondition condition = from(schemas.folder.schemaType()) .where(schemas.folder.borrowed()).isTrue().andWhere(schemas.folder.borrowUserEntered()) .is(userId).andWhere(schemas.folder.borrowPreviewReturnDate()) .isLessThan(TimeProvider.getLocalDate()); return new LogicalSearchQuery(condition).filteredWithUser(currentUser).sortAsc(Schemas.TITLE); } public LogicalSearchQuery newFindCreatedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.CREATE_FOLDER, startDate, endDate); } public LogicalSearchQuery newFindModifiedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.MODIFY_FOLDER, startDate, endDate); } public LogicalSearchQuery newFindDeletedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.DELETE_FOLDER, startDate, endDate); } public LogicalSearchQuery newFindBorrowedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.BORROW_FOLDER, startDate, endDate); } public LogicalSearchQuery newFindReturnedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.RETURN_FOLDER, startDate, endDate); } public List<Event> findCurrentlyBorrowedFolders(User currentUser) { return findNotCanceledEventsPerUser(currentUser, EventType.BORROW_FOLDER, EventType.RETURN_FOLDER); } public LogicalSearchQuery newFindBorrowedContainersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.BORROW_CONTAINER, startDate, endDate); } public LogicalSearchQuery newFindReturnedContainersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.RETURN_CONTAINER, startDate, endDate); } public LogicalSearchQuery newFindRelocatedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.FOLDER_RELOCATION, startDate, endDate); } public LogicalSearchQuery newFindFolderDepositByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.FOLDER_DEPOSIT, startDate, endDate); } public LogicalSearchQuery newFindDestructedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.FOLDER_DESTRUCTION, startDate, endDate); } public LogicalSearchQuery newFindPdfAGenerationEventsByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.PDF_A_GENERATION, startDate, endDate); } public LogicalSearchQuery newFindReceivedFoldersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.RECEIVE_FOLDER, startDate, endDate); } public LogicalSearchQuery newFindReceivedContainersByDateRangeQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate) { return newFindEventByDateRangeQuery(currentUser, EventType.RECEIVE_CONTAINER, startDate, endDate); } //By Filing space and date range public LogicalSearchQuery newFindCreatedFoldersByDateRangeAndByFilingSpaceQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate, String principalPath) { return newFindEventByDateRangeAndByAdministrativeUnitQuery(currentUser, EventType.CREATE_FOLDER, startDate, endDate, principalPath); } public LogicalSearchQuery newFindGrantedPermissionsByDateRangeAndByFolderQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate, Folder folder) { return newFindEventByDateRangeAndByFolderQuery(currentUser, EventType.GRANT_PERMISSION, startDate, endDate, folder); } public LogicalSearchQuery newFindCreatedDocumentsByDateRangeAndByUserQuery(User currentUser, LocalDateTime startDate, LocalDateTime endDate, String username) { return newFindEventByDateRangeAndByUserQuery(currentUser, EventType.CREATE_DOCUMENT, startDate, endDate, username); } private LogicalSearchQuery newFindEventQuery(User currentUser, String eventType) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata timestamp = Schemas.CREATED_ON; return new LogicalSearchQuery(fromEventsAccessibleBy(currentUser).andWhere(type).isEqualTo(eventType)) .sortDesc(timestamp); } public LogicalSearchQuery newFindEventByDateRangeQuery(User currentUser, String eventType, LocalDateTime startDate, LocalDateTime endDate) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata timestamp = Schemas.CREATED_ON; LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(type).isEqualTo(eventType).andWhere(timestamp).isValueInRange(startDate, endDate); return new LogicalSearchQuery(condition).sortDesc(timestamp); } public LogicalSearchQuery newFindEventByDateRangeAndByFolderQuery(User currentUser, String eventType, LocalDateTime startDate, LocalDateTime endDate, Folder folder) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata recordId = schemas.eventSchema().getMetadata(Event.RECORD_ID); Metadata timestamp = Schemas.CREATED_ON; LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(type).isEqualTo(eventType) .andWhere(timestamp).isValueInRange(startDate, endDate) .andWhere(recordId).isEqualTo(folder); return new LogicalSearchQuery(condition).sortDesc(timestamp); } public LogicalSearchQuery newFindEventByDateRangeAndByUserIdQuery(User currentUser, String eventType, LocalDateTime startDate, LocalDateTime endDate, String userId) { User user = schemas.getUser(userId); String username = user.getUsername(); return newFindEventByDateRangeAndByUserQuery(currentUser, eventType, startDate, endDate, username); } public LogicalSearchQuery newFindEventByDateRangeAndByUserQuery(User currentUser, String eventType, LocalDateTime startDate, LocalDateTime endDate, String userName) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata timestamp = Schemas.CREATED_ON; Metadata user = schemas.eventSchema().getMetadata(Event.USERNAME); LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(type).isEqualTo(eventType) .andWhere(timestamp).isValueInRange(startDate, endDate) .andWhere(user).isEqualTo(userName); return new LogicalSearchQuery(condition).sortDesc(timestamp); } public LogicalSearchQuery newFindEventByDateRangeAndByAdministrativeUnitQuery(User currentUser, String eventType, LocalDateTime startDate, LocalDateTime endDate, String id) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata timestamp = Schemas.CREATED_ON; Metadata principalPath = schemas.eventSchema().getMetadata(EVENT_PRINCIPAL_PATH); String filteringSpacePathWithoutFirstAndLastSeparator = StringUtils.removeEnd(id, "/"); if (filteringSpacePathWithoutFirstAndLastSeparator.startsWith("/")) { filteringSpacePathWithoutFirstAndLastSeparator = StringUtils .removeStart("/", filteringSpacePathWithoutFirstAndLastSeparator); } LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(principalPath).isAny( endingWithText("/" + filteringSpacePathWithoutFirstAndLastSeparator), containingText("/" + filteringSpacePathWithoutFirstAndLastSeparator + "/")) .andWhere(type).isEqualTo(eventType) .andWhere(timestamp).isValueInRange(startDate, endDate); return new LogicalSearchQuery(condition).sortDesc(timestamp); } private List<Event> findNotCanceledEventsPerUser(User currentUser, String eventType, String eventTypeCancellation) { List<Event> returnList = new ArrayList<>(); LogicalSearchQuery searchedEventsQuery = newFindEventQuery(currentUser, eventType); SearchServices searchServices = modelLayerFactory.newSearchServices(); List<Event> searchedEvents = schemas.wrapEvents(searchServices.search(searchedEventsQuery)); List<Event> mostRecentEventsPerUser = EventUtils.keepOnlyMostRecentEventPerUser(searchedEvents); for (Event event : mostRecentEventsPerUser) { String username = event.getUsername(); LocalDateTime eventDate = event.getCreatedOn(); LogicalSearchQuery eventCancellationAfterEventDateQuery = newFindEventForUserAfterDateQuery( currentUser, eventTypeCancellation, username, eventDate); long canceledEventsCount = searchServices.getResultsCount(eventCancellationAfterEventDateQuery); if (canceledEventsCount == 0) { returnList.add(event); } } return returnList; } private LogicalSearchQuery newFindEventForUserAfterDateQuery(User currentUser, String eventType, String username, LocalDateTime date) { Metadata type = schemas.eventSchema().getMetadata(Event.TYPE); Metadata timestamp = Schemas.CREATED_ON; Metadata user = schemas.eventSchema().getMetadata(Event.USERNAME); LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(type).isEqualTo(eventType) .andWhere(user).isEqualTo(username) .andWhere(timestamp).isGreaterOrEqualThan(date); return new LogicalSearchQuery(condition).sortDesc(timestamp); } private LogicalSearchCondition fromEventsAccessibleBy(User user) { Metadata eventPrincipalPath = schemas.eventSchema().getMetadata(EVENT_PRINCIPAL_PATH); AuthorizationsServices authenticationService = schemas.getModelLayerFactory().newAuthorizationsServices(); if (user.has(CorePermissions.VIEW_EVENTS).globally()) { return from(schemas.eventSchemaType()).returnAll(); } else { SearchServices searchServices = schemas.getModelLayerFactory().newSearchServices(); List<String> ids; ids = authenticationService.getConceptsForWhichUserHasPermission(CorePermissions.VIEW_EVENTS ,user); List<LogicalSearchValueCondition> ofTheseAdministrativeUnits = new ArrayList<>(); ofTheseAdministrativeUnits.add(isNull()); for (Record concept : searchServices.search( new LogicalSearchQuery(from(schemas.administrativeUnit.schemaType()).where(Schemas.IDENTIFIER).isIn(ids)))) { List<String> paths = concept.get(Schemas.PATH); if (!paths.isEmpty()) { ofTheseAdministrativeUnits.add(startingWithText(paths.get(0))); } } return from(schemas.eventSchemaType()).where(eventPrincipalPath).isAny(ofTheseAdministrativeUnits); } } public LogicalSearchQuery newFindEventByRecordIDQuery(User currentUser, String recordID) { Metadata metadataRecordID = schemas.eventSchema().getMetadata(Event.RECORD_ID); Metadata timestamp = Schemas.CREATED_ON; LogicalSearchCondition condition = fromEventsAccessibleBy(currentUser) .andWhere(metadataRecordID).isEqualTo(recordID); return new LogicalSearchQuery(condition).sortDesc(timestamp); } }