This is an automated email from the ASF dual-hosted git repository.

mandarambawane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new 3f1338ceb ATLAS-5144: Export failure due to missing support for 
handling multiple relationship types under a single attribute (#593)
3f1338ceb is described below

commit 3f1338ceb7e3c1c8d321ce492189cd39d663813d
Author: sheetalshah1007 <[email protected]>
AuthorDate: Wed Jul 29 16:45:29 2026 +0530

    ATLAS-5144: Export failure due to missing support for handling multiple 
relationship types under a single attribute (#593)
---
 .../atlas/repository/impexp/ExportService.java     |   2 +-
 .../store/graph/v2/EntityGraphRetriever.java       | 156 ++++++++++++++++++++-
 2 files changed, 151 insertions(+), 7 deletions(-)

diff --git 
a/repository/src/main/java/org/apache/atlas/repository/impexp/ExportService.java
 
b/repository/src/main/java/org/apache/atlas/repository/impexp/ExportService.java
index 8ccc63c1b..74b055f20 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/impexp/ExportService.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/impexp/ExportService.java
@@ -79,7 +79,7 @@ public class ExportService {
     @Inject
     public ExportService(final AtlasTypeRegistry typeRegistry, AtlasGraph 
graph, AuditsWriter auditsWriter, HdfsPathEntityCreator hdfsPathEntityCreator, 
GlossaryService glossaryService) {
         this.typeRegistry                    = typeRegistry;
-        this.entityGraphRetriever            = new EntityGraphRetriever(graph, 
this.typeRegistry);
+        this.entityGraphRetriever            = new EntityGraphRetriever(graph, 
this.typeRegistry, false, true);
         this.auditsWriter                    = auditsWriter;
         this.hdfsPathEntityCreator           = hdfsPathEntityCreator;
         this.glossaryService                 = glossaryService;
diff --git 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
index 1043589b1..ffd5296b0 100644
--- 
a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
+++ 
b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphRetriever.java
@@ -170,17 +170,27 @@ public class EntityGraphRetriever {
     private final AtlasTypeRegistry typeRegistry;
     private final boolean           ignoreRelationshipAttr;
     private final AtlasGraph        graph;
+    private final  boolean processMultipleRelationshipTypes;
 
     @Inject
     public EntityGraphRetriever(AtlasGraph graph, AtlasTypeRegistry 
typeRegistry) {
-        this(graph, typeRegistry, false);
+        this(graph, typeRegistry, false, false);
     }
 
     public EntityGraphRetriever(AtlasGraph graph, AtlasTypeRegistry 
typeRegistry, boolean ignoreRelationshipAttr) {
-        this.graph                  = graph;
-        this.graphHelper            = new GraphHelper(graph);
-        this.typeRegistry           = typeRegistry;
-        this.ignoreRelationshipAttr = ignoreRelationshipAttr;
+        this(graph, typeRegistry, ignoreRelationshipAttr, false);
+    }
+
+    public EntityGraphRetriever(AtlasGraph graph, AtlasTypeRegistry 
typeRegistry, boolean ignoreRelationshipAttr, boolean 
processMultipleRelationshipTypes) {
+        this.graph                            = graph;
+        this.graphHelper                      = new GraphHelper(graph);
+        this.typeRegistry                     = typeRegistry;
+        this.ignoreRelationshipAttr           = ignoreRelationshipAttr;
+        this.processMultipleRelationshipTypes = 
processMultipleRelationshipTypes;
+    }
+
+    public boolean isProcessMultipleRelationshipTypes() {
+        return processMultipleRelationshipTypes;
     }
 
     public static Object mapVertexToPrimitive(AtlasElement entityVertex, final 
String vertexPropertyName, AtlasAttributeDef attrDef) {
@@ -1415,7 +1425,11 @@ public class EntityGraphRetriever {
         }
 
         for (String attributeName : 
entityType.getRelationshipAttributes().keySet()) {
-            mapVertexToRelationshipAttribute(entityVertex, entityType, 
attributeName, entity, entityExtInfo, isMinExtInfo);
+            if (isProcessMultipleRelationshipTypes()) {
+                
mapVertexToRelationshipAttributeWithMultipleTypes(entityVertex, entityType, 
attributeName, entity, entityExtInfo, isMinExtInfo);
+            } else {
+                mapVertexToRelationshipAttribute(entityVertex, entityType, 
attributeName, entity, entityExtInfo, isMinExtInfo);
+            }
         }
     }
 
@@ -1467,6 +1481,136 @@ public class EntityGraphRetriever {
         return ret;
     }
 
+    private Object 
mapVertexToRelationshipAttributeWithMultipleTypes(AtlasVertex entityVertex, 
AtlasEntityType entityType, String attributeName, AtlasEntity entity, 
AtlasEntityExtInfo entityExtInfo, boolean isMinExtInfo) throws 
AtlasBaseException {
+        Object      ret                   = null;
+        Set<String> relationshipTypeNames = 
entityType.getAttributeRelationshipTypes(attributeName);
+
+        if (CollectionUtils.isEmpty(relationshipTypeNames)) {
+            throw new 
AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID, "relationshipDef is 
null");
+        }
+
+        ret = mapMultipleRelationshipTypes(entityVertex, entityType, 
attributeName, relationshipTypeNames, entityExtInfo, isMinExtInfo);
+
+        entity.setRelationshipAttribute(attributeName, ret);
+
+        // Handle legacy attributes for the first relationship type found
+        if (!relationshipTypeNames.isEmpty()) {
+            String                firstRelationshipTypeName = 
relationshipTypeNames.iterator().next();
+            AtlasRelationshipType firstRelationshipType     = 
typeRegistry.getRelationshipTypeByName(firstRelationshipTypeName);
+            if (firstRelationshipType != null) {
+                AtlasAttribute attribute = 
entityType.getRelationshipAttribute(attributeName, firstRelationshipTypeName);
+                if (attribute != null) {
+                    AtlasRelationshipEndDef attributeEndDef = 
getAttributeEndDefFromRelationshipType(firstRelationshipType, entityType, 
attributeName);
+
+                    if (attributeEndDef != null && 
attributeEndDef.getIsLegacyAttribute() && !entity.hasAttribute(attributeName)) {
+                        entity.setAttribute(attributeName, 
toLegacyAttribute(ret));
+                    }
+                }
+            }
+        }
+
+        return ret;
+    }
+
+    private AtlasRelationshipEndDef 
getAttributeEndDefFromRelationshipType(AtlasRelationshipType relationshipType, 
AtlasEntityType entityType, String attributeName) {
+        if (relationshipType == null) {
+            return null;
+        }
+
+        AtlasRelationshipDef    relationshipDef = 
relationshipType.getRelationshipDef();
+        AtlasRelationshipEndDef endDef1         = relationshipDef.getEndDef1();
+        AtlasRelationshipEndDef endDef2         = relationshipDef.getEndDef2();
+        AtlasEntityType         endDef1Type     = 
typeRegistry.getEntityTypeByName(endDef1.getType());
+        AtlasEntityType         endDef2Type     = 
typeRegistry.getEntityTypeByName(endDef2.getType());
+
+        if (endDef1Type.isTypeOrSuperTypeOf(entityType.getTypeName()) && 
StringUtils.equals(endDef1.getName(), attributeName)) {
+            return endDef1;
+        } else if (endDef2Type.isTypeOrSuperTypeOf(entityType.getTypeName()) 
&& StringUtils.equals(endDef2.getName(), attributeName)) {
+            return endDef2;
+        }
+
+        return null;
+    }
+
+    private Object mapMultipleRelationshipTypes(AtlasVertex entityVertex, 
AtlasEntityType entityType, String attributeName, Set<String> 
relationshipTypeNames, AtlasEntityExtInfo entityExtInfo, boolean isMinExtInfo) 
throws AtlasBaseException {
+        List<Object> allResults            = new ArrayList<>();
+        boolean      hasSingleCardinality  = false;
+        boolean      hasListSetCardinality = false;
+
+        for (String relationshipTypeName : relationshipTypeNames) {
+            try {
+                AtlasRelationshipType relationshipType = 
typeRegistry.getRelationshipTypeByName(relationshipTypeName);
+                if (relationshipType == null) {
+                    continue;
+                }
+
+                AtlasAttribute attribute = 
entityType.getRelationshipAttribute(attributeName, relationshipTypeName);
+                if (attribute == null) {
+                    continue;
+                }
+
+                AtlasRelationshipEndDef attributeEndDef = 
getAttributeEndDefFromRelationshipType(relationshipType, entityType, 
attributeName);
+                if (attributeEndDef == null) {
+                    continue;
+                }
+
+                Object result = null;
+                switch (attributeEndDef.getCardinality()) {
+                    case SINGLE:
+                        hasSingleCardinality = true;
+                        result = mapRelatedVertexToObjectId(entityVertex, 
attribute, entityExtInfo, isMinExtInfo);
+                        break;
+
+                    case LIST:
+                    case SET:
+                        hasListSetCardinality = true;
+                        result = mapRelationshipArrayAttribute(entityVertex, 
attribute, entityExtInfo, isMinExtInfo);
+                        break;
+                }
+
+                if (result != null) {
+                    allResults.add(result);
+                }
+            } catch (Exception e) {
+                LOG.warn("Error processing relationship type {}: {}", 
relationshipTypeName, e.getMessage());
+            }
+        }
+
+        // Combine results based on cardinality
+        if (hasSingleCardinality && hasListSetCardinality) {
+            // Mixed cardinalities - combine into a list
+            List<Object> combinedResults = new ArrayList<>();
+            for (Object result : allResults) {
+                if (result instanceof Collection) {
+                    combinedResults.addAll((Collection<?>) result);
+                } else {
+                    combinedResults.add(result);
+                }
+            }
+            return combinedResults;
+        } else if (hasListSetCardinality) {
+            // All are list/set cardinalities - combine all collections
+            List<Object> combinedResults = new ArrayList<>();
+            for (Object result : allResults) {
+                if (result instanceof Collection) {
+                    combinedResults.addAll((Collection<?>) result);
+                } else {
+                    combinedResults.add(result);
+                }
+            }
+            return combinedResults;
+        } else if (hasSingleCardinality) {
+            // All are single cardinalities - return the first non-null result
+            for (Object result : allResults) {
+                if (result != null) {
+                    return result;
+                }
+            }
+        }
+
+        return null;
+    }
+
     private Object toLegacyAttribute(Object obj) {
         final Object ret;
 

Reply via email to