Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
This commit is contained in:
Abhishek Kumar 2026-06-17 10:39:36 +05:30
parent dbad2e5646
commit 5a4c449cca
2 changed files with 103 additions and 1 deletions

View File

@ -129,12 +129,14 @@ public class ResponseMessageResolver {
if (MapUtils.isNotEmpty(metadata)) {
for (Map.Entry<String, Object> entry : metadata.entrySet()) {
Object value = entry.getValue();
stringMap.put(entry.getKey(), getMetadataObjectStringValue(value));
stringMap.put(entry.getKey(), getMetadataObjectStringValueAlt(value));
}
}
return stringMap;
}
/**
* Converts a metadata object to a human-readable string for error messages.
*
@ -212,6 +214,39 @@ public class ResponseMessageResolver {
return sb.toString();
}
/**
* Converts a metadata object to a human-readable string, prioritizing toString().
*
* <p>Behavior:
* <ul>
* <li>If {@code obj} is {@code null}, returns {@code null}.</li>
* <li>First attempts to use {@code obj.toString()}. If the result is non-empty, returns it.</li>
* <li>For non-root admins, removes any "id: DBID" patterns from the toString() result.</li>
* <li>If {@code obj.toString()} is empty or null (after filtering), falls back to {@link #getMetadataObjectStringValue(Object)},
* which uses reflection to find display names and format metadata with UUID/ID info.</li>
* </ul>
*
* @param obj metadata object
* @return formatted metadata string suitable for inclusion in error messages, or {@code null}
* if {@code obj} is {@code null}
*/
protected static String getMetadataObjectStringValueAlt(Object obj) {
if (obj == null) {
return null;
}
String result = obj.toString();
if (StringUtils.isNotEmpty(result)) {
// Remove id: DBID pattern for non-root admins
if (!CallContext.current().isCallingAccountRootAdmin()) {
result = result.replaceAll("\\bid:\\s*\\d+", "").trim();
}
if (StringUtils.isNotEmpty(result)) {
return result;
}
}
return getMetadataObjectStringValue(obj);
}
protected static String invokeStringGetter(Object obj, String methodName) {
try {
Class<?> cls = obj.getClass();

View File

@ -441,6 +441,73 @@ public class ResponseMessageResolverTest {
Assert.assertEquals(Map.of("field", "value"), response.getErrorMetadata());
}
@Test
public void getMetadataObjectStringValueAlt_shouldReturnNullWhenObjectIsNull() {
Assert.assertNull(ResponseMessageResolver.getMetadataObjectStringValueAlt(null));
}
@Test
public void getMetadataObjectStringValueAlt_shouldReturnToStringWhenNonEmptyForRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(true);
Object obj = new Object() {
@Override public String toString() { return "SomeObject id: 42"; }
};
Assert.assertEquals("SomeObject id: 42", ResponseMessageResolver.getMetadataObjectStringValueAlt(obj));
}
@Test
public void getMetadataObjectStringValueAlt_shouldStripIdPatternForNonRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(false);
Object obj = new Object() {
@Override public String toString() { return "SomeObject id: 42"; }
};
Assert.assertEquals("SomeObject", ResponseMessageResolver.getMetadataObjectStringValueAlt(obj));
}
@Test
public void getMetadataObjectStringValueAlt_shouldStripMultipleIdPatternsForNonRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(false);
Object obj = new Object() {
@Override public String toString() { return "id: 1 SomeObject id: 42"; }
};
Assert.assertEquals("SomeObject", ResponseMessageResolver.getMetadataObjectStringValueAlt(obj));
}
@Test
public void getMetadataObjectStringValueAlt_shouldReturnToStringUnchangedWhenNoIdPatternForNonRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(false);
Object obj = new Object() {
@Override public String toString() { return "SomeObjectWithoutId"; }
};
Assert.assertEquals("SomeObjectWithoutId", ResponseMessageResolver.getMetadataObjectStringValueAlt(obj));
}
@Test
public void getMetadataObjectStringValueAlt_shouldFallbackToGetMetadataObjectStringValueWhenToStringIsEmpty() {
Identity identityMock = Mockito.mock(Identity.class);
when(identityMock.toString()).thenReturn("");
when(identityMock.getUuid()).thenReturn("uuid-fallback");
Assert.assertEquals("uuid-fallback", ResponseMessageResolver.getMetadataObjectStringValueAlt(identityMock));
}
@Test
public void getMetadataObjectStringValueAlt_shouldFallbackWhenToStringBecomesBlankAfterStrippingIdForNonRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(false);
DataCenter dataCenterMock = Mockito.mock(DataCenter.class);
when(dataCenterMock.toString()).thenReturn("id: 99");
when(dataCenterMock.getName()).thenReturn("FallbackName");
Assert.assertEquals("'FallbackName'", ResponseMessageResolver.getMetadataObjectStringValueAlt(dataCenterMock));
}
@Test
public void getMetadataObjectStringValueAlt_shouldPreserveIdInToStringForRootAdmin() {
when(callContextMock.isCallingAccountRootAdmin()).thenReturn(true);
Object obj = new Object() {
@Override public String toString() { return "Zone [id: 7, name: TestZone]"; }
};
Assert.assertEquals("Zone [id: 7, name: TestZone]", ResponseMessageResolver.getMetadataObjectStringValueAlt(obj));
}
@Test
public void updateExceptionResponse_shouldHandleNullMetadata() {
ExceptionResponse response = new ExceptionResponse();