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
7 changes: 7 additions & 0 deletions sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ private SDMConstants() {
public static final String FAILED_TO_FETCH_UP_ID = "Failed to fetch up_id";
public static final String FAILED_TO_FETCH_FACET =
"Invalid facet format, unable to extract required information.";
public static final String PARENT_ENTITY_NOT_FOUND_ERROR = "Unable to find parent entity: %s";
public static final String COMPOSITION_NOT_FOUND_ERROR =
"Unable to find composition '%s' in entity: %s";
public static final String TARGET_ATTACHMENT_ENTITY_NOT_FOUND_ERROR =
"Unable to find target attachment entity: %s";
public static final String INVALID_FACET_FORMAT_ERROR =
"Invalid facet format. Expected: Service.Entity.Composition, got: %s";

public static String nameConstraintMessage(
List<String> fileNameWithRestrictedCharacters, String operation) {
Expand Down
10 changes: 6 additions & 4 deletions sdm/src/main/java/com/sap/cds/sdm/model/CopyAttachmentInput.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
import java.util.List;

/**
* The class {@link CopyAttachmentInput} is used to store the input for creating an attachment.
* The class {@link CopyAttachmentInput} is used to store the input for copying attachments. This
* model supports both regular entities and projection entities by using facet-based navigation.
*
* @param upId The keys for the attachment entity
* @param facet
* @param objectIds
* @param upId The key of the parent entity instance
* @param facet The full facet path (e.g., "Service.Entity.composition") that will be internally
* parsed to determine parent entity and composition name
* @param objectIds The list of attachment object IDs to be copied
*/
public record CopyAttachmentInput(String upId, String facet, List<String> objectIds) {}
110 changes: 110 additions & 0 deletions sdm/src/main/java/com/sap/cds/sdm/model/CopyAttachmentsRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package com.sap.cds.sdm.model;

import com.sap.cds.sdm.service.handler.AttachmentCopyEventContext;
import java.util.List;

/**
* Parameter object for copyAttachmentsToSDM method to reduce parameter count and improve code
* maintainability.
*/
public class CopyAttachmentsRequest {
private final AttachmentCopyEventContext context;
private final List<String> objectIds;
private final String folderId;
private final String repositoryId;
private final SDMCredentials sdmCredentials;
private final Boolean isSystemUser;
private final boolean folderExists;

private CopyAttachmentsRequest(Builder builder) {
this.context = builder.context;
this.objectIds = builder.objectIds;
this.folderId = builder.folderId;
this.repositoryId = builder.repositoryId;
this.sdmCredentials = builder.sdmCredentials;
this.isSystemUser = builder.isSystemUser;
this.folderExists = builder.folderExists;
}

// Getters
public AttachmentCopyEventContext getContext() {
return context;
}

public List<String> getObjectIds() {
return objectIds;
}

public String getFolderId() {
return folderId;
}

public String getRepositoryId() {
return repositoryId;
}

public SDMCredentials getSdmCredentials() {
return sdmCredentials;
}

public Boolean getIsSystemUser() {
return isSystemUser;
}

public boolean isFolderExists() {
return folderExists;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private AttachmentCopyEventContext context;
private List<String> objectIds;
private String folderId;
private String repositoryId;
private SDMCredentials sdmCredentials;
private Boolean isSystemUser;
private boolean folderExists;

public Builder context(AttachmentCopyEventContext context) {
this.context = context;
return this;
}

public Builder objectIds(List<String> objectIds) {
this.objectIds = objectIds;
return this;
}

public Builder folderId(String folderId) {
this.folderId = folderId;
return this;
}

public Builder repositoryId(String repositoryId) {
this.repositoryId = repositoryId;
return this;
}

public Builder sdmCredentials(SDMCredentials sdmCredentials) {
this.sdmCredentials = sdmCredentials;
return this;
}

public Builder isSystemUser(Boolean isSystemUser) {
this.isSystemUser = isSystemUser;
return this;
}

public Builder folderExists(boolean folderExists) {
this.folderExists = folderExists;
return this;
}

public CopyAttachmentsRequest build() {
return new CopyAttachmentsRequest(this);
}
}
}
121 changes: 121 additions & 0 deletions sdm/src/main/java/com/sap/cds/sdm/model/CreateDraftEntriesRequest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package com.sap.cds.sdm.model;

import java.util.List;

/**
* Parameter object for createDraftEntries method to reduce parameter count and improve code
* maintainability.
*/
public class CreateDraftEntriesRequest {
private final List<List<String>> attachmentsMetadata;
private final List<CmisDocument> populatedDocuments;
private final String parentEntity;
private final String compositionName;
private final String upID;
private final String upIdKey;
private final String repositoryId;
private final String folderId;

private CreateDraftEntriesRequest(Builder builder) {
this.attachmentsMetadata = builder.attachmentsMetadata;
this.populatedDocuments = builder.populatedDocuments;
this.parentEntity = builder.parentEntity;
this.compositionName = builder.compositionName;
this.upID = builder.upID;
this.upIdKey = builder.upIdKey;
this.repositoryId = builder.repositoryId;
this.folderId = builder.folderId;
}

// Getters
public List<List<String>> getAttachmentsMetadata() {
return attachmentsMetadata;
}

public List<CmisDocument> getPopulatedDocuments() {
return populatedDocuments;
}

public String getParentEntity() {
return parentEntity;
}

public String getCompositionName() {
return compositionName;
}

public String getUpID() {
return upID;
}

public String getUpIdKey() {
return upIdKey;
}

public String getRepositoryId() {
return repositoryId;
}

public String getFolderId() {
return folderId;
}

public static Builder builder() {
return new Builder();
}

public static class Builder {
private List<List<String>> attachmentsMetadata;
private List<CmisDocument> populatedDocuments;
private String parentEntity;
private String compositionName;
private String upID;
private String upIdKey;
private String repositoryId;
private String folderId;

public Builder attachmentsMetadata(List<List<String>> attachmentsMetadata) {
this.attachmentsMetadata = attachmentsMetadata;
return this;
}

public Builder populatedDocuments(List<CmisDocument> populatedDocuments) {
this.populatedDocuments = populatedDocuments;
return this;
}

public Builder parentEntity(String parentEntity) {
this.parentEntity = parentEntity;
return this;
}

public Builder compositionName(String compositionName) {
this.compositionName = compositionName;
return this;
}

public Builder upID(String upID) {
this.upID = upID;
return this;
}

public Builder upIdKey(String upIdKey) {
this.upIdKey = upIdKey;
return this;
}

public Builder repositoryId(String repositoryId) {
this.repositoryId = repositoryId;
return this;
}

public Builder folderId(String folderId) {
this.folderId = folderId;
return this;
}

public CreateDraftEntriesRequest build() {
return new CreateDraftEntriesRequest(this);
}
}
}
63 changes: 51 additions & 12 deletions sdm/src/main/java/com/sap/cds/sdm/persistence/DBQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@
import com.sap.cds.ql.Update;
import com.sap.cds.ql.cqn.CqnSelect;
import com.sap.cds.ql.cqn.CqnUpdate;
import com.sap.cds.reflect.CdsAssociationType;
import com.sap.cds.reflect.CdsElement;
import com.sap.cds.reflect.CdsEntity;
import com.sap.cds.reflect.CdsModel;
import com.sap.cds.sdm.constants.SDMConstants;
import com.sap.cds.sdm.model.CmisDocument;
import com.sap.cds.sdm.service.handler.AttachmentCopyEventContext;
import com.sap.cds.services.ServiceException;
import com.sap.cds.services.persistence.PersistenceService;
import java.util.*;

Expand Down Expand Up @@ -65,31 +69,66 @@ public CmisDocument getObjectIdForAttachmentID(

public CmisDocument getAttachmentForObjectID(
PersistenceService persistenceService, String id, AttachmentCopyEventContext context) {
Optional<CdsEntity> attachmentEntity = context.getModel().findEntity(context.getFacet());

// Use the new API to resolve the target attachment entity
String parentEntity = context.getParentEntity();
String compositionName = context.getCompositionName();
CdsModel model = context.getModel();

// Find the parent entity
Optional<CdsEntity> optionalParentEntity = model.findEntity(parentEntity);
if (optionalParentEntity.isEmpty()) {
throw new ServiceException(
String.format(SDMConstants.PARENT_ENTITY_NOT_FOUND_ERROR, parentEntity));
}

// Find the composition element in the parent entity
Optional<CdsElement> compositionElement =
optionalParentEntity.get().findElement(compositionName);
if (compositionElement.isEmpty() || !compositionElement.get().getType().isAssociation()) {
throw new ServiceException(
String.format(SDMConstants.COMPOSITION_NOT_FOUND_ERROR, compositionName, parentEntity));
}

// Get the target entity of the composition
CdsAssociationType assocType = (CdsAssociationType) compositionElement.get().getType();
String targetEntityName = assocType.getTarget().getQualifiedName();

// Find the target attachment entity
Optional<CdsEntity> attachmentEntity = model.findEntity(targetEntityName);
if (attachmentEntity.isEmpty()) {
throw new ServiceException(
String.format(SDMConstants.TARGET_ATTACHMENT_ENTITY_NOT_FOUND_ERROR, targetEntityName));
}

// Search in active entity first
CqnSelect q =
Select.from(attachmentEntity.get())
.columns("linkUrl", "type")
.where(doc -> doc.get("objectId").eq(id));
Result result = persistenceService.run(q);
Optional<Row> res = result.first();

CmisDocument cmisDocument = new CmisDocument();
if (res.isPresent()) {
Row row = res.get();
cmisDocument.setType(row.get("type") != null ? row.get("type").toString() : null);
cmisDocument.setUrl(row.get("linkUrl") != null ? row.get("linkUrl").toString() : null);
} else {
// Check in draft table as well
attachmentEntity = context.getModel().findEntity(context.getFacet() + "_drafts");
q =
Select.from(attachmentEntity.get())
.columns("linkUrl", "type")
.where(doc -> doc.get("objectId").eq(id));
result = persistenceService.run(q);
res = result.first();
if (res.isPresent()) {
Row row = res.get();
cmisDocument.setType(row.get("type") != null ? row.get("type").toString() : null);
cmisDocument.setUrl(row.get("linkUrl") != null ? row.get("linkUrl").toString() : null);
Optional<CdsEntity> attachmentDraftEntity = model.findEntity(targetEntityName + "_drafts");
if (attachmentDraftEntity.isPresent()) {
q =
Select.from(attachmentDraftEntity.get())
.columns("linkUrl", "type")
.where(doc -> doc.get("objectId").eq(id));
result = persistenceService.run(q);
res = result.first();
if (res.isPresent()) {
Row row = res.get();
cmisDocument.setType(row.get("type") != null ? row.get("type").toString() : null);
cmisDocument.setUrl(row.get("linkUrl") != null ? row.get("linkUrl").toString() : null);
}
}
}
return cmisDocument;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,13 @@ public interface RegisterService extends Service {
String SDM_NAME = "SDMAttachmentService$Default";
String EVENT_COPY_ATTACHMENT = "COPY_ATTACHMENT";

/**
* Copies attachments using the facet-based approach. This method supports both regular entities
* and projection entities by internally parsing the facet to determine parent entity and
* composition name.
*
* @param input The copy attachment input containing facet and object IDs
* @param isSystemUser Whether to use system user flow
*/
public void copyAttachments(CopyAttachmentInput input, boolean isSystemUser);
}
Loading
Loading