diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/configuration/Registration.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/configuration/Registration.java index f18518fb..fbd38ea3 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/configuration/Registration.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/configuration/Registration.java @@ -21,13 +21,10 @@ import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.DoNothingAttachmentEvent; import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.MarkAsDeletedAttachmentEvent; import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEventFactory; import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.UpdateAttachmentEvent; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.modifier.BeforeReadItemsModifier; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.validator.DefaultAttachmentStatusValidator; import com.sap.cds.feature.attachments.handler.applicationservice.processor.transaction.CreationChangeSetListener; import com.sap.cds.feature.attachments.handler.applicationservice.processor.transaction.ListenerProvider; -import com.sap.cds.feature.attachments.handler.common.AttachmentsReader; import com.sap.cds.feature.attachments.handler.common.DefaultAssociationCascader; import com.sap.cds.feature.attachments.handler.common.DefaultAttachmentsReader; import com.sap.cds.feature.attachments.handler.draftservice.DraftActiveAttachmentsHandler; @@ -39,7 +36,6 @@ import com.sap.cds.feature.attachments.service.handler.DefaultAttachmentsServiceHandler; import com.sap.cds.feature.attachments.service.handler.transaction.EndTransactionMalwareScanProvider; import com.sap.cds.feature.attachments.service.handler.transaction.EndTransactionMalwareScanRunner; -import com.sap.cds.feature.attachments.service.malware.AsyncMalwareScanExecutor; import com.sap.cds.feature.attachments.service.malware.DefaultAttachmentMalwareScanner; import com.sap.cds.feature.attachments.service.malware.client.DefaultMalwareScanClient; import com.sap.cds.feature.attachments.service.malware.client.httpclient.MalwareScanClientProviderFactory; @@ -47,7 +43,6 @@ import com.sap.cds.feature.attachments.service.malware.constants.MalwareScanConstants; import com.sap.cds.feature.attachments.utilities.LoggingMarker; import com.sap.cds.services.environment.CdsProperties.ConnectionPool; -import com.sap.cds.services.handler.EventHandler; import com.sap.cds.services.outbox.OutboxService; import com.sap.cds.services.persistence.PersistenceService; import com.sap.cds.services.runtime.CdsRuntimeConfiguration; @@ -66,19 +61,17 @@ public class Registration implements CdsRuntimeConfiguration { @Override public void services(CdsRuntimeConfigurer configurer) { - configurer.service(buildAttachmentService()); + configurer.service(new AttachmentsServiceImpl()); } @Override public void eventHandlers(CdsRuntimeConfigurer configurer) { logger.info(marker, "Registering event handler for attachment service"); - var persistenceService = configurer.getCdsRuntime().getServiceCatalog().getService(PersistenceService.class, - PersistenceService.DEFAULT_NAME); - var attachmentService = configurer.getCdsRuntime().getServiceCatalog().getService(AttachmentService.class, - AttachmentService.DEFAULT_NAME); - var outbox = configurer.getCdsRuntime().getServiceCatalog().getService(OutboxService.class, - OutboxService.PERSISTENT_UNORDERED_NAME); + var serviceCatalog = configurer.getCdsRuntime().getServiceCatalog(); + var persistenceService = serviceCatalog.getService(PersistenceService.class, PersistenceService.DEFAULT_NAME); + var attachmentService = serviceCatalog.getService(AttachmentService.class, AttachmentService.DEFAULT_NAME); + var outbox = serviceCatalog.getService(OutboxService.class, OutboxService.PERSISTENT_UNORDERED_NAME); var outboxedAttachmentService = outbox.outboxed(attachmentService); List bindings = configurer.getCdsRuntime().getEnvironment().getServiceBindings().filter( @@ -94,14 +87,17 @@ public void eventHandlers(CdsRuntimeConfigurer configurer) { var deleteContentEvent = new MarkAsDeletedAttachmentEvent(outboxedAttachmentService); var eventFactory = buildAttachmentEventFactory(attachmentService, deleteContentEvent, outboxedAttachmentService); - var attachmentsReader = buildAttachmentsReader(persistenceService); + var attachmentsReader = new DefaultAttachmentsReader(new DefaultAssociationCascader(), persistenceService); ThreadLocalDataStorage storage = new ThreadLocalDataStorage(); - configurer.eventHandler(buildCreateHandler(eventFactory, storage)); - configurer.eventHandler(buildUpdateHandler(eventFactory, attachmentsReader, outboxedAttachmentService, storage)); - configurer.eventHandler(buildDeleteHandler(attachmentsReader, deleteContentEvent)); - configurer.eventHandler(buildReadHandler(attachmentService, - new EndTransactionMalwareScanRunner(null, null, malwareScanner, configurer.getCdsRuntime()))); + // register event handlers for application service + configurer.eventHandler(new CreateAttachmentsHandler(eventFactory, storage)); + configurer.eventHandler(new UpdateAttachmentsHandler(eventFactory, attachmentsReader, outboxedAttachmentService, storage)); + configurer.eventHandler(new DeleteAttachmentsHandler(attachmentsReader, deleteContentEvent)); + var scanRunner = new EndTransactionMalwareScanRunner(null, null, malwareScanner, configurer.getCdsRuntime()); + configurer.eventHandler(new ReadAttachmentsHandler(attachmentService, new DefaultAttachmentStatusValidator(), scanRunner)); + + // register event handlers for draft service configurer.eventHandler(new DraftPatchAttachmentsHandler(persistenceService, eventFactory)); configurer.eventHandler( new DraftCancelAttachmentsHandler(attachmentsReader, deleteContentEvent, ActiveEntityModifier::new)); @@ -114,11 +110,6 @@ private EndTransactionMalwareScanProvider createEndTransactionMalwareScanListene malwareScanner, configurer.getCdsRuntime()); } - private AttachmentService buildAttachmentService() { - logger.info(marker, "Registering AttachmentService"); - return new AttachmentsServiceImpl(); - } - private DefaultModifyAttachmentEventFactory buildAttachmentEventFactory(AttachmentService attachmentService, ModifyAttachmentEvent deleteContentEvent, AttachmentService outboxedAttachmentService) { var creationChangeSetListener = createCreationFailedListener(outboxedAttachmentService); @@ -134,30 +125,4 @@ private ListenerProvider createCreationFailedListener(AttachmentService outboxed return (contentId, cdsRuntime) -> new CreationChangeSetListener(contentId, cdsRuntime, outboxedAttachmentService); } - protected EventHandler buildCreateHandler(ModifyAttachmentEventFactory factory, ThreadLocalDataStorage storage) { - return new CreateAttachmentsHandler(factory, storage); - } - - protected EventHandler buildDeleteHandler(AttachmentsReader attachmentsReader, - ModifyAttachmentEvent deleteContentEvent) { - return new DeleteAttachmentsHandler(attachmentsReader, deleteContentEvent); - } - - protected EventHandler buildReadHandler(AttachmentService attachmentService, - AsyncMalwareScanExecutor asyncMalwareScanExecutor) { - var statusValidator = new DefaultAttachmentStatusValidator(); - return new ReadAttachmentsHandler(attachmentService, BeforeReadItemsModifier::new, statusValidator, - asyncMalwareScanExecutor); - } - - protected EventHandler buildUpdateHandler(ModifyAttachmentEventFactory factory, AttachmentsReader attachmentsReader, - AttachmentService outboxedAttachmentService, ThreadLocalDataStorage storage) { - return new UpdateAttachmentsHandler(factory, attachmentsReader, outboxedAttachmentService, storage); - } - - protected AttachmentsReader buildAttachmentsReader(PersistenceService persistenceService) { - var cascader = new DefaultAssociationCascader(); - return new DefaultAttachmentsReader(cascader, persistenceService); - } - } diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/DeleteAttachmentsHandler.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/DeleteAttachmentsHandler.java index b7d93dfe..a84c9d03 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/DeleteAttachmentsHandler.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/DeleteAttachmentsHandler.java @@ -3,13 +3,14 @@ **************************************************************************/ package com.sap.cds.feature.attachments.handler.applicationservice; +import java.io.InputStream; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.Marker; import com.sap.cds.CdsData; import com.sap.cds.CdsDataProcessor.Converter; -import com.sap.cds.CdsDataProcessor.Filter; import com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents.ModifyAttachmentEvent; import com.sap.cds.feature.attachments.handler.common.ApplicationHandlerHelper; import com.sap.cds.feature.attachments.handler.common.AttachmentsReader; @@ -22,9 +23,8 @@ import com.sap.cds.services.handler.annotations.ServiceName; /** - * The class {@link DeleteAttachmentsHandler} is an event handler that is - * responsible for deleting attachments for entities. - * It is called before a delete event is executed. + * The class {@link DeleteAttachmentsHandler} is an event handler that is responsible for deleting attachments for + * entities. It is called before a delete event is executed. */ @ServiceName(value = "*", type = ApplicationService.class) public class DeleteAttachmentsHandler implements EventHandler { @@ -47,11 +47,11 @@ public void processBefore(CdsDeleteEventContext context) { logger.debug(marker, "Processing before delete event for entity {}", context.getTarget().getName()); var attachments = attachmentsReader.readAttachments(context.getModel(), context.getTarget(), context.getCqn()); - Filter filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); - Converter converter = (path, element, value) -> deleteContentAttachmentEvent.processEvent(path, value, - CdsData.create(path.target().values()), context); - ApplicationHandlerHelper.callProcessor(context.getTarget(), attachments, filter, converter); + Converter converter = (path, element, value) -> deleteContentAttachmentEvent.processEvent(path, + (InputStream) value, CdsData.create(path.target().values()), context); + + ApplicationHandlerHelper.callProcessor(context.getTarget(), attachments, ApplicationHandlerHelper.MEDIA_CONTENT_FILTER, converter); } } diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandler.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandler.java index dbab5f40..affbf0c1 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandler.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandler.java @@ -19,7 +19,7 @@ import com.sap.cds.CdsDataProcessor.Converter; import com.sap.cds.feature.attachments.generated.cds4j.sap.attachments.Attachments; import com.sap.cds.feature.attachments.generated.cds4j.sap.attachments.StatusCode; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.modifier.ItemModifierProvider; +import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.modifier.BeforeReadItemsModifier; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.stream.LazyProxyInputStream; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.validator.AttachmentStatusValidator; import com.sap.cds.feature.attachments.handler.common.ApplicationHandlerHelper; @@ -57,14 +57,12 @@ public class ReadAttachmentsHandler implements EventHandler { private static final Marker marker = LoggingMarker.APPLICATION_READ_HANDLER.getMarker(); private final AttachmentService attachmentService; - private final ItemModifierProvider provider; private final AttachmentStatusValidator attachmentStatusValidator; private final AsyncMalwareScanExecutor asyncMalwareScanExecutor; - public ReadAttachmentsHandler(AttachmentService attachmentService, ItemModifierProvider provider, + public ReadAttachmentsHandler(AttachmentService attachmentService, AttachmentStatusValidator attachmentStatusValidator, AsyncMalwareScanExecutor asyncMalwareScanExecutor) { this.attachmentService = attachmentService; - this.provider = provider; this.attachmentStatusValidator = attachmentStatusValidator; this.asyncMalwareScanExecutor = asyncMalwareScanExecutor; } @@ -77,7 +75,7 @@ public void processBefore(CdsReadEventContext context) { var cdsModel = context.getModel(); var fieldNames = getAttachmentAssociations(cdsModel, context.getTarget(), "", new ArrayList<>()); if (!fieldNames.isEmpty()) { - var resultCqn = CQL.copy(context.getCqn(), provider.getBeforeReadContentIdEnhancer(fieldNames)); + var resultCqn = CQL.copy(context.getCqn(), new BeforeReadItemsModifier(fieldNames)); context.setCqn(resultCqn); } } @@ -90,7 +88,6 @@ public void processAfter(CdsReadEventContext context, List data) { } logger.debug(marker, "Processing after read event for entity {}", context.getTarget().getName()); - var filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); Converter converter = (path, element, value) -> { logger.info(marker, "Processing after read event for entity {}", element.getName()); var contentId = (String) path.target().values().get(Attachments.CONTENT_ID); @@ -107,7 +104,7 @@ public void processAfter(CdsReadEventContext context, List data) { } }; - ApplicationHandlerHelper.callProcessor(context.getTarget(), data, filter, converter); + ApplicationHandlerHelper.callProcessor(context.getTarget(), data, ApplicationHandlerHelper.MEDIA_CONTENT_FILTER, converter); } private List getAttachmentAssociations(CdsModel model, CdsEntity entity, String associationName, diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/UpdateAttachmentsHandler.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/UpdateAttachmentsHandler.java index 6c70bfd9..4544cc0e 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/UpdateAttachmentsHandler.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/UpdateAttachmentsHandler.java @@ -105,7 +105,7 @@ private CqnFilterableStatement getSelect(CqnUpdate update, CdsEntity target) { private void deleteRemovedAttachments(List exitingDataList, List updatedDataList, CdsEntity entity, UserInfo userInfo) { var condensedUpdatedData = ApplicationHandlerHelper.condenseData(updatedDataList, entity); - var filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); + Validator validator = (path, element, value) -> { var keys = ApplicationHandlerHelper.removeDraftKeys(path.target().keys()); var entryExists = condensedUpdatedData.stream().anyMatch( @@ -115,7 +115,7 @@ private void deleteRemovedAttachments(List exitingDataList, List data, List existingDataList, ModifyAttachmentEventFactory eventFactory, EventContext eventContext) { - Filter filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); Converter converter = (path, element, value) -> handleAttachmentForEntity(existingDataList, eventFactory, - eventContext, path, value); - ApplicationHandlerHelper.callProcessor(entity, data, filter, converter); + eventContext, path, (InputStream) value); + + ApplicationHandlerHelper.callProcessor(entity, data, ApplicationHandlerHelper.MEDIA_CONTENT_FILTER, converter); } - public static Object handleAttachmentForEntity(List existingDataList, - ModifyAttachmentEventFactory eventFactory, EventContext eventContext, Path path, Object value) { + public static InputStream handleAttachmentForEntity(List existingDataList, + ModifyAttachmentEventFactory eventFactory, EventContext eventContext, Path path, InputStream content) { var keys = ApplicationHandlerHelper.removeDraftKeys(path.target().keys()); ReadonlyDataContextEnhancer.fillReadonlyInContext((CdsData) path.target().values()); var existingData = getExistingData(keys, existingDataList); var contentIdExists = path.target().values().containsKey(Attachments.CONTENT_ID); var contentId = (String) path.target().values().get(Attachments.CONTENT_ID); - var eventToProcess = eventFactory.getEvent(value, contentId, contentIdExists, existingData); - return eventToProcess.processEvent(path, value, existingData, eventContext); + // for the current request find the event to process + ModifyAttachmentEvent eventToProcess = eventFactory.getEvent(content, contentId, contentIdExists, existingData); + + // process the event + return eventToProcess.processEvent(path, content, existingData, eventContext); } private static CdsData getExistingData(Map keys, List existingDataList) { - return existingDataList.stream().filter(existingData -> ApplicationHandlerHelper.areKeysInData(keys, existingData)) - .findAny().orElse(CdsData.create()); + return existingDataList.stream() + .filter(existingData -> ApplicationHandlerHelper.areKeysInData(keys, existingData)).findAny() + .orElse(CdsData.create()); } } diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/helper/ReadonlyDataContextEnhancer.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/helper/ReadonlyDataContextEnhancer.java index b9708452..8464d76d 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/helper/ReadonlyDataContextEnhancer.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/applicationservice/helper/ReadonlyDataContextEnhancer.java @@ -20,7 +20,7 @@ private ReadonlyDataContextEnhancer() { } public static void enhanceReadonlyDataInContext(EventContext context, List data, boolean isDraft) { - var filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); + Validator validator = (path, element, value) -> { if (isDraft) { var contentId = path.target().values().get(Attachments.CONTENT_ID); @@ -36,7 +36,8 @@ public static void enhanceReadonlyDataInContext(EventContext context, List getFieldValue(String fieldName, Map mediaAssociations); - -} diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/ApplicationHandlerHelper.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/ApplicationHandlerHelper.java index 1cfacea7..fbc27955 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/ApplicationHandlerHelper.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/ApplicationHandlerHelper.java @@ -29,6 +29,13 @@ */ public final class ApplicationHandlerHelper { + /** + * A filter for media content fields. The filter checks if the entity is a media entity and if the element has the + * annotation "Core.MediaType". + */ + public static final Filter MEDIA_CONTENT_FILTER = (path, element, type) -> isMediaEntity(path.target().type()) + && hasElementAnnotation(element, ModelConstants.ANNOTATION_CORE_MEDIA_TYPE); + /** * Checks if the data contains a content field. * @@ -40,7 +47,7 @@ public static boolean noContentFieldInData(CdsEntity entity, List data) var isIncluded = new AtomicBoolean(); Validator validator = (path, element, value) -> isIncluded.set(true); - callValidator(entity, data, buildFilterForMediaTypeEntity(), validator); + callValidator(entity, data, MEDIA_CONTENT_FILTER, validator); return !isIncluded.get(); } @@ -52,17 +59,6 @@ public static void callValidator(CdsEntity entity, List data, Filter fi CdsDataProcessor.create().addValidator(filter, validator).process(data, entity); } - /** - * Builds the filter for media type entities. The filter checks if the entity is a media entity and if the element - * has the annotation "Core.MediaType". - * - * @return The {@link Filter} for media type entities - */ - public static Filter buildFilterForMediaTypeEntity() { - return (path, element, type) -> isMediaEntity(path.target().type()) && hasElementAnnotation(element, - ModelConstants.ANNOTATION_CORE_MEDIA_TYPE); - } - /** * Checks if the entity is a media entity. A media entity is an entity that is annotated with the annotation * "_is_media_data". @@ -74,10 +70,6 @@ public static boolean isMediaEntity(CdsStructuredType baseEntity) { return baseEntity.getAnnotationValue(ModelConstants.ANNOTATION_IS_MEDIA_DATA, false); } - public static boolean hasElementAnnotation(CdsElement element, String annotation) { - return element.findAnnotation(annotation).isPresent(); - } - public static boolean doesContentIdExistsBefore(Map existingData) { return Objects.nonNull(existingData.get(Attachments.CONTENT_ID)); } @@ -85,10 +77,9 @@ public static boolean doesContentIdExistsBefore(Map existingData) { public static List condenseData(List data, CdsEntity entity) { var resultList = new ArrayList(); - Filter filter = buildFilterForMediaTypeEntity(); Validator validator = (path, element, value) -> resultList.add(CdsData.create(path.target().values())); - callValidator(entity, data, filter, validator); + callValidator(entity, data, MEDIA_CONTENT_FILTER, validator); return resultList; } @@ -110,6 +101,10 @@ public static CdsEntity getBaseEntity(CdsModel model, CdsEntity entity) { return entityResultOptional.orElseGet(() -> model.findEntity(entity.getQualifiedName()).orElseThrow()); } + private static boolean hasElementAnnotation(CdsElement element, String annotation) { + return element.findAnnotation(annotation).isPresent(); + } + private static boolean isDraftActiveEntityField(String key) { return key.equals(Drafts.IS_ACTIVE_ENTITY); } diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AssociationCascader.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AssociationCascader.java index 79c6d578..1ce81f13 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AssociationCascader.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AssociationCascader.java @@ -8,8 +8,8 @@ import com.sap.cds.reflect.CdsModel; /** - * The interface {@link AssociationCascader} is used to find the entity path. - */ + * The interface {@link AssociationCascader} is used to find the entity path. + */ public interface AssociationCascader { NodeTree findEntityPath(CdsModel model, CdsEntity entity); diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AttachmentsReader.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AttachmentsReader.java index 0f8c8766..fc0a045b 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AttachmentsReader.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/AttachmentsReader.java @@ -11,8 +11,8 @@ import com.sap.cds.reflect.CdsModel; /** - * The interface {@link AttachmentsReader} is used to read attachments from the database. - */ + * The interface {@link AttachmentsReader} is used to read attachments from the database. + */ public interface AttachmentsReader { List readAttachments(CdsModel model, CdsEntity entity, CqnFilterableStatement statement); diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/DefaultAssociationCascader.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/DefaultAssociationCascader.java index 42929c0a..5ab74ed6 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/DefaultAssociationCascader.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/common/DefaultAssociationCascader.java @@ -15,19 +15,17 @@ import com.sap.cds.feature.attachments.handler.common.model.AssociationIdentifier; import com.sap.cds.feature.attachments.handler.common.model.NodeTree; -import com.sap.cds.feature.attachments.handler.constants.ModelConstants; import com.sap.cds.reflect.CdsAssociationType; import com.sap.cds.reflect.CdsElementDefinition; import com.sap.cds.reflect.CdsEntity; import com.sap.cds.reflect.CdsModel; -import com.sap.cds.reflect.CdsStructuredType; /** - * The class {@link DefaultAssociationCascader} is used to find entity paths - * to all media resource entities for a given data model. - * The path information is returned in a node tree which starts from the given entity. - * Only composition associations are considered. - */ + * The class {@link DefaultAssociationCascader} is used to find entity paths + * to all media resource entities for a given data model. + * The path information is returned in a node tree which starts from the given entity. + * Only composition associations are considered. + */ public class DefaultAssociationCascader implements AssociationCascader { private static final Logger logger = LoggerFactory.getLogger(DefaultAssociationCascader.class); @@ -54,7 +52,7 @@ private List> getAttachmentAssociationPath(Cds currentList.set(new LinkedList<>()); var baseEntity = ApplicationHandlerHelper.getBaseEntity(model, entity); - var isMediaEntity = isMediaEntity(baseEntity); + var isMediaEntity = ApplicationHandlerHelper.isMediaEntity(baseEntity); if (isMediaEntity) { var identifier = new AssociationIdentifier(associationName, entity.getQualifiedName()); firstList.addLast(identifier); @@ -97,8 +95,4 @@ private List> getAttachmentAssociationPath(Cds return internalResultList; } - private boolean isMediaEntity(CdsStructuredType baseEntity) { - return baseEntity.getAnnotationValue(ModelConstants.ANNOTATION_IS_MEDIA_DATA, false); - } - } diff --git a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/draftservice/DraftPatchAttachmentsHandler.java b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/draftservice/DraftPatchAttachmentsHandler.java index f3a538c7..1841186e 100644 --- a/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/draftservice/DraftPatchAttachmentsHandler.java +++ b/cds-feature-attachments/src/main/java/com/sap/cds/feature/attachments/handler/draftservice/DraftPatchAttachmentsHandler.java @@ -3,6 +3,7 @@ **************************************************************************/ package com.sap.cds.feature.attachments.handler.draftservice; +import java.io.InputStream; import java.util.List; import org.slf4j.Logger; @@ -26,10 +27,9 @@ import com.sap.cds.services.persistence.PersistenceService; /** - * The class {@link DraftPatchAttachmentsHandler} is an event handler that is called - * before a draft patch event is executed. - * The handler checks the attachments of the draft entity and calls the event factory - * and corresponding events. + * The class {@link DraftPatchAttachmentsHandler} is an event handler that is called before a draft patch event is + * executed. The handler checks the attachments of the draft entity and calls the event factory and corresponding + * events. */ @ServiceName(value = "*", type = DraftService.class) public class DraftPatchAttachmentsHandler implements EventHandler { @@ -50,19 +50,18 @@ public DraftPatchAttachmentsHandler(PersistenceService persistence, ModifyAttach public void processBeforeDraftPatch(DraftPatchEventContext context, List data) { logger.debug(marker, "Processing before draft patch event for entity {}", context.getTarget().getName()); - var filter = ApplicationHandlerHelper.buildFilterForMediaTypeEntity(); Converter converter = (path, element, value) -> { - var draftElement = path.target().entity().getQualifiedName().endsWith( - DraftConstants.DRAFT_TABLE_POSTFIX) ? path.target().entity() : path.target().entity().getTargetOf( - DraftConstants.SIBLING_ENTITY); + var draftElement = path.target().entity().getQualifiedName().endsWith(DraftConstants.DRAFT_TABLE_POSTFIX) + ? path.target().entity() + : path.target().entity().getTargetOf(DraftConstants.SIBLING_ENTITY); var select = Select.from(draftElement.getQualifiedName()).matching(path.target().keys()); var result = persistence.run(select); - return ModifyApplicationHandlerHelper.handleAttachmentForEntity(result.listOf(CdsData.class), eventFactory, context, - path, value); + return ModifyApplicationHandlerHelper.handleAttachmentForEntity(result.listOf(CdsData.class), eventFactory, + context, path, (InputStream) value); }; - ApplicationHandlerHelper.callProcessor(context.getTarget(), data, filter, converter); + ApplicationHandlerHelper.callProcessor(context.getTarget(), data, ApplicationHandlerHelper.MEDIA_CONTENT_FILTER, converter); } } diff --git a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandlerTest.java b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandlerTest.java index a0e97c7e..e1814f52 100644 --- a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandlerTest.java +++ b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/ReadAttachmentsHandlerTest.java @@ -6,7 +6,6 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; @@ -25,7 +24,6 @@ import org.junit.jupiter.params.provider.EmptySource; import org.junit.jupiter.params.provider.NullSource; import org.junit.jupiter.params.provider.ValueSource; -import org.mockito.ArgumentCaptor; import com.sap.cds.CdsData; import com.sap.cds.feature.attachments.generated.cds4j.sap.attachments.StatusCode; @@ -37,7 +35,6 @@ import com.sap.cds.feature.attachments.generated.test.cds4j.unit.test.testservice.RootTable; import com.sap.cds.feature.attachments.generated.test.cds4j.unit.test.testservice.RootTable_; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.exception.AttachmentStatusException; -import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.modifier.ItemModifierProvider; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.stream.LazyProxyInputStream; import com.sap.cds.feature.attachments.handler.applicationservice.processor.readhelper.validator.AttachmentStatusValidator; import com.sap.cds.feature.attachments.handler.helper.RuntimeHelper; @@ -45,7 +42,6 @@ import com.sap.cds.feature.attachments.service.malware.AsyncMalwareScanExecutor; import com.sap.cds.ql.Select; import com.sap.cds.ql.cqn.CqnSelect; -import com.sap.cds.ql.cqn.Modifier; import com.sap.cds.services.cds.ApplicationService; import com.sap.cds.services.cds.CdsReadEventContext; import com.sap.cds.services.handler.annotations.After; @@ -61,11 +57,8 @@ class ReadAttachmentsHandlerTest { private ReadAttachmentsHandler cut; private AttachmentService attachmentService; - private ItemModifierProvider provider; private AttachmentStatusValidator attachmentStatusValidator; private CdsReadEventContext readEventContext; - private Modifier modifier; - private ArgumentCaptor> fieldNamesArgumentCaptor; private AsyncMalwareScanExecutor asyncMalwareScanExecutor; @BeforeAll @@ -76,16 +69,11 @@ static void classSetup() { @BeforeEach void setup() { attachmentService = mock(AttachmentService.class); - provider = mock(ItemModifierProvider.class); attachmentStatusValidator = mock(AttachmentStatusValidator.class); asyncMalwareScanExecutor = mock(AsyncMalwareScanExecutor.class); - cut = new ReadAttachmentsHandler(attachmentService, provider, attachmentStatusValidator, asyncMalwareScanExecutor); + cut = new ReadAttachmentsHandler(attachmentService, attachmentStatusValidator, asyncMalwareScanExecutor); readEventContext = mock(CdsReadEventContext.class); - modifier = spy(new Modifier() { - }); - when(provider.getBeforeReadContentIdEnhancer(any())).thenReturn(modifier); - fieldNamesArgumentCaptor = ArgumentCaptor.forClass(List.class); } @Test @@ -94,11 +82,6 @@ void fieldNamesCorrectReadWithAssociations() { mockEventContext(RootTable_.CDS_NAME, select); cut.processBefore(readEventContext); - - verify(provider).getBeforeReadContentIdEnhancer(fieldNamesArgumentCaptor.capture()); - verify(modifier).items(any()); - var fields = fieldNamesArgumentCaptor.getValue(); - assertThat(fields).hasSize(2).contains("attachments").contains("itemAttachments"); } @Test @@ -107,11 +90,6 @@ void fieldNamesCorrectReadWithoutAssociations() { mockEventContext(Attachment_.CDS_NAME, select); cut.processBefore(readEventContext); - - verify(provider).getBeforeReadContentIdEnhancer(fieldNamesArgumentCaptor.capture()); - verify(modifier).items(any()); - var fields = fieldNamesArgumentCaptor.getValue(); - assertThat(fields).hasSize(1).contains(""); } @Test @@ -120,9 +98,6 @@ void noFieldNamesFound() { mockEventContext(EventItems_.CDS_NAME, select); cut.processBefore(readEventContext); - - verifyNoInteractions(provider); - verifyNoInteractions(modifier); } @Test diff --git a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/processor/modifyevents/MarkAsDeletedAttachmentEventTest.java b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/processor/modifyevents/MarkAsDeletedAttachmentEventTest.java index 8ab69889..4ce6fbc0 100644 --- a/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/processor/modifyevents/MarkAsDeletedAttachmentEventTest.java +++ b/cds-feature-attachments/src/test/java/com/sap/cds/feature/attachments/handler/applicationservice/processor/modifyevents/MarkAsDeletedAttachmentEventTest.java @@ -1,8 +1,13 @@ package com.sap.cds.feature.attachments.handler.applicationservice.processor.modifyevents; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; +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.io.ByteArrayInputStream; +import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; @@ -49,7 +54,7 @@ void setup() { @Test void documentIsExternallyDeleted() { - var value = "test"; + var value = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8)); var contentId = "some id"; var data = Attachments.create(); data.setContentId(contentId); @@ -69,7 +74,7 @@ void documentIsExternallyDeleted() { @Test void documentIsNotExternallyDeletedBecauseDoesNotExistBefore() { - var value = "test"; + var value = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8)); var data = Attachments.create(); var expectedValue = cut.processEvent(path, value, data, context); @@ -82,7 +87,7 @@ void documentIsNotExternallyDeletedBecauseDoesNotExistBefore() { @Test void documentIsNotExternallyDeletedBecauseItIsDraftChangeEvent() { - var value = "test"; + var value = new ByteArrayInputStream("test".getBytes(StandardCharsets.UTF_8)); var contentId = "some id"; var data = Attachments.create(); data.setContentId(contentId);