@@ -102,9 +102,7 @@ private static void processDirectAttachmentComposition(
102102 : null ;
103103
104104 if (isDirectAttachmentTargetAspect (targetAspect )) {
105- String serviceName = entity .getQualifiedName ().split ("\\ ." )[0 ];
106- String entityName = entity .getName ();
107- String directPath = serviceName + "." + entityName + "." + compositionName ;
105+ String directPath = entity .getQualifiedName () + "." + compositionName ;
108106 pathMapping .put (directPath , directPath );
109107 }
110108 }
@@ -165,7 +163,9 @@ private static void processAttachmentPaths(
165163 String entityPath = buildEntityPath (entity , targetEntity , attachmentPath );
166164 String actualPath = buildActualPath (entity , compositionName , attachmentPath );
167165
168- if (entityPath != null && actualPath != null ) {
166+ // Only add the mapping if both paths are non-null and the key doesn't already exist
167+ // This preserves direct attachment mappings from being overwritten by nested ones
168+ if (entityPath != null && actualPath != null && !pathMapping .containsKey (entityPath )) {
169169 pathMapping .put (entityPath , actualPath );
170170 }
171171 }
@@ -219,17 +219,20 @@ private static String buildEntityPath(
219219 try {
220220 String [] pathParts = attachmentPath .split ("\\ ." );
221221 if (pathParts .length >= 3 ) {
222- // Get the service name (first part)
223- String serviceName = pathParts [0 ];
224-
225- // Get the target entity name (without service prefix)
226- String targetEntityName = targetEntity .getName ();
227-
228222 // Get the attachment part (last part)
229223 String attachmentPart = pathParts [pathParts .length - 1 ];
230224
231- // Build the entity path: ServiceName.EntityName.attachments
232- return serviceName + "." + targetEntityName + "." + attachmentPart ;
225+ // For nested compositions, use the full target entity path to ensure uniqueness
226+ // For direct attachments on the parent entity, the targetEntity equals parentEntity
227+ String entityPath ;
228+ if (targetEntity .getQualifiedName ().equals (parentEntity .getQualifiedName ())) {
229+ // Direct attachment: use parent entity path
230+ entityPath = parentEntity .getQualifiedName () + "." + attachmentPart ;
231+ } else {
232+ // Nested attachment: use target entity path to ensure uniqueness
233+ entityPath = targetEntity .getQualifiedName () + "." + attachmentPart ;
234+ }
235+ return entityPath ;
233236 }
234237 } catch (Exception e ) {
235238 logger .warn (SDMConstants .FETCH_ATTACHMENT_COMPOSITION_ERROR , e .getMessage ());
@@ -242,15 +245,15 @@ private static String buildActualPath(
242245 try {
243246 String [] pathParts = attachmentPath .split ("\\ ." );
244247 if (pathParts .length >= 3 ) {
245- // Get the service name (first part)
246- String serviceName = pathParts [0 ];
247-
248- // Replace the entity name with the composition property name
249- // Keep the attachment part (last part)
248+ // Get the attachment part (last part)
250249 String attachmentPart = pathParts [pathParts .length - 1 ];
251250
252- // Build the new path: ServiceName.compositionPropertyName.attachments
253- return serviceName + "." + compositionPropertyName + "." + attachmentPart ;
251+ // Build the new path using parent entity qualified name + composition property name
252+ return parentEntity .getQualifiedName ()
253+ + "."
254+ + compositionPropertyName
255+ + "."
256+ + attachmentPart ;
254257 }
255258 } catch (Exception e ) {
256259 logger .warn (SDMConstants .FETCH_ATTACHMENT_COMPOSITION_ERROR , e .getMessage ());
0 commit comments