Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@
import com.sap.cds.feature.attachments.handler.draftservice.DraftActiveAttachmentsHandler;
import com.sap.cds.feature.attachments.handler.draftservice.DraftCancelAttachmentsHandler;
import com.sap.cds.feature.attachments.handler.draftservice.DraftPatchAttachmentsHandler;
import com.sap.cds.feature.attachments.handler.draftservice.modifier.ActiveEntityModifier;
import com.sap.cds.feature.attachments.service.AttachmentService;
import com.sap.cds.feature.attachments.service.AttachmentsServiceImpl;
import com.sap.cds.feature.attachments.service.handler.DefaultAttachmentsServiceHandler;
Expand Down Expand Up @@ -124,8 +123,7 @@ public void eventHandlers(CdsRuntimeConfigurer configurer) {
boolean hasDraftServices = serviceCatalog.getServices(DraftService.class).findFirst().isPresent();
if (hasDraftServices) {
configurer.eventHandler(new DraftPatchAttachmentsHandler(persistenceService, eventFactory));
configurer.eventHandler(new DraftCancelAttachmentsHandler(attachmentsReader, deleteContentEvent,
ActiveEntityModifier::new));
configurer.eventHandler(new DraftCancelAttachmentsHandler(attachmentsReader, deleteContentEvent));
configurer.eventHandler(new DraftActiveAttachmentsHandler(storage));
} else {
logger.debug("No draft service is available. Draft event handlers will not be registered.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**************************************************************************
* (C) 2019-2025 SAP SE or an SAP affiliate company. All rights reserved. *
**************************************************************************/
package com.sap.cds.feature.attachments.handler.draftservice.modifier;
package com.sap.cds.feature.attachments.handler.draftservice;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -24,14 +24,14 @@
* <li>{@code fullEntityName}</li>
* </ul>
*/
public class ActiveEntityModifier implements Modifier {
class ActiveEntityModifier implements Modifier {

private static final Logger logger = LoggerFactory.getLogger(ActiveEntityModifier.class);

private final boolean isActiveEntity;
private final String fullEntityName;

public ActiveEntityModifier(boolean isActiveEntity, String fullEntityName) {
ActiveEntityModifier(boolean isActiveEntity, String fullEntityName) {
this.isActiveEntity = isActiveEntity;
this.fullEntityName = fullEntityName;
}
Expand All @@ -44,10 +44,9 @@ public CqnStructuredTypeRef ref(CqnStructuredTypeRef original) {
fullEntityName);
rootSegment.id(fullEntityName);

Modifier modifier = new ActiveEntityModifier(isActiveEntity, fullEntityName);
for (RefSegment segment : ref.segments()) {
if (segment.filter().isPresent()) {
segment.filter(CQL.copy(segment.filter().orElseThrow(), new ActiveEntityModifier(isActiveEntity, fullEntityName)));
}
segment.filter(segment.filter().map(filter -> CQL.copy(filter, modifier)).orElse(null));
}
return ref.build();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.sap.cds.feature.attachments.handler.common.ApplicationHandlerHelper;
import com.sap.cds.feature.attachments.handler.common.AttachmentsReader;
import com.sap.cds.feature.attachments.handler.draftservice.constants.DraftConstants;
import com.sap.cds.feature.attachments.handler.draftservice.modifier.ActiveEntityModifierProvider;
import com.sap.cds.ql.CQL;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsStructuredType;
Expand All @@ -41,13 +40,11 @@ public class DraftCancelAttachmentsHandler implements EventHandler {

private final AttachmentsReader attachmentsReader;
private final ModifyAttachmentEvent deleteContentAttachmentEvent;
private final ActiveEntityModifierProvider activeEntityModifierProvider;

public DraftCancelAttachmentsHandler(AttachmentsReader attachmentsReader,
ModifyAttachmentEvent deleteContentAttachmentEvent, ActiveEntityModifierProvider activeEntityModifierProvider) {
ModifyAttachmentEvent deleteContentAttachmentEvent) {
this.attachmentsReader = attachmentsReader;
this.deleteContentAttachmentEvent = deleteContentAttachmentEvent;
this.activeEntityModifierProvider = activeEntityModifierProvider;
}

@Before
Expand All @@ -66,7 +63,6 @@ public void processBeforeDraftCancel(DraftCancelEventContext context) {
var validator = buildDeleteContentValidator(context, activeCondensedAttachments);
ApplicationHandlerHelper.callValidator(context.getTarget(), draftAttachments, filter, validator);
}

}

private Validator buildDeleteContentValidator(DraftCancelEventContext context,
Expand Down Expand Up @@ -105,8 +101,7 @@ private boolean isDraftEntity(DraftCancelEventContext context) {

private List<CdsData> readAttachments(DraftCancelEventContext context, CdsStructuredType entity,
boolean isActiveEntity) {
var cqnInactiveEntity = CQL.copy(context.getCqn(),
activeEntityModifierProvider.getModifier(isActiveEntity, entity.getQualifiedName()));
var cqnInactiveEntity = CQL.copy(context.getCqn(), new ActiveEntityModifier(isActiveEntity, entity.getQualifiedName()));
return attachmentsReader.readAttachments(context.getModel(), (CdsEntity) entity, cqnInactiveEntity);
}

Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.sap.cds.feature.attachments.handler.draftservice.modifier;
package com.sap.cds.feature.attachments.handler.draftservice;

import static com.sap.cds.services.draft.Drafts.IS_ACTIVE_ENTITY;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
package com.sap.cds.feature.attachments.handler.draftservice;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoInteractions;
import static org.mockito.Mockito.when;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

import org.junit.jupiter.api.BeforeAll;
Expand All @@ -18,13 +24,10 @@
import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEvent;
import com.sap.cds.feature.attachments.handler.common.AttachmentsReader;
import com.sap.cds.feature.attachments.handler.draftservice.constants.DraftConstants;
import com.sap.cds.feature.attachments.handler.draftservice.modifier.ActiveEntityModifierProvider;
import com.sap.cds.feature.attachments.handler.helper.RuntimeHelper;
import com.sap.cds.ql.Delete;
import com.sap.cds.ql.cqn.CqnDelete;
import com.sap.cds.ql.cqn.Modifier;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.services.draft.DraftCancelEventContext;
import com.sap.cds.services.runtime.CdsRuntime;

Expand All @@ -35,7 +38,6 @@ class DraftCancelAttachmentsHandlerTest {
private DraftCancelAttachmentsHandler cut;
private AttachmentsReader attachmentsReader;
private ModifyAttachmentEvent deleteContentAttachmentEvent;
private ActiveEntityModifierProvider modifierProvider;
private DraftCancelEventContext eventContext;
private ArgumentCaptor<CqnDelete> deleteArgumentCaptor;
private ArgumentCaptor<CdsData> dataArgumentCaptor;
Expand All @@ -49,31 +51,28 @@ static void classSetup() {
void setup() {
attachmentsReader = mock(AttachmentsReader.class);
deleteContentAttachmentEvent = mock(ModifyAttachmentEvent.class);
modifierProvider = mock(ActiveEntityModifierProvider.class);
cut = new DraftCancelAttachmentsHandler(attachmentsReader, deleteContentAttachmentEvent, modifierProvider);
cut = new DraftCancelAttachmentsHandler(attachmentsReader, deleteContentAttachmentEvent);

eventContext = mock(DraftCancelEventContext.class);
when(modifierProvider.getModifier(anyBoolean(), anyString())).thenReturn(new Modifier() {
});
deleteArgumentCaptor = ArgumentCaptor.forClass(CqnDelete.class);
dataArgumentCaptor = ArgumentCaptor.forClass(CdsData.class);
}

@Test
void whereConditionIncludedNothingHappens() {
getEntityAndMockContext(RootTable_.CDS_NAME);
var delete = Delete.from(RootTable_.class).where(root -> root.ID().eq("test"));
CqnDelete delete = Delete.from(RootTable_.class).where(root -> root.ID().eq("test"));
when(eventContext.getCqn()).thenReturn(delete);

cut.processBeforeDraftCancel(eventContext);

verifyNoInteractions(attachmentsReader, deleteContentAttachmentEvent, modifierProvider);
verifyNoInteractions(attachmentsReader, deleteContentAttachmentEvent);
}

@Test
void nothingSelectedNothingToDo() {
getEntityAndMockContext(RootTable_.CDS_NAME);
var delete = Delete.from(RootTable_.class);
CqnDelete delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());

Expand All @@ -85,63 +84,58 @@ void nothingSelectedNothingToDo() {
@Test
void attachmentReaderCorrectCalled() {
getEntityAndMockContext(RootTable_.CDS_NAME);
var delete = Delete.from(RootTable_.class);
CqnDelete delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());

cut.processBeforeDraftCancel(eventContext);

var target = eventContext.getTarget();
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq(target), deleteArgumentCaptor.capture());
var originDelete = deleteArgumentCaptor.getValue();
CdsEntity target = eventContext.getTarget();
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq(target),
deleteArgumentCaptor.capture());
CqnDelete originDelete = deleteArgumentCaptor.getValue();
assertThat(originDelete.toJson()).isEqualTo(delete.toJson());

deleteArgumentCaptor = ArgumentCaptor.forClass(CqnDelete.class);
var siblingTarget = target.getTargetOf(DraftConstants.SIBLING_ENTITY);
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq((CdsEntity) siblingTarget),
CdsEntity siblingTarget = target.getTargetOf(DraftConstants.SIBLING_ENTITY);
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq(siblingTarget),
deleteArgumentCaptor.capture());
var siblingDelete = deleteArgumentCaptor.getValue();
assertThat(siblingDelete.toJson()).isEqualTo(delete.toJson());
CqnDelete siblingDelete = deleteArgumentCaptor.getValue();
assertThat(siblingDelete.toJson()).isNotEqualTo(delete.toJson());
}

@Test
void modifierCalledWithCorrectEntitiesIfDraftIsInContext() {
getEntityAndMockContext(RootTable_.CDS_NAME + DraftConstants.DRAFT_TABLE_POSTFIX);
var delete = Delete.from(RootTable_.class);
CqnDelete delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());

cut.processBeforeDraftCancel(eventContext);

verify(modifierProvider).getModifier(false, RootTable_.CDS_NAME + DraftConstants.DRAFT_TABLE_POSTFIX);
verify(modifierProvider).getModifier(true, RootTable_.CDS_NAME);
}

@Test
void modifierCalledWithCorrectEntitiesIfActiveEntityIsInContext() {
getEntityAndMockContext(RootTable_.CDS_NAME);
var delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());

cut.processBeforeDraftCancel(eventContext);

verify(modifierProvider).getModifier(false, RootTable_.CDS_NAME + DraftConstants.DRAFT_TABLE_POSTFIX);
verify(modifierProvider).getModifier(true, RootTable_.CDS_NAME);
CdsEntity target = eventContext.getTarget();
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq(target),
deleteArgumentCaptor.capture());
CdsEntity siblingTarget = target.getTargetOf(DraftConstants.SIBLING_ENTITY);
verify(attachmentsReader).readAttachments(eq(runtime.getCdsModel()), eq(siblingTarget),
deleteArgumentCaptor.capture());
CqnDelete siblingDelete = deleteArgumentCaptor.getValue();
assertThat(siblingDelete.toJson()).isEqualTo(delete.toJson());
}

@Test
void createdEntityNeedsToBeDeleted() {
getEntityAndMockContext(Attachment_.CDS_NAME);
var delete = Delete.from(RootTable_.class);
CqnDelete delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());
var siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
var attachment = buildAttachmentAndReturnByReader("test", siblingTarget, false, "");
CdsEntity siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
Attachment attachment = buildAttachmentAndReturnByReader("test", siblingTarget, false, "");

cut.processBeforeDraftCancel(eventContext);

verify(deleteContentAttachmentEvent).processEvent(any(), eq(null), dataArgumentCaptor.capture(), eq(eventContext));
verify(deleteContentAttachmentEvent).processEvent(any(), eq(null), dataArgumentCaptor.capture(),
eq(eventContext));
assertThat(dataArgumentCaptor.getValue()).isEqualTo(attachment);
}

Expand All @@ -151,14 +145,15 @@ void updatedEntityNeedsToBeDeleted() {
var delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());
var siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
CdsEntity siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
var id = UUID.randomUUID().toString();
var draftAttachment = buildAttachmentAndReturnByReader("test", siblingTarget, true, id);
Attachment draftAttachment = buildAttachmentAndReturnByReader("test", siblingTarget, true, id);
buildAttachmentAndReturnByReader("test origin", eventContext.getTarget(), false, id);

cut.processBeforeDraftCancel(eventContext);

verify(deleteContentAttachmentEvent).processEvent(any(), eq(null), dataArgumentCaptor.capture(), eq(eventContext));
verify(deleteContentAttachmentEvent).processEvent(any(), eq(null), dataArgumentCaptor.capture(),
eq(eventContext));
assertThat(dataArgumentCaptor.getValue()).isEqualTo(draftAttachment);
}

Expand All @@ -168,7 +163,7 @@ void entityNotUpdatedNothingToDelete() {
var delete = Delete.from(RootTable_.class);
when(eventContext.getCqn()).thenReturn(delete);
when(eventContext.getModel()).thenReturn(runtime.getCdsModel());
var siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
CdsEntity siblingTarget = eventContext.getTarget().getTargetOf(DraftConstants.SIBLING_ENTITY);
var id = UUID.randomUUID().toString();
var contentId = UUID.randomUUID().toString();
buildAttachmentAndReturnByReader(contentId, siblingTarget, true, id);
Expand All @@ -179,24 +174,20 @@ void entityNotUpdatedNothingToDelete() {
verifyNoInteractions(deleteContentAttachmentEvent);
}

private Attachment buildAttachmentAndReturnByReader(String contentId, CdsStructuredType target,
boolean hasActiveEntity, String id) {
var attachment = Attachment.create();
private Attachment buildAttachmentAndReturnByReader(String contentId, CdsEntity target, boolean hasActiveEntity,
String id) {
Attachment attachment = Attachment.create();
attachment.setId(id);
attachment.setContentId(contentId);
attachment.setHasActiveEntity(hasActiveEntity);
attachment.setContent(null);
when(attachmentsReader.readAttachments(any(), (CdsEntity) eq(target), any())).thenReturn(List.of(attachment));
when(attachmentsReader.readAttachments(any(), eq(target), any())).thenReturn(List.of(attachment));
return attachment;
}

private void getEntityAndMockContext(String cdsName) {
var serviceEntity = runtime.getCdsModel().findEntity(cdsName);
mockTargetInUpdateContext(serviceEntity.orElseThrow());
}

private void mockTargetInUpdateContext(CdsEntity serviceEntity) {
when(eventContext.getTarget()).thenReturn(serviceEntity);
Optional<CdsEntity> serviceEntity = runtime.getCdsModel().findEntity(cdsName);
when(eventContext.getTarget()).thenReturn(serviceEntity.orElseThrow());
}

}