use of io.lumeer.core.task.executor.operation.DocumentRemovalOperation in project engine by Lumeer.
the class LumeerBridge method removeDocumentsInView.
@SuppressWarnings("unused")
public void removeDocumentsInView(final String viewId) {
try {
final View view = task.getDaoContextSnapshot().getViewDao().getViewById(viewId);
final Query query = view.getQuery().getFirstStem(0, Task.MAX_VIEW_DOCUMENTS);
final Language language = Language.fromString(task.getCurrentLocale());
final Set<RoleType> roles = PermissionUtils.getUserRolesInResource(task.getDaoContextSnapshot().getOrganization(), task.getDaoContextSnapshot().getProject(), view, task.getInitiator(), task.getGroups());
final AllowedPermissions permissions = new AllowedPermissions(roles);
final List<Document> documents = DocumentUtils.getDocuments(task.getDaoContextSnapshot(), query, task.getInitiator(), language, permissions, task.getTimeZone());
documents.stream().filter(d -> task.getDaoContextSnapshot().increaseDeletionCounter() <= Task.MAX_CREATED_AND_DELETED_DOCUMENTS_AND_LINKS).forEach(d -> operations.add(new DocumentRemovalOperation(d)));
} catch (Exception e) {
cause = e;
throw e;
}
}
use of io.lumeer.core.task.executor.operation.DocumentRemovalOperation in project engine by Lumeer.
the class SingleStage method commitOperations.
public ChangesTracker commitOperations() {
if (operations.isEmpty()) {
return new ChangesTracker();
}
@SuppressWarnings("rawtypes") final List<Operation> invalidOperations = operations.stream().filter(operation -> !operation.isComplete()).collect(toList());
if (invalidOperations.size() > 0) {
final StringBuilder sb = new StringBuilder();
invalidOperations.forEach(operation -> sb.append("Invalid update request: ").append(operation.toString()).append("\n"));
throw new IllegalArgumentException(sb.toString());
}
// first create all new documents
final List<Document> createdDocuments = createDocuments(operations.stream().filter(operation -> operation instanceof DocumentCreationOperation && operation.isComplete()).map(operation -> (DocumentCreationOperation) operation).collect(toList()));
final Map<String, List<Document>> toBeRemovedDocumentsByCollection = Utils.categorize(operations.stream().filter(operation -> operation instanceof DocumentRemovalOperation && operation.isComplete()).map(operation -> ((DocumentRemovalOperation) operation).getEntity()), Document::getCollectionId);
// get data structures for efficient manipulation with the new documents
final Map<String, List<Document>> documentsByCollection = DocumentUtils.getDocumentsByCollection(createdDocuments);
final List<String> usedCollections = new ArrayList<>(documentsByCollection.keySet());
usedCollections.addAll(toBeRemovedDocumentsByCollection.keySet());
final Map<String, Collection> collectionsMap = task.getDaoContextSnapshot().getCollectionDao().getCollectionsByIds(usedCollections).stream().collect(Collectors.toMap(Collection::getId, Function.identity()));
final Map<String, String> correlationIdsToIds = createdDocuments.stream().collect(Collectors.toMap(doc -> doc.createIfAbsentMetaData().getString(Document.META_CORRELATION_ID), Document::getId));
// report new empty documents, later updates are sent separately
changesTracker.addCreatedDocuments(createdDocuments);
changesTracker.addCollections(collectionsMap.values().stream().filter(c -> documentsByCollection.containsKey(c.getId())).collect(toSet()));
// map the newly create document IDs to all other changes so that we use the correct document in updates etc.
operations.stream().filter(operation -> operation instanceof DocumentOperation).forEach(operation -> {
final Document doc = (Document) operation.getEntity();
if (StringUtils.isEmpty(doc.getId()) && StringUtils.isNotEmpty(doc.createIfAbsentMetaData().getString(Document.META_CORRELATION_ID))) {
doc.setId(correlationIdsToIds.get(doc.getMetaData().getString(Document.META_CORRELATION_ID)));
}
});
operations.stream().filter(operation -> operation instanceof LinkCreationOperation).forEach(operation -> {
final LinkInstance link = ((LinkCreationOperation) operation).getEntity();
if (StringUtils.isEmpty(link.getId()) && StringUtils.isNotEmpty(link.getTemplateId())) {
link.setDocumentIds(List.of(correlationIdsToIds.containsKey(link.getDocumentIds().get(0)) ? correlationIdsToIds.get(link.getDocumentIds().get(0)) : link.getDocumentIds().get(0), correlationIdsToIds.containsKey(link.getDocumentIds().get(1)) ? correlationIdsToIds.get(link.getDocumentIds().get(1)) : link.getDocumentIds().get(1)));
}
});
// commit document changes
final List<Document> changedDocuments = commitDocumentOperations(operations.stream().filter(operation -> operation instanceof DocumentOperation && operation.isComplete()).map(operation -> (DocumentOperation) operation).collect(toList()), createdDocuments, collectionsMap);
// remove documents
final List<Document> removedDocuments = removeDocuments(operations.stream().filter(operation -> operation instanceof DocumentRemovalOperation).map(operation -> (DocumentRemovalOperation) operation).collect(toList()));
changesTracker.addRemovedDocuments(removedDocuments);
// remove created documents that were deleted later
final Set<Document> unusedCreatedDocuments = new HashSet<>(changesTracker.getRemovedDocuments());
unusedCreatedDocuments.retainAll(changesTracker.getCreatedDocuments());
changesTracker.getCreatedDocuments().removeAll(unusedCreatedDocuments);
// create new links
final List<LinkCreationOperation> linkCreationOperations = operations.stream().filter(operation -> operation instanceof LinkCreationOperation && operation.isComplete()).map(operation -> (LinkCreationOperation) operation).collect(toList());
final List<LinkInstance> createdLinks = createLinks(linkCreationOperations);
final Map<String, List<LinkInstance>> linksByType = LinkTypeUtils.getLinksByType(createdLinks);
final Map<String, LinkType> linkTypesMap = task.getDaoContextSnapshot().getLinkTypeDao().getLinkTypesByIds(linksByType.keySet()).stream().collect(Collectors.toMap(LinkType::getId, Function.identity()));
final Map<String, String> linkCorrelationIdsToIds = createdLinks.stream().collect(Collectors.toMap(LinkInstance::getTemplateId, LinkInstance::getId));
// report new empty links, later updates are sent separately
changesTracker.addCreatedLinkInstances(createdLinks);
changesTracker.addLinkTypes(linkTypesMap.values().stream().filter(c -> linksByType.containsKey(c.getId())).collect(toSet()));
// map the newly create link IDs to all other changes so that we use the correct document in updates etc.
operations.stream().filter(operation -> operation instanceof LinkOperation).forEach(operation -> {
final LinkInstance link = (LinkInstance) operation.getEntity();
if (StringUtils.isEmpty(link.getId()) && StringUtils.isNotEmpty(link.getTemplateId())) {
link.setId(linkCorrelationIdsToIds.get(link.getTemplateId()));
}
});
// commit link changes
final List<LinkInstance> changedLinkInstances = commitLinkOperations(taskExecutor, operations.stream().filter(operation -> operation instanceof LinkOperation && operation.isComplete()).map(operation -> (LinkOperation) operation).collect(toList()), createdLinks, linkTypesMap);
// report user messages, print, navigate, and send email requests for rules triggered via an Action button
final String correlationId = task.getAppId() != null ? task.getAppId().getValue() : null;
if (StringUtils.isNotEmpty(correlationId)) {
final List<UserMessageRequest> userMessageRequests = operations.stream().filter(operation -> operation instanceof UserMessageOperation).map(operation -> ((UserMessageOperation) operation).getEntity()).collect(toList());
changesTracker.addUserMessageRequests(userMessageRequests);
List<GenericPrintRequest> printRequests = operations.stream().filter(operation -> operation instanceof PrintAttributeOperation).map(operation -> ((PrintAttributeOperation) operation).getEntity()).collect(toList());
changesTracker.addPrintRequests(printRequests);
printRequests = operations.stream().filter(operation -> operation instanceof PrintTextOperation).map(operation -> ((PrintTextOperation) operation).getEntity()).collect(toList());
changesTracker.addPrintRequests(printRequests);
final List<NavigationRequest> navigationRequests = operations.stream().filter(operation -> operation instanceof NavigationOperation).map(operation -> ((NavigationOperation) operation).getEntity()).collect(toList());
changesTracker.addNavigationRequests(navigationRequests);
final List<SendEmailRequest> sendEmailRequests = operations.stream().filter(operation -> operation instanceof SendEmailOperation).map(operation -> ((SendEmailOperation) operation).getEntity()).collect(toList());
changesTracker.addSendEmailRequests(sendEmailRequests);
}
// propagate changes in existing documents and links that has been loaded prior to calling this rule
task.propagateChanges(changedDocuments, changedLinkInstances);
return changesTracker;
}
use of io.lumeer.core.task.executor.operation.DocumentRemovalOperation in project engine by Lumeer.
the class SingleStage method removeDocuments.
private List<Document> removeDocuments(final List<DocumentRemovalOperation> operations) {
if (!operations.isEmpty()) {
final List<Document> documents = operations.stream().map(DocumentRemovalOperation::getEntity).collect(toList());
final Map<String, Collection> allCollections = task.getDaoContextSnapshot().getCollectionDao().getCollectionsByIds(documents.stream().map(Document::getCollectionId).collect(toList())).stream().collect(Collectors.toMap(Collection::getId, Function.identity()));
final Map<String, LinkType> allLinkTypes = task.getDaoContextSnapshot().getLinkTypeDao().getAllLinkTypes().stream().collect(Collectors.toMap(LinkType::getId, Function.identity()));
documents.forEach(document -> {
// decrease documents count in collections map
if (!changesTracker.getCollectionsMap().containsKey(document.getCollectionId())) {
// not yet tracked
final Collection collection = allCollections.get(document.getCollectionId());
changesTracker.updateCollectionsMap(Map.of(collection.getId(), collection));
}
// decrease documents count in updated collections in operations tracker
final Optional<Collection> changedCollection = changesTracker.getCollections().stream().filter(c -> c.getId().equals(document.getCollectionId())).findFirst();
final Collection collection = allCollections.get(document.getCollectionId());
if (changedCollection.isEmpty()) {
// not yet tracked
changesTracker.getCollections().add(collection);
}
final List<LinkInstance> removedLinks = task.getDaoContextSnapshot().getLinkInstanceDao().getLinkInstancesByDocumentIds(Set.of(document.getId()));
final Set<String> removedFromLinkTypes = removedLinks.stream().map(LinkInstance::getLinkTypeId).collect(toSet());
changesTracker.addRemovedLinkInstances(removedLinks);
task.getDaoContextSnapshot().getLinkInstanceDao().deleteLinkInstancesByDocumentsIds(Set.of(document.getId()));
removedLinks.forEach(link -> {
var linkType = allLinkTypes.get(link.getLinkTypeId());
var decodedDeletedData = constraintManager.decodeDataTypes(linkType, link.getData());
auditAdapter.registerDelete(link.getLinkTypeId(), ResourceType.LINK, link.getId(), task.getInitiator(), automationName, null, decodedDeletedData);
});
removedFromLinkTypes.forEach(linkTypeId -> {
// decrease link instances count in link types map
if (changesTracker.getLinkTypesMap().containsKey(linkTypeId)) {
// present in link types map
final LinkType linkType = changesTracker.getLinkTypesMap().get(linkTypeId);
linkTypeAdapter.mapLinkTypeComputedProperties(linkType);
} else {
// not yet in the map
final LinkType linkType = allLinkTypes.get(linkTypeId);
linkTypeAdapter.mapLinkTypeComputedProperties(linkType);
changesTracker.updateLinkTypesMap(Map.of(linkType.getId(), linkType));
}
// decrease link instances count in updated link types in operations tracker
final Optional<LinkType> changedLinkType = changesTracker.getLinkTypes().stream().filter(l -> l.getId().equals(linkTypeId)).findFirst();
final LinkType linkType = allLinkTypes.get(linkTypeId);
if (changedLinkType.isPresent()) {
// tracked in operations tracker
changedLinkType.get().setLinksCount(linkType.getLinksCount());
} else {
// not yet tracked
changesTracker.getLinkTypes().add(linkType);
}
});
task.getDaoContextSnapshot().getDocumentDao().deleteDocument(document.getId(), document.getData());
task.getDaoContextSnapshot().getDataDao().deleteData(document.getCollectionId(), document.getId());
var decodedDeletedData = constraintManager.decodeDataTypes(collection, document.getData());
auditAdapter.registerDelete(document.getCollectionId(), ResourceType.DOCUMENT, document.getId(), task.getInitiator(), automationName, null, decodedDeletedData);
});
return documents;
}
return List.of();
}
Aggregations