@@ -1506,21 +1506,19 @@ private void mapRelationshipAttributes(AtlasEntity entity, AtlasEntityType entit
15061506
15071507 if (op .equals (CREATE )) {
15081508 for (String attrName : entityType .getRelationshipAttributes ().keySet ()) {
1509- Object attrValue = entity .getRelationshipAttribute (attrName );
1510- String relationType = AtlasEntityUtil .getRelationshipType (attrValue );
1511- AtlasAttribute attribute = entityType .getRelationshipAttribute (attrName , relationType );
1512-
1513- mapAttribute (attribute , attrValue , vertex , op , context );
1509+ Object attrValue = entity .getRelationshipAttribute (attrName );
1510+ if (attrValue != null ) {
1511+ mapRelationshipAttributeWithMultipleTypes (entity , entityType , attrName , attrValue , vertex , op , context );
1512+ }
15141513 }
15151514 } else if (op .equals (UPDATE ) || op .equals (PARTIAL_UPDATE )) {
15161515 // relationship attributes mapping
15171516 for (String attrName : entityType .getRelationshipAttributes ().keySet ()) {
15181517 if (entity .hasRelationshipAttribute (attrName )) {
1519- Object attrValue = entity .getRelationshipAttribute (attrName );
1520- String relationType = AtlasEntityUtil .getRelationshipType (attrValue );
1521- AtlasAttribute attribute = entityType .getRelationshipAttribute (attrName , relationType );
1522-
1523- mapAttribute (attribute , attrValue , vertex , op , context );
1518+ Object attrValue = entity .getRelationshipAttribute (attrName );
1519+ if (attrValue != null ) {
1520+ mapRelationshipAttributeWithMultipleTypes (entity , entityType , attrName , attrValue , vertex , op , context );
1521+ }
15241522 }
15251523 }
15261524 }
@@ -1533,6 +1531,98 @@ private void mapRelationshipAttributes(AtlasEntity entity, AtlasEntityType entit
15331531 LOG .debug ("<== mapRelationshipAttributes({}, {})" , op , entity .getTypeName ());
15341532 }
15351533
1534+ private void mapRelationshipAttributeWithMultipleTypes (AtlasEntity entity , AtlasEntityType entityType , String attrName , Object attrValue , AtlasVertex vertex , EntityOperation op , EntityMutationContext context ) throws AtlasBaseException {
1535+ LOG .debug ("==> mapRelationshipAttributeWithMultipleTypes({}, {})" , attrName , entity .getTypeName ());
1536+ Set <String > relationshipTypeNames = entityType .getAttributeRelationshipTypes (attrName );
1537+
1538+ if (CollectionUtils .isEmpty (relationshipTypeNames )) {
1539+ // Fallback to single relationship type processing
1540+ String relationType = AtlasEntityUtil .getRelationshipType (attrValue );
1541+ AtlasAttribute attribute = entityType .getRelationshipAttribute (attrName , relationType );
1542+ mapAttribute (attribute , attrValue , vertex , op , context );
1543+
1544+ return ;
1545+ }
1546+
1547+ if (attrValue instanceof Collection ) {
1548+ Collection <?> relatedObjects = (Collection <?>) attrValue ;
1549+
1550+ // Group related objects by their appropriate relationship type
1551+ // e.g., hive_table elements should use hive_table_db relationship, anothertype_table elements should use anothertype_table_db
1552+ Map <String , List <Object >> elementsByRelationshipType = groupElementsByRelationshipType (
1553+ relatedObjects , attrName , relationshipTypeNames );
1554+
1555+ // Process each relationship type with its filtered elements
1556+ for (Map .Entry <String , List <Object >> entry : elementsByRelationshipType .entrySet ()) {
1557+ String relationshipTypeName = entry .getKey ();
1558+ List <Object > filteredElements = entry .getValue ();
1559+
1560+ AtlasAttribute attribute = entityType .getRelationshipAttribute (attrName , relationshipTypeName );
1561+
1562+ if (attribute != null && CollectionUtils .isNotEmpty (filteredElements )) {
1563+ // Use the same collection type as the original (List or Set)
1564+ Object filteredValue = createCollectionOfSameType (attrValue , filteredElements );
1565+
1566+ LOG .debug ("Processing relationship type {} for attribute {} with {} elements" ,
1567+ relationshipTypeName , attrName , filteredElements .size ());
1568+
1569+ mapAttribute (attribute , filteredValue , vertex , op , context );
1570+ }
1571+ }
1572+ } else {
1573+ // Single element - prefer explicit relationship type from the value
1574+ String appropriateRelType = AtlasEntityUtil .getRelationshipType (attrValue );
1575+ AtlasAttribute attribute = entityType .getRelationshipAttribute (attrName , appropriateRelType );
1576+ mapAttribute (attribute , attrValue , vertex , op , context );
1577+ }
1578+
1579+ LOG .debug ("<== mapRelationshipAttributeWithMultipleTypes({}, {})" , attrName , entity .getTypeName ());
1580+ }
1581+
1582+ private Map <String , List <Object >> groupElementsByRelationshipType (Collection <?> relatedObjects ,
1583+ String attrName ,
1584+ Set <String > relationshipTypeNames ) {
1585+ Map <String , List <Object >> elementsByRelationshipType = new HashMap <>();
1586+
1587+ // Group related objects by their appropriate relationship type
1588+ for (Object element : relatedObjects ) {
1589+ // Prefer the explicit relationship type encoded in the element, if any
1590+ String appropriateRelType = AtlasEntityUtil .getRelationshipType (element );
1591+
1592+ if (StringUtils .isEmpty (appropriateRelType )) {
1593+ // If only one relationship type is configured, fall back to it; otherwise, skip this element
1594+ if (relationshipTypeNames .size () == 1 ) {
1595+ appropriateRelType = relationshipTypeNames .iterator ().next ();
1596+ LOG .warn ("No relationshipType found in element for attribute {}; falling back to configured type {}" ,
1597+ attrName , appropriateRelType );
1598+ } else {
1599+ LOG .warn ("No relationshipType found in element for attribute {}; configured relationship types: {}. Skipping element." ,
1600+ attrName , relationshipTypeNames );
1601+ continue ;
1602+ }
1603+ } else if (!relationshipTypeNames .contains (appropriateRelType )) {
1604+ // Element's relationshipType is not configured for this attribute; ignore this element
1605+ LOG .warn ("relationshipType {} from element in attribute {} is not in configured relationship types {}; element will be ignored" ,
1606+ appropriateRelType , attrName , relationshipTypeNames );
1607+ continue ;
1608+ }
1609+
1610+ elementsByRelationshipType .computeIfAbsent (appropriateRelType , k -> new ArrayList <>()).add (element );
1611+ }
1612+
1613+ return elementsByRelationshipType ;
1614+ }
1615+
1616+ private Object createCollectionOfSameType (Object originalValue , List <Object > filteredElements ) {
1617+ if (originalValue instanceof List ) {
1618+ return filteredElements ;
1619+ } else if (originalValue instanceof Set ) {
1620+ return new HashSet <>(filteredElements );
1621+ } else {
1622+ return filteredElements ;
1623+ }
1624+ }
1625+
15361626 private void mapAttribute (AtlasAttribute attribute , Object attrValue , AtlasVertex vertex , EntityOperation op , EntityMutationContext context ) throws AtlasBaseException {
15371627 boolean isDeletedEntity = context .isDeletedEntity (vertex );
15381628 AtlasType attrType = attribute .getAttributeType ();
0 commit comments