Skip to content

Commit cd4ee77

Browse files
Merge branch 'develop' into copyTests
2 parents a4a78c3 + 0617f5d commit cd4ee77

20 files changed

Lines changed: 878 additions & 114 deletions

README.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
1616
- Maximum allowed uploads: Provides the capability to define the maximum number of uploads allowed for the user.
1717
- Multiple attachment facets: Provides the capability to define multiple attachment facets/sections in the CAP Entity.
1818
- Technical user support: Provides the capability to consume the plugin using technical user.
19+
- Copy attachments: Provides the capability to copy attachments from one entity to another entity.
1920

2021
## Table of Contents
2122

@@ -28,6 +29,7 @@ This plugin can be consumed by the CAP application deployed on BTP to store thei
2829
- [Support for Maximum allowed uploads](#support-for-maximum-allowed-uploads)
2930
- [Support for Multiple attachment facets](#support-for-multiple-attachment-facets)
3031
- [Support for Technical user](#support-for-technical-user)
32+
- [Support for Copy attachments](#support-for-copy-attachments)
3133
- [Known Restrictions](#known-restrictions)
3234
- [Support, Feedback, Contributing](#support-feedback-contributing)
3335
- [Code of Conduct](#code-of-conduct)
@@ -314,10 +316,9 @@ Follow these steps if you want to integrate the SDM CAP Plugin with your own CAP
314316

315317
## Support for Multitenancy
316318

317-
318319
This plugin provides APIs for onboarding and offboarding of repositories for multitenant CAP SaaS applications.
319320

320-
GetDependencies,subscribe and unsubscribe are the mandatory steps to be performed to support multitenancy.
321+
GetDependencies, subscribe and unsubscribe are the mandatory steps to be performed to support multitenancy.
321322

322323
Refer the below example to pass the SDM Service dependencies to SaaSRegistry so that SDM credentials are passed to subscribing tenant.
323324
```java
@@ -514,6 +515,47 @@ request =
514515
.build();
515516
```
516517

518+
## Support for copy attachments
519+
520+
This plugin provides capability to copy attachments from one entity to another. This capability will copy attachments metadata on CAP as well as actual content on the SAP Document Management service repository. This feature can be used in following two ways.
521+
522+
1. **A helper method to copy attachments from one entity to another**
523+
524+
The `AttachmentService` instance can be used to call `copyAttachments` method. This method expects an object of `CopyAttachmentInput` which requires new entity's Id (`up__Id`), the `attachments facet name` and the `list of objectIds` corresponding to attachments that are to be copied.
525+
526+
Example usage:
527+
```java
528+
String up__ID = "123";
529+
List<String> objectIds = ["abc", "xyz"];
530+
String facet = "AdminService.Books.attachments" // Target facet. This can be usually obtained from context.getTarget().getQualifiedName()
531+
boolean isSystemUser = false;
532+
var copyEventInput =
533+
new CopyAttachmentInput(up__ID, facet, objectIds);
534+
attachmentService.copyAttachments(copyEventInput, isSystemUser);
535+
```
536+
2. **OData API to copy attachments from one entity to another**
537+
538+
You can also use an OData API call to trigger the copy operation.
539+
`AttachmentsService` endpoint URL can be used with suffix `/<Service_name>.copyAttachments` . This request expects the following request body:
540+
```json
541+
{
542+
"up__ID" : "<up__ID>", // ID of the new entity
543+
"objectIds" : "abc","xyz" // objectIds corresponding to attachments that are to be copied
544+
}
545+
```
546+
547+
Example usage:
548+
```
549+
HTTP Method: POST
550+
Request URL:
551+
<app_url>/odata/v4/<Service_Name>/<Entity_Name>(ID=<up__ID>,IsActiveEntity=false)/attachments/<Service_name>.copyAttachments
552+
Request Body:
553+
{
554+
"up__ID": "<up__ID>",
555+
"objectIds": "abc","xyz"
556+
}
557+
```
558+
517559
## Known Restrictions
518560

519561
- UI5 Version 1.135.0: This version causes error in upload of attachments.

sdm/pom.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,9 @@
559559
<exclude>
560560
com/sap/cds/sdm/caching/**
561561
</exclude>
562+
<exclude>
563+
com/sap/cds/sdm/service/handler/AttachmentCopyEventContext.class
564+
</exclude>
562565
</excludes>
563566
</configuration>
564567
<executions>

sdm/src/main/java/com/sap/cds/sdm/configuration/Registration.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
import com.sap.cds.sdm.persistence.DBQuery;
1111
import com.sap.cds.sdm.service.*;
1212
import com.sap.cds.sdm.service.handler.SDMAttachmentsServiceHandler;
13+
import com.sap.cds.sdm.service.handler.SDMCustomServiceHandler;
14+
import com.sap.cds.sdm.service.handler.SDMServiceGenericHandler;
15+
import com.sap.cds.services.draft.DraftService;
1316
import com.sap.cds.services.environment.CdsEnvironment;
1417
import com.sap.cds.services.environment.CdsProperties;
1518
import com.sap.cds.services.handler.EventHandler;
@@ -48,12 +51,19 @@ public void eventHandlers(CdsRuntimeConfigurer configurer) {
4851
.getCdsRuntime()
4952
.getServiceCatalog()
5053
.getService(PersistenceService.class, PersistenceService.DEFAULT_NAME);
54+
var attachmentService =
55+
configurer
56+
.getCdsRuntime()
57+
.getServiceCatalog()
58+
.getService(RegisterService.class, RegisterService.SDM_NAME);
5159
List<ServiceBinding> bindings =
5260
environment
5361
.getServiceBindings()
5462
.filter(b -> ServiceBindingUtils.matches(b, SDMConstants.SDM_ENV_NAME))
5563
.toList();
5664
var binding = !bindings.isEmpty() ? bindings.get(0) : null;
65+
List<DraftService> draftServiceList =
66+
configurer.getCdsRuntime().getServiceCatalog().getServices(DraftService.class).toList();
5767

5868
// get HTTP connection pool configuration
5969
var connectionPool = getConnectionPool(environment);
@@ -77,6 +87,9 @@ public void eventHandlers(CdsRuntimeConfigurer configurer) {
7787
documentService,
7888
tokenHandlerInstance,
7989
dbQueryInstance));
90+
configurer.eventHandler(new SDMServiceGenericHandler(attachmentService));
91+
configurer.eventHandler(
92+
new SDMCustomServiceHandler(sdmService, draftServiceList, tokenHandlerInstance));
8093
}
8194

8295
private AttachmentService buildAttachmentService() {

sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ private SDMConstants() {
6969
public static final String NAMED_USER_FLOW = "TOKEN_EXCHANGE";
7070
public static final String ANNOTATION_IS_MEDIA_DATA = "_is_media_data";
7171
public static final String DRAFT_READONLY_CONTEXT = "DRAFT_READONLY_CONTEXT";
72+
public static final String FAILED_TO_COPY_ATTACHMENT = "Failed to copy attachment";
73+
public static final String FAILED_TO_FETCH_UP_ID = "Failed to fetch up_id";
74+
public static final String FAILED_TO_FETCH_FACET =
75+
"Invalid facet format, unable to extract required information.";
7276

7377
public static String nameConstraintMessage(
7478
List<String> fileNameWithRestrictedCharacters, String operation) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package com.sap.cds.sdm.model;
2+
3+
import java.util.List;
4+
5+
/**
6+
* The class {@link CopyAttachmentInput} is used to store the input for creating an attachment.
7+
*
8+
* @param upId The keys for the attachment entity
9+
* @param facet
10+
* @param objectIds
11+
*/
12+
public record CopyAttachmentInput(String upId, String facet, List<String> objectIds) {}

sdm/src/main/java/com/sap/cds/sdm/service/DocumentUploadService.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public DocumentUploadService(
5050
* Implementation to create document.
5151
*/
5252
public JSONObject createDocument(
53-
CmisDocument cmisDocument, SDMCredentials sdmCredentials, Boolean isSystemUser)
53+
CmisDocument cmisDocument, SDMCredentials sdmCredentials, boolean isSystemUser)
5454
throws IOException {
5555
try {
5656
long totalSize = cmisDocument.getContentLength();
@@ -93,7 +93,7 @@ private void appendContentStream(
9393
int bytesRead,
9494
boolean isLastChunk,
9595
int chunkIndex,
96-
Boolean isSystemUser)
96+
boolean isSystemUser)
9797
throws IOException, ParseException {
9898

9999
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
@@ -132,7 +132,7 @@ private void appendContentStream(
132132
}
133133

134134
private JSONObject createEmptyDocument(
135-
CmisDocument cmisDocument, String sdmUrl, Boolean isSystemUser) {
135+
CmisDocument cmisDocument, String sdmUrl, boolean isSystemUser) {
136136

137137
MultipartEntityBuilder builder = MultipartEntityBuilder.create();
138138
builder.addTextBody("cmisaction", "createDocument");
@@ -157,7 +157,7 @@ private JSONObject createEmptyDocument(
157157
}
158158

159159
public JSONObject uploadSingleChunk(
160-
CmisDocument cmisDocument, SDMCredentials sdmCredentials, Boolean isSystemUser)
160+
CmisDocument cmisDocument, SDMCredentials sdmCredentials, boolean isSystemUser)
161161
throws IOException {
162162

163163
InputStream originalStream = cmisDocument.getContent();
@@ -194,7 +194,7 @@ public JSONObject uploadSingleChunk(
194194
}
195195

196196
private JSONObject uploadLargeFileInChunks(
197-
CmisDocument cmisDocument, String sdmUrl, int chunkSize, Boolean isSystemUser)
197+
CmisDocument cmisDocument, String sdmUrl, int chunkSize, boolean isSystemUser)
198198
throws IOException {
199199

200200
try (ReadAheadInputStream chunkedStream =
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
package com.sap.cds.sdm.service;
22

3+
import com.sap.cds.sdm.model.CopyAttachmentInput;
34
import com.sap.cds.services.Service;
45

56
public interface RegisterService extends Service {
67
String SDM_NAME = "SDMAttachmentService$Default";
8+
String EVENT_COPY_ATTACHMENT = "COPY_ATTACHMENT";
9+
10+
public void copyAttachments(CopyAttachmentInput input, boolean isSystemUser);
711
}

sdm/src/main/java/com/sap/cds/sdm/service/SDMAttachmentsService.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentReadEventContext;
1111
import com.sap.cds.feature.attachments.service.model.servicehandler.AttachmentRestoreEventContext;
1212
import com.sap.cds.feature.attachments.service.model.servicehandler.DeletionUserInfo;
13+
import com.sap.cds.sdm.model.CopyAttachmentInput;
14+
import com.sap.cds.sdm.service.handler.AttachmentCopyEventContext;
1315
import com.sap.cds.services.ServiceDelegator;
1416
import com.sap.cds.services.request.UserInfo;
1517
import java.io.InputStream;
@@ -25,6 +27,23 @@ public SDMAttachmentsService() {
2527
super(SDM_NAME);
2628
}
2729

30+
@Override
31+
public void copyAttachments(CopyAttachmentInput input, boolean isSystemUser) {
32+
logger.info(
33+
"Copying attachments for upId: {}, facet: {}, objectIds: {}, isSystemUser: {}",
34+
input.upId(),
35+
input.facet(),
36+
input.objectIds(),
37+
isSystemUser);
38+
var copyContext = AttachmentCopyEventContext.create();
39+
copyContext.setUpId(input.upId());
40+
copyContext.setFacet(input.facet());
41+
copyContext.setObjectIds(input.objectIds());
42+
copyContext.setSystemUser(isSystemUser);
43+
44+
emit(copyContext);
45+
}
46+
2847
@Override
2948
public InputStream readAttachment(String contentId) {
3049
logger.info("Reading attachment with document id: {}", contentId);

sdm/src/main/java/com/sap/cds/sdm/service/SDMService.java

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,15 @@ public JSONObject createDocument(
1616
CmisDocument cmisDocument, SDMCredentials sdmCredentials, String jwtToken) throws IOException;
1717

1818
public String createFolder(
19-
String parentId, String repositoryId, SDMCredentials sdmCredentials, Boolean isSystemUser)
19+
String parentId, String repositoryId, SDMCredentials sdmCredentials, boolean isSystemUser)
2020
throws IOException;
2121

2222
public String getFolderId(
23-
Result result, PersistenceService persistenceService, String upID, Boolean isSystemUser)
23+
Result result, PersistenceService persistenceService, String upID, boolean isSystemUser)
2424
throws IOException;
2525

2626
public String getFolderIdByPath(
27-
String parentId, String repositoryId, SDMCredentials sdmCredentials, Boolean isSystemUser)
27+
String parentId, String repositoryId, SDMCredentials sdmCredentials, boolean isSystemUser)
2828
throws IOException;
2929

3030
public String checkRepositoryType(String repositoryId, String tenant) throws IOException;
@@ -44,19 +44,23 @@ public int updateAttachments(
4444
CmisDocument cmisDocument,
4545
Map<String, String> secondaryProperties,
4646
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
47-
Boolean isSystemUser)
47+
boolean isSystemUser)
4848
throws ServiceException;
4949

50-
public String getObject(String objectId, SDMCredentials sdmCredentials, Boolean isSystemUser)
50+
public String getObject(String objectId, SDMCredentials sdmCredentials, boolean isSystemUser)
5151
throws IOException;
5252

5353
public List<String> getSecondaryTypes(
54-
String repositoryId, SDMCredentials sdmCredentials, Boolean isSystemUser) throws IOException;
54+
String repositoryId, SDMCredentials sdmCredentials, boolean isSystemUser) throws IOException;
5555

5656
public List<String> getValidSecondaryProperties(
5757
List<String> secondaryTypes,
5858
SDMCredentials sdmCredentials,
5959
String repositoryId,
60-
Boolean isSystemUser)
60+
boolean isSystemUser)
61+
throws IOException;
62+
63+
public List<String> copyAttachment(
64+
CmisDocument cmisDocument, SDMCredentials sdmCredentials, boolean isSystemUser)
6165
throws IOException;
6266
}

0 commit comments

Comments
 (0)