Skip to content
Open
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
2 changes: 1 addition & 1 deletion sdm/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

<properties>
<packageName>sdm</packageName>
<cds.install-cdsdk.version>7.6.0</cds.install-cdsdk.version>
<cds.install-cdsdk.version>8.9.8</cds.install-cdsdk.version>
<generation-package>com.sap.cds.sdm.generated</generation-package>
<test-generation-folder>src/test/gen</test-generation-folder>
<maven.compiler.source>17</maven.compiler.source>
Expand Down
39 changes: 24 additions & 15 deletions sdm/src/main/java/com/sap/cds/sdm/constants/SDMConstants.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.sap.cds.sdm.constants;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SDMConstants {
private SDMConstants() {
Expand Down Expand Up @@ -81,25 +83,32 @@ 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 FILENAME_WHITESPACE_WARNING_MESSAGE =
"The file name cannot be empty or consist entirely of space characters. Enter a value.";

public static String nameConstraintMessage(
List<String> fileNameWithRestrictedCharacters, String operation) {
// Create the base message
String prefixMessage =
"%s unsuccessful. The following filename(s) contain unsupported characters (/, \\). \n\n";
// Helper Methods to create error/warning messages
public static String buildErrorMessage(
Collection<String> filenames, String operation, String prefixTemplate) {
String closingRemark = "Rename the files and try again.";
StringBuilder message = new StringBuilder(String.format(prefixTemplate, operation));

// Create the formatted prefix message
String formattedPrefixMessage = String.format(prefixMessage, operation);
for (String file : filenames) {
message.append(String.format("\t• %s%n", file));
}
message.append("\n ").append(closingRemark);
return message.toString();
}

// Initialize the StringBuilder with the formatted message prefix
StringBuilder bulletPoints = new StringBuilder(formattedPrefixMessage);
public static String nameConstraintMessage(List<String> invalidFileNames, String operation) {
String prefix =
"%s unsuccessful. The following filename(s) contain unsupported characters (/, \\). \n\n";
return buildErrorMessage(invalidFileNames, operation, prefix);
}

// Append each unsupported file name to the StringBuilder
for (String file : fileNameWithRestrictedCharacters) {
bulletPoints.append(String.format("\t• %s%n", file));
}
bulletPoints.append("\nRename the files and try again.");
return bulletPoints.toString();
public static String duplicateFilenameFormat(Set<String> duplicateFileNames, String operation) {
String prefix =
"%s unsuccessful. The following filename(s) have been added multiple times. \n\n";
return buildErrorMessage(duplicateFileNames, operation, prefix);
}

public static String linkNameConstraintMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,15 +62,15 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
throws IOException {
Map<String, String> propertyTitles = new HashMap<>();
Map<String, String> secondaryPropertiesWithInvalidDefinitions = new HashMap<>();
Set<String> duplicateFilenames = SDMUtils.isFileNameDuplicateInDrafts(data, composition);
if (!duplicateFilenames.isEmpty()) {
handleDuplicateFilenames(context, duplicateFilenames);
} else {
Boolean isError = false;
isError = SDMUtils.validateFileName(context, data, composition, "Create");
if (!isError) {
List<String> fileNameWithRestrictedCharacters = new ArrayList<>();
List<String> duplicateFileNameList = new ArrayList<>();
List<String> filesNotFound = new ArrayList<>();
List<String> filesWithUnsupportedProperties = new ArrayList<>();
Map<String, String> badRequest = new HashMap<>();
List<String> fileWithWhiteSpace = new ArrayList<>();
List<String> noSDMRoles = new ArrayList<>();
for (Map<String, Object> entity : data) {
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
Expand All @@ -95,7 +95,8 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
composition,
attachmentEntity,
secondaryPropertiesWithInvalidDefinitions,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
handleWarnings(
context,
fileNameWithRestrictedCharacters,
Expand All @@ -104,7 +105,8 @@ public void updateName(CdsCreateEventContext context, List<CdsData> data, String
filesWithUnsupportedProperties,
badRequest,
propertyTitles,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
}
}
}
Expand All @@ -130,7 +132,8 @@ private void processEntity(
String composition,
Optional<CdsEntity> attachmentEntity,
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
List<String> noSDMRoles)
List<String> noSDMRoles,
List<String> fileWithWhiteSpace)
throws IOException {
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
if (attachments != null) {
Expand All @@ -146,7 +149,8 @@ private void processEntity(
composition,
attachmentEntity,
secondaryPropertiesWithInvalidDefinitions,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
}
SecondaryPropertiesKey secondaryPropertiesKey =
new SecondaryPropertiesKey(); // Emptying cache after attachments are updated in loop
Expand All @@ -166,7 +170,8 @@ private void processAttachment(
String composition,
Optional<CdsEntity> attachmentEntity,
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
List<String> noSDMRoles)
List<String> noSDMRoles,
List<String> fileWithWhiteSpace)
throws IOException {
String id = (String) attachment.get("ID");
String fileNameInDB;
Expand Down Expand Up @@ -224,14 +229,17 @@ private void processAttachment(
if (fileNameInDB
== null) { // If the file name in DB is null, it means that the file is being created for
// the first time
if (filenameInRequest != null) {
if (filenameInRequest != null && !filenameInRequest.isBlank()) {
updatedSecondaryProperties.put("filename", filenameInRequest);
} else {
throw new ServiceException("Filename cannot be empty");
}
} else {
if (filenameInRequest == null) {
throw new ServiceException("Filename cannot be empty");
if (filenameInRequest == null || filenameInRequest.trim().length() == 0) {
fileWithWhiteSpace.add(fileNameInDB);
replacePropertiesInAttachment(
attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties);

} else if (!fileNameInDB.equals(
filenameInRequest)) { // If the file name in DB is not equal to the file name in
// request, it means that the file name has been modified
Expand Down Expand Up @@ -322,7 +330,8 @@ private void handleWarnings(
List<String> filesWithUnsupportedProperties,
Map<String, String> badRequest,
Map<String, String> propertyTitles,
List<String> noSDMRoles) {
List<String> noSDMRoles,
List<String> fileWithWhiteSpace) {
if (!fileNameWithRestrictedCharacters.isEmpty()) {
context
.getMessages()
Expand Down Expand Up @@ -363,6 +372,14 @@ private void handleWarnings(
if (!noSDMRoles.isEmpty()) {
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "create"));
}
if (!fileWithWhiteSpace.isEmpty()) {
context
.getMessages()
.warn(
String.format(
SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE,
String.join(", ", fileWithWhiteSpace)));
}
}

private List<String> getEntityCompositions(CdsCreateEventContext context) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,9 @@ public void processBefore(CdsUpdateEventContext context, List<CdsData> data) thr

public void updateName(CdsUpdateEventContext context, List<CdsData> data, String composition)
throws IOException {
Set<String> duplicateFilenames = SDMUtils.isFileNameDuplicateInDrafts(data, composition);
if (!duplicateFilenames.isEmpty()) {
context
.getMessages()
.error(
String.format(
SDMConstants.DUPLICATE_FILE_IN_DRAFT_ERROR_MESSAGE,
String.join(", ", duplicateFilenames)));
} else {
Boolean isError = false;
isError = SDMUtils.validateFileName(context, data, composition, "Update");
if (!isError) {
Optional<CdsEntity> attachmentEntity =
context.getModel().findEntity(context.getTarget().getQualifiedName() + "." + composition);
renameDocument(attachmentEntity, context, data, composition);
Expand All @@ -83,6 +77,7 @@ private void renameDocument(
Map<String, String> badRequest = new HashMap<>();
Map<String, String> propertyTitles = new HashMap<>();
List<String> noSDMRoles = new ArrayList<>();
List<String> fileWithWhiteSpace = new ArrayList<>();
for (Map<String, Object> entity : data) {
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
if (attachments != null && !attachments.isEmpty()) {
Expand All @@ -109,7 +104,8 @@ private void renameDocument(
filesWithUnsupportedProperties,
badRequest,
secondaryPropertiesWithInvalidDefinitions,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
}
}
handleWarnings(
Expand All @@ -120,7 +116,8 @@ private void renameDocument(
filesWithUnsupportedProperties,
badRequest,
propertyTitles,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
}

private void processAttachments(
Expand All @@ -133,7 +130,8 @@ private void processAttachments(
List<String> filesWithUnsupportedProperties,
Map<String, String> badRequest,
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
List<String> noSDMRoles)
List<String> noSDMRoles,
List<String> fileWithWhiteSpace)
throws IOException {
Iterator<Map<String, Object>> iterator = attachments.iterator();
while (iterator.hasNext()) {
Expand All @@ -148,7 +146,8 @@ private void processAttachments(
filesWithUnsupportedProperties,
badRequest,
secondaryPropertiesWithInvalidDefinitions,
noSDMRoles);
noSDMRoles,
fileWithWhiteSpace);
}
SecondaryPropertiesKey secondaryPropertiesKey = new SecondaryPropertiesKey();
secondaryPropertiesKey.setRepositoryId(SDMConstants.REPOSITORY_ID);
Expand All @@ -168,7 +167,8 @@ public void processAttachment(
List<String> filesWithUnsupportedProperties,
Map<String, String> badRequest,
Map<String, String> secondaryPropertiesWithInvalidDefinitions,
List<String> noSDMRoles)
List<String> noSDMRoles,
List<String> fileWithWhiteSpace)
throws IOException {
String id = (String) attachment.get("ID");
Map<String, String> secondaryTypeProperties =
Expand Down Expand Up @@ -222,8 +222,10 @@ public void processAttachment(
throw new ServiceException("Filename cannot be empty");
}
} else {
if (filenameInRequest == null) {
throw new ServiceException("Filename cannot be empty");
if (filenameInRequest == null || filenameInRequest.trim().length() == 0) {
fileWithWhiteSpace.add(fileNameInDB);
replacePropertiesInAttachment(
attachment, fileNameInDB, propertiesInDB, secondaryTypeProperties);
} else if (!fileNameInDB.equals(filenameInRequest)) {
updatedSecondaryProperties.put("filename", filenameInRequest);
}
Expand Down Expand Up @@ -313,7 +315,8 @@ private void handleWarnings(
List<String> filesWithUnsupportedProperties,
Map<String, String> badRequest,
Map<String, String> propertyTitles,
List<String> noSDMRoles) {
List<String> noSDMRoles,
List<String> fileWithWhiteSpace) {
if (!fileNameWithRestrictedCharacters.isEmpty()) {
context
.getMessages()
Expand Down Expand Up @@ -353,6 +356,14 @@ private void handleWarnings(
if (!noSDMRoles.isEmpty()) {
context.getMessages().warn(SDMConstants.noSDMRolesMessage(noSDMRoles, "update"));
}
if (!fileWithWhiteSpace.isEmpty()) {
context
.getMessages()
.warn(
String.format(
SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE,
String.join(", ", fileWithWhiteSpace)));
}
}

private List<String> getEntityCompositions(CdsUpdateEventContext context) {
Expand Down
61 changes: 57 additions & 4 deletions sdm/src/main/java/com/sap/cds/sdm/utilities/SDMUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.sap.cds.sdm.caching.CacheConfig;
import com.sap.cds.sdm.constants.SDMConstants;
import com.sap.cds.sdm.model.AttachmentInfo;
import com.sap.cds.services.EventContext;
import com.sap.cds.services.persistence.PersistenceService;
import java.io.IOException;
import java.util.ArrayList;
Expand All @@ -32,6 +33,53 @@ private SDMUtils() {
// Doesn't do anything
}

public static Boolean validateFileName(
EventContext context, List<CdsData> data, String composition, String operation) {
Boolean isError = false;

// Validation for file names
Set<String> whitespaceFilenames = isFileNameContainsWhitespace(data, composition);
List<String> restrictedFileNames = isFileNameContainsRestrictedCharaters(data);
Set<String> duplicateFilenames = isFileNameDuplicateInDrafts(data, composition);

// Collecting all the errors
if (whitespaceFilenames != null && !whitespaceFilenames.isEmpty()) {
context.getMessages().error(SDMConstants.FILENAME_WHITESPACE_WARNING_MESSAGE);
isError = true;
}
if (restrictedFileNames != null && !restrictedFileNames.isEmpty()) {
context
.getMessages()
.error(SDMConstants.nameConstraintMessage(restrictedFileNames, operation));
isError = true;
}
if (duplicateFilenames != null && !duplicateFilenames.isEmpty()) {
String formattedMessage =
String.format(SDMConstants.duplicateFilenameFormat(duplicateFilenames, operation));
context.getMessages().error(formattedMessage);
}
// returning the error message
return isError;
}

public static Set<String> isFileNameContainsWhitespace(List<CdsData> data, String composition) {
Set<String> filenamesWithWhitespace = new HashSet<>();
for (Map<String, Object> entity : data) {
List<Map<String, Object>> attachments = (List<Map<String, Object>>) entity.get(composition);
if (attachments != null) {
Iterator<Map<String, Object>> iterator = attachments.iterator();
while (iterator.hasNext()) {
Map<String, Object> attachment = iterator.next();
String filenameInRequest = (String) attachment.get("fileName");
if (filenameInRequest == null || filenameInRequest.isBlank()) {
filenamesWithWhitespace.add("Whitespace/null");
}
}
}
}
return filenamesWithWhitespace;
}

public static Set<String> isFileNameDuplicateInDrafts(List<CdsData> data, String composition) {
Set<String> uniqueFilenames = new HashSet<>();
Set<String> duplicateFilenames = new HashSet<>();
Expand All @@ -42,10 +90,12 @@ public static Set<String> isFileNameDuplicateInDrafts(List<CdsData> data, String
while (iterator.hasNext()) {
Map<String, Object> attachment = iterator.next();
String filenameInRequest = (String) attachment.get("fileName");
String repositoryInRequest = (String) attachment.get("repositoryId");
String fileRepositorySpecific = filenameInRequest + "#" + repositoryInRequest;
if (!uniqueFilenames.add(fileRepositorySpecific)) {
duplicateFilenames.add(filenameInRequest);
if (filenameInRequest != null && !filenameInRequest.isBlank()) {
String repositoryInRequest = (String) attachment.get("repositoryId");
String fileRepositorySpecific = filenameInRequest + "#" + repositoryInRequest;
if (!uniqueFilenames.add(fileRepositorySpecific)) {
duplicateFilenames.add(filenameInRequest);
}
}
}
}
Expand All @@ -72,6 +122,9 @@ public static List<String> isFileNameContainsRestrictedCharaters(List<CdsData> d
}

public static boolean isRestrictedCharactersInName(String cmisName) {
if (cmisName == null || cmisName.isBlank()) {
return false;
}
String regex = "[/\\\\]";
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(cmisName);
Expand Down
Loading
Loading