Skip to content

Commit 2fb5bf8

Browse files
fix copy attachment with invalid properties
1 parent 8b29824 commit 2fb5bf8

4 files changed

Lines changed: 147 additions & 19 deletions

File tree

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ private SDMErrorMessages() {
142142
"Invalid secondary properties detected: ";
143143
public static final String INVALID_SECONDARY_PROPERTIES_FOR_MOVE_SUFFIX =
144144
". Attachment rolled back to source.";
145+
public static final String INVALID_SECONDARY_PROPERTIES_FOR_COPY_PREFIX =
146+
"Invalid secondary properties detected: ";
147+
public static final String INVALID_SECONDARY_PROPERTIES_FOR_COPY_SUFFIX =
148+
". Attachment not copied.";
145149
public static final String SDM_MOVE_OPERATION_FAILED = "SDM move operation failed";
146150
public static final String FAILED_TO_ACCESS_ERROR_KEY_FIELDS =
147151
"Failed to access SDM error key fields";

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ private SDMUIErrorKeys() {}
8787
"SDM.invalidSecondaryPropertiesForMovePrefix";
8888
public static final String INVALID_SECONDARY_PROPERTIES_FOR_MOVE_SUFFIX_KEY =
8989
"SDM.invalidSecondaryPropertiesForMoveSuffix";
90+
public static final String INVALID_SECONDARY_PROPERTIES_FOR_COPY_PREFIX_KEY =
91+
"SDM.invalidSecondaryPropertiesForCopyPrefix";
92+
public static final String INVALID_SECONDARY_PROPERTIES_FOR_COPY_SUFFIX_KEY =
93+
"SDM.invalidSecondaryPropertiesForCopySuffix";
9094
public static final String MAX_COUNT_ERROR_MESSAGE_KEY = "SDM.maxCountErrorMessage";
9195

9296
public static Map<String, Object> getAllUIErrorKeys() {

sdm/src/main/java/com/sap/cds/sdm/model/CopyAttachmentsResult.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
11
package com.sap.cds.sdm.model;
22

3+
import java.util.ArrayList;
34
import java.util.List;
45
import java.util.Map;
56

67
/** Result class for copyAttachmentsToSDM method. */
78
public class CopyAttachmentsResult {
89
private final List<Map<String, String>> attachmentsMetadata;
910
private final List<CmisDocument> populatedDocuments;
11+
private final List<Map<String, String>> failedAttachments;
1012

1113
public CopyAttachmentsResult(
1214
List<Map<String, String>> attachmentsMetadata, List<CmisDocument> populatedDocuments) {
15+
this(attachmentsMetadata, populatedDocuments, new ArrayList<>());
16+
}
17+
18+
public CopyAttachmentsResult(
19+
List<Map<String, String>> attachmentsMetadata,
20+
List<CmisDocument> populatedDocuments,
21+
List<Map<String, String>> failedAttachments) {
1322
this.attachmentsMetadata = attachmentsMetadata;
1423
this.populatedDocuments = populatedDocuments;
24+
this.failedAttachments = failedAttachments;
1525
}
1626

1727
public List<Map<String, String>> getAttachmentsMetadata() {
@@ -21,4 +31,8 @@ public List<Map<String, String>> getAttachmentsMetadata() {
2131
public List<CmisDocument> getPopulatedDocuments() {
2232
return populatedDocuments;
2333
}
34+
35+
public List<Map<String, String>> getFailedAttachments() {
36+
return failedAttachments;
37+
}
2438
}

sdm/src/main/java/com/sap/cds/sdm/service/handler/SDMCustomServiceHandler.java

Lines changed: 125 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -150,25 +150,55 @@ public void copyAttachments(AttachmentCopyEventContext context) throws IOExcepti
150150

151151
List<Map<String, String>> attachmentsMetadata = copyResult.getAttachmentsMetadata();
152152
List<CmisDocument> populatedDocuments = copyResult.getPopulatedDocuments();
153+
List<Map<String, String>> copyFailures = copyResult.getFailedAttachments();
153154

154-
String upIdKey = resolveUpIdKey(context, parentEntity, compositionName);
155+
// Show warning if there are failures
156+
if (!copyFailures.isEmpty()) {
157+
StringBuilder warningMessage =
158+
new StringBuilder("Failed to copy the following attachments:\n");
159+
for (Map<String, String> failure : copyFailures) {
160+
warningMessage
161+
.append(" - ObjectId: ")
162+
.append(failure.get(OBJECT_ID_KEY))
163+
.append(", Reason: ")
164+
.append(failure.get(FAILURE_REASON_KEY))
165+
.append("\n");
166+
}
167+
context.getMessages().warn(warningMessage.toString());
168+
}
155169

156-
CreateDraftEntriesRequest draftRequest =
157-
CreateDraftEntriesRequest.builder()
158-
.attachmentsMetadata(attachmentsMetadata)
159-
.populatedDocuments(populatedDocuments)
160-
.parentEntity(parentEntity)
161-
.compositionName(compositionName)
162-
.upID(upID)
163-
.upIdKey(upIdKey)
164-
.repositoryId(repositoryId)
165-
.folderId(folderId)
166-
.customPropertyValues(null)
167-
.build();
170+
String upIdKey = resolveUpIdKey(context, parentEntity, compositionName);
168171

169-
// Pass the entity for type conversion
170-
CdsEntity targetEntity = entity.isPresent() ? entity.get() : null;
171-
createDraftEntries(draftRequest, customPropertyDefinitions, targetEntity);
172+
// Create draft entries if there are successful copies
173+
if (!attachmentsMetadata.isEmpty()) {
174+
CreateDraftEntriesRequest draftRequest =
175+
CreateDraftEntriesRequest.builder()
176+
.attachmentsMetadata(attachmentsMetadata)
177+
.populatedDocuments(populatedDocuments)
178+
.parentEntity(parentEntity)
179+
.compositionName(compositionName)
180+
.upID(upID)
181+
.upIdKey(upIdKey)
182+
.repositoryId(repositoryId)
183+
.folderId(folderId)
184+
.customPropertyValues(null)
185+
.build();
186+
187+
// Pass the entity for type conversion
188+
CdsEntity targetEntity = entity.isPresent() ? entity.get() : null;
189+
createDraftEntries(draftRequest, customPropertyDefinitions, targetEntity);
190+
} else if (!folderExists) {
191+
// All copies failed but folder was newly created - delete the empty folder
192+
logger.info(
193+
"All attachments failed to copy. Deleting newly created empty folder: {}", folderId);
194+
try {
195+
sdmService.deleteDocument(
196+
"deleteTree", folderId, context.getUserInfo().getName(), isSystemUser);
197+
logger.info("Deleted empty folder: {}", folderId);
198+
} catch (Exception e) {
199+
logger.error("Failed to delete empty folder {}: {}", folderId, e.getMessage());
200+
}
201+
}
172202

173203
logger.info(
174204
"Copy attachments completed - {} attachments copied for upID: {}",
@@ -570,6 +600,33 @@ private CopyAttachmentsResult copyAttachmentsToSDM(
570600
logger.debug("START: Copy {} attachments to SDM", request.getObjectIds().size());
571601
List<Map<String, String>> attachmentsMetadata = new ArrayList<>();
572602
List<CmisDocument> populatedDocuments = new ArrayList<>();
603+
List<Map<String, String>> failedAttachments = new ArrayList<>();
604+
605+
// Fetch valid secondary properties for validation
606+
List<String> validSecondaryProperties = new ArrayList<>();
607+
boolean shouldValidateSecondaryProperties = false;
608+
if (!customPropertiesInSDM.isEmpty()) {
609+
try {
610+
List<String> secondaryTypes =
611+
sdmService.getSecondaryTypes(
612+
request.getRepositoryId(), request.getSdmCredentials(), request.getIsSystemUser());
613+
validSecondaryProperties =
614+
sdmService.getValidSecondaryProperties(
615+
secondaryTypes,
616+
request.getSdmCredentials(),
617+
request.getRepositoryId(),
618+
request.getIsSystemUser());
619+
shouldValidateSecondaryProperties = true;
620+
logger.debug(
621+
"Fetched {} valid secondary properties for copy validation",
622+
validSecondaryProperties.size());
623+
} catch (Exception e) {
624+
logger.warn(
625+
"Failed to fetch valid secondary properties for copy validation: {}. "
626+
+ "Proceeding without validation.",
627+
e.getMessage());
628+
}
629+
}
573630

574631
for (String objectId : request.getObjectIds()) {
575632
logger.debug("Processing copy for objectId: {}", objectId);
@@ -584,7 +641,6 @@ private CopyAttachmentsResult copyAttachmentsToSDM(
584641
populatedDocument.setType(cmisDocument.getType());
585642
populatedDocument.setUrl(cmisDocument.getUrl());
586643
populatedDocument.setUploadStatus(cmisDocument.getUploadStatus());
587-
populatedDocuments.add(populatedDocument);
588644

589645
try {
590646
Map<String, String> attachmentData =
@@ -594,6 +650,53 @@ private CopyAttachmentsResult copyAttachmentsToSDM(
594650
request.getIsSystemUser(),
595651
customPropertiesInSDM);
596652

653+
// Validate secondary properties after copy (similar to move validation)
654+
// Only validate if we successfully fetched valid secondary properties
655+
List<String> invalidProperties = new ArrayList<>();
656+
if (shouldValidateSecondaryProperties) {
657+
for (String customProp : customPropertiesInSDM) {
658+
if (attachmentData.containsKey(customProp)
659+
&& !validSecondaryProperties.contains(customProp)) {
660+
invalidProperties.add(customProp);
661+
}
662+
}
663+
}
664+
665+
if (!invalidProperties.isEmpty()) {
666+
// Validation failed - delete the copied attachment and record failure
667+
String copiedObjectId = attachmentData.get("cmis:objectId");
668+
logger.error(
669+
"Attachment {} validation FAILED - Found {} invalid properties: {}. "
670+
+ "Deleting copied attachment...",
671+
objectId,
672+
invalidProperties.size(),
673+
invalidProperties);
674+
try {
675+
sdmService.deleteDocument(
676+
"delete",
677+
copiedObjectId,
678+
request.getContext().getUserInfo().getName(),
679+
request.getIsSystemUser());
680+
logger.info("Deleted invalid copied attachment: {}", copiedObjectId);
681+
} catch (Exception deleteEx) {
682+
logger.error(
683+
"Failed to delete invalid copied attachment {}: {}",
684+
copiedObjectId,
685+
deleteEx.getMessage());
686+
}
687+
// Add to failed attachments list instead of throwing exception
688+
Map<String, String> failure = new HashMap<>();
689+
failure.put(OBJECT_ID_KEY, objectId);
690+
failure.put(
691+
FAILURE_REASON_KEY,
692+
SDMUtils.getErrorMessage("INVALID_SECONDARY_PROPERTIES_FOR_COPY_PREFIX")
693+
+ String.join(", ", invalidProperties)
694+
+ SDMUtils.getErrorMessage("INVALID_SECONDARY_PROPERTIES_FOR_COPY_SUFFIX"));
695+
failedAttachments.add(failure);
696+
continue;
697+
}
698+
699+
populatedDocuments.add(populatedDocument);
597700
attachmentsMetadata.add(attachmentData);
598701
logger.debug("Successfully copied attachment: {}", objectId);
599702
} catch (ServiceException e) {
@@ -607,8 +710,11 @@ private CopyAttachmentsResult copyAttachmentsToSDM(
607710
}
608711
}
609712

610-
logger.debug("END: Copy attachments to SDM - {} successful", attachmentsMetadata.size());
611-
return new CopyAttachmentsResult(attachmentsMetadata, populatedDocuments);
713+
logger.debug(
714+
"END: Copy attachments to SDM - {} successful, {} failed",
715+
attachmentsMetadata.size(),
716+
failedAttachments.size());
717+
return new CopyAttachmentsResult(attachmentsMetadata, populatedDocuments, failedAttachments);
612718
}
613719

614720
/**

0 commit comments

Comments
 (0)