Skip to content

Commit 85e2798

Browse files
ATLAS-5156: Import failure due to missing support for handling multiple relationship types under a single attribute
1 parent 30244d7 commit 85e2798

2 files changed

Lines changed: 778 additions & 10 deletions

File tree

repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java

Lines changed: 100 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)