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 eff7880f4 ATLAS-4576 Backward compatibility for check provided for 
AttributeName in Parent and Child TypeDef
eff7880f4 is described below

commit eff7880f4528b3eecf4940f62fbe515d933e836b
Author: Mandar Ambawane <mandar.ambaw...@freestoneinfotech.com>
AuthorDate: Fri Jan 6 16:03:04 2023 +0530

    ATLAS-4576 Backward compatibility for check provided for AttributeName in 
Parent and Child TypeDef
    
    Signed-off-by: Mandar Ambawane <mandar.ambaw...@freestoneinfotech.com>
---
 distro/src/conf/atlas-application.properties       |   4 +
 .../apache/atlas/type/AtlasClassificationType.java |  10 +-
 .../org/apache/atlas/type/AtlasEntityType.java     |   7 +-
 .../org/apache/atlas/type/AtlasStructType.java     |  28 ++--
 .../atlas/type/TestAtlasClassificationType.java    | 168 ++++++++++++++++++++
 .../org/apache/atlas/type/TestAtlasEntityType.java | 171 ++++++++++++++++++++-
 6 files changed, 371 insertions(+), 17 deletions(-)

diff --git a/distro/src/conf/atlas-application.properties 
b/distro/src/conf/atlas-application.properties
index c92c619c9..b5734d7a8 100755
--- a/distro/src/conf/atlas-application.properties
+++ b/distro/src/conf/atlas-application.properties
@@ -278,3 +278,7 @@ atlas.search.gremlin.enable=false
 #########  UI Configuration ########
 
 #atlas.ui.default.version=v2
+
+######### Skip check for the same attribute name in Parent type and Child type 
#########
+
+#atlas.skip.check.for.parent.child.attribute.name=true
\ No newline at end of file
diff --git 
a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java 
b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
index 17422cf95..f8b66c4d0 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
@@ -31,6 +31,8 @@ import 
org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.commons.validator.routines.DateValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.util.*;
 
@@ -38,6 +40,7 @@ import java.util.*;
  * class that implements behaviour of a classification-type.
  */
 public class AtlasClassificationType extends AtlasStructType {
+    private static final Logger LOG = 
LoggerFactory.getLogger(AtlasClassificationType.class);
 
     public  static final AtlasClassificationType CLASSIFICATION_ROOT      = 
initRootClassificationType();
     private static final String                  CLASSIFICATION_ROOT_NAME = 
"__CLASSIFICATION_ROOT";
@@ -130,7 +133,6 @@ public class AtlasClassificationType extends 
AtlasStructType {
     @Override
     void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws 
AtlasBaseException {
         super.resolveReferencesPhase2(typeRegistry);
-        ensureNoAttributeOverride(superTypes);
 
         for (AtlasClassificationType superType : superTypes) {
             superType.addSubType(this);
@@ -562,7 +564,11 @@ public class AtlasClassificationType extends 
AtlasStructType {
                 String attributeName    = attributeDef.getName();
 
                 if 
(attributeToClassificationNameMap.containsKey(attributeName) && 
!attributeToClassificationNameMap.get(attributeName).equals(classificationDef.getName()))
 {
-                    throw new 
AtlasBaseException(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE,
 classificationDef.getName(), attributeName, 
attributeToClassificationNameMap.get(attributeName));
+                    if (skipCheckForParentChildAttributeName) {
+                        
LOG.warn(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getFormattedErrorMessage(classificationDef.getName(),
 attributeName, attributeToClassificationNameMap.get(attributeName)));
+                    } else {
+                        throw new 
AtlasBaseException(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE,
 classificationDef.getName(), attributeName, 
attributeToClassificationNameMap.get(attributeName));
+                    }
                 }
 
                 allAttributes.put(attributeName, new AtlasAttribute(this, 
attributeDef, type));
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java 
b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
index 76bee36f2..60e57a379 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
@@ -213,7 +213,6 @@ public class AtlasEntityType extends AtlasStructType {
     @Override
     void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws 
AtlasBaseException {
         super.resolveReferencesPhase2(typeRegistry);
-        ensureNoAttributeOverride(superTypes);
 
         for (AtlasEntityType superType : superTypes) {
             superType.addSubType(this);
@@ -885,7 +884,11 @@ public class AtlasEntityType extends AtlasStructType {
                 String    attributeName = attributeDef.getName();
 
                 if (attributeToEntityNameMap.containsKey(attributeName) && 
!attributeToEntityNameMap.get(attributeName).equals(entityDef.getName())) {
-                    throw new 
AtlasBaseException(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE,
 entityDef.getName(), attributeName, 
attributeToEntityNameMap.get(attributeName));
+                    if (skipCheckForParentChildAttributeName) {
+                        
LOG.warn(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getFormattedErrorMessage(entityDef.getName(),
 attributeName, attributeToEntityNameMap.get(attributeName)));
+                    } else {
+                        throw new 
AtlasBaseException(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE,
 entityDef.getName(), attributeName, 
attributeToEntityNameMap.get(attributeName));
+                    }
                 }
 
                 allAttributes.put(attributeName, new AtlasAttribute(this, 
attributeDef, type));
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java 
b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
index 21ce23657..591b31612 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
@@ -17,18 +17,19 @@
  */
 package org.apache.atlas.type;
 
+import org.apache.atlas.ApplicationProperties;
 import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.AtlasException;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.instance.AtlasEntity;
 import org.apache.atlas.model.instance.AtlasStruct;
-import org.apache.atlas.model.typedef.AtlasClassificationDef;
-import org.apache.atlas.model.typedef.AtlasEntityDef;
 import org.apache.atlas.model.typedef.AtlasStructDef;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
 import 
org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
+import org.apache.commons.configuration.Configuration;
 import org.apache.commons.lang.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -52,6 +53,19 @@ public class AtlasStructType extends AtlasType {
     protected Map<String, AtlasAttribute> allAttributes  = 
Collections.emptyMap();
     protected Map<String, AtlasAttribute> uniqAttributes = 
Collections.emptyMap();
 
+    protected static boolean skipCheckForParentChildAttributeName;
+    private static Configuration configuration;
+    private static String SKIP_CHECK_FOR_PARENT_CHILD_ATTRIBUTE_NAME = 
"atlas.skip.check.for.parent.child.attribute.name";
+
+    static {
+        try {
+            configuration = ApplicationProperties.get();
+        } catch (AtlasException e) {
+            throw new RuntimeException(e);
+        }
+        skipCheckForParentChildAttributeName = 
configuration.getBoolean(SKIP_CHECK_FOR_PARENT_CHILD_ATTRIBUTE_NAME, false);
+    }
+
     public AtlasStructType(AtlasStructDef structDef) {
         super(structDef);
 
@@ -720,16 +734,6 @@ public class AtlasStructType extends AtlasType {
         return ret;
     }
 
-    protected void ensureNoAttributeOverride(List<? extends AtlasStructType> 
superTypes) throws AtlasBaseException {
-        for (AtlasStructType superType : superTypes) {
-            for (AtlasAttributeDef attributeDef : 
this.structDef.getAttributeDefs()) {
-                if 
(superType.getAllAttributes().containsKey(attributeDef.getName())) {
-                    throw new 
AtlasBaseException(AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_PARENT_TYPE, 
getStructDef().getName(), attributeDef.getName(), 
superType.getStructDef().getName());
-                }
-            }
-        }
-    }
-
     public static class AtlasAttribute {
         public static final Object VERTEX_PROPERTY_PREFIX_STRING_INDEX_TYPE = 
"__s_";
         private final AtlasStructType          definedInType;
diff --git 
a/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java 
b/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java
index b6055fa30..3fb821b56 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java
@@ -19,6 +19,7 @@ package org.apache.atlas.type;
 
 import java.util.*;
 
+import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.ModelTestUtil;
 import org.apache.atlas.model.TimeBoundary;
@@ -26,6 +27,7 @@ import org.apache.atlas.model.instance.AtlasClassification;
 import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
 import org.apache.atlas.model.typedef.AtlasClassificationDef;
 import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
 import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
 import org.testng.annotations.Test;
 
@@ -343,4 +345,170 @@ public class TestAtlasClassificationType {
         assertFalse(isValidTimeZone("GMT+13:60")); // minutes 00-59 only
 
     }
+
+    @Test
+    public void testInvalidAttributeNameForSubtype() throws AtlasBaseException 
{
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild), 
Collections.singleton("classificationDefParent"));
+        try {
+            ttr.addType(classificationDefChild);
+            fail("Parent attribute name and Child attribute name should not be 
the same");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeUpdate() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild));
+        ttr.addType(classificationDefChild);
+
+        Set<String> superTypes = classificationDefChild.getSuperTypes();
+        assertEquals(superTypes.size(), 0);
+
+        superTypes.add(classificationDefParent.getName());
+        classificationDefChild.setSuperTypes(superTypes);
+
+        try {
+            ttr.updateType(classificationDefChild);
+            fail("Parent attribute name and Child attribute name should not be 
the same");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeForMultipleParents() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent2 = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent2 = new 
AtlasClassificationDef("classificationDefParent2", "classificationDefParent2 
desc", null, Collections.singletonList(attrDefForClassificationDefParent2));
+        ttr.addType(classificationDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        Set<String> superTypes = new HashSet<>();
+        superTypes.add("classificationDefParent");
+        superTypes.add("classificationDefParent2");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild), superTypes);
+
+        try {
+            ttr.addType(classificationDefChild);
+            fail("Child type cannot have two Parent types having same 
attribute names");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeForMultipleParents_Update() 
throws AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent2 = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent2 = new 
AtlasClassificationDef("classificationDefParent2", "classificationDefParent2 
desc", null, Collections.singletonList(attrDefForClassificationDefParent2));
+        ttr.addType(classificationDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild), 
Collections.singleton("classificationDefParent"));
+        ttr.addType(classificationDefChild);
+
+        Set<String> superTypes = classificationDefChild.getSuperTypes();
+        assertEquals(superTypes.size(), 1);
+
+        superTypes.add(classificationDefParent2.getName());
+        classificationDefChild.setSuperTypes(superTypes);
+        try {
+            ttr.updateType(classificationDefChild);
+            fail("Child type cannot have two Parent types having same 
attribute names");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testSkipInvalidAttributeNameForSubtype() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+        AtlasStructType.skipCheckForParentChildAttributeName = true;
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild), 
Collections.singleton("classificationDefParent"));
+
+        try {
+            ttr.addType(classificationDefChild);
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+            fail("Parent attribute name and Child attribute name should be 
allowed to be the same when skip-check flag is true");
+        } finally {
+            AtlasStructType.skipCheckForParentChildAttributeName = false;
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testSkipInvalidAttributeNameForSubtypeForMultipleParents() 
throws AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+        AtlasStructType.skipCheckForParentChildAttributeName = true;
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent = new 
AtlasClassificationDef("classificationDefParent", "classificationDefParent 
desc", null, Collections.singletonList(attrDefForClassificationDefParent));
+        ttr.addType(classificationDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefParent2 = 
new AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasClassificationDef classificationDefParent2 = new 
AtlasClassificationDef("classificationDefParent2", "classificationDefParent2 
desc", null, Collections.singletonList(attrDefForClassificationDefParent2));
+        ttr.addType(classificationDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForClassificationDefChild = 
new AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        Set<String> superTypes = new HashSet<>();
+        superTypes.add("classificationDefParent");
+        superTypes.add("classificationDefParent2");
+        AtlasClassificationDef classificationDefChild = new 
AtlasClassificationDef("classificationDefChild", "classificationDefChild desc", 
null, Collections.singletonList(attrDefForClassificationDefChild), superTypes);
+
+        try {
+            ttr.addType(classificationDefChild);
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+            fail("Parent attribute name and Child attribute name should be 
allowed to be same when skip-check flag is true");
+        } finally {
+            AtlasStructType.skipCheckForParentChildAttributeName = false;
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
 }
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java 
b/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
index 742970390..e829db16b 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasEntityType.java
@@ -18,10 +18,12 @@
 package org.apache.atlas.type;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.atlas.AtlasErrorCode;
 import org.apache.atlas.exception.AtlasBaseException;
@@ -29,6 +31,7 @@ import org.apache.atlas.model.ModelTestUtil;
 import org.apache.atlas.model.instance.AtlasEntity;
 import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
 import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
 import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
 import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
@@ -513,4 +516,170 @@ public class TestAtlasEntityType {
 
         return column;
     }
-}
+
+    @Test
+    public void testInvalidAttributeNameForSubtype() throws AtlasBaseException 
{
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild), 
Collections.singleton("entityDefParent"));
+        try {
+            ttr.addType(entityDefChild);
+            fail("Parent attribute name and Child attribute name should not be 
the same");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeUpdate() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild));
+        ttr.addType(entityDefChild);
+
+        Set<String> superTypes = entityDefChild.getSuperTypes();
+        assertEquals(superTypes.size(), 0);
+
+        superTypes.add(entityDefParent.getName());
+        entityDefChild.setSuperTypes(superTypes);
+
+        try {
+            ttr.updateType(entityDefChild);
+            fail("Parent attribute name and Child attribute name should not be 
the same");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeForMultipleParents() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent2 = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent2 = new 
AtlasEntityDef("entityDefParent2", "entityDefParent2 desc", null, 
Collections.singletonList(attrDefForEntityDefParent2));
+        ttr.addType(entityDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        Set<String> superTypes = new HashSet<>();
+        superTypes.add("entityDefParent");
+        superTypes.add("entityDefParent2");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild), superTypes);
+
+        try {
+            ttr.addType(entityDefChild);
+            fail("Child type cannot have two Parent types having same 
attribute names");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testInvalidAttributeNameForSubtypeForMultipleParents_Update() 
throws AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent2 = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent2 = new 
AtlasEntityDef("entityDefParent2", "entityDefParent2 desc", null, 
Collections.singletonList(attrDefForEntityDefParent2));
+        ttr.addType(entityDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild), 
Collections.singleton("entityDefParent"));
+        ttr.addType(entityDefChild);
+
+        Set<String> superTypes = entityDefChild.getSuperTypes();
+        assertEquals(superTypes.size(), 1);
+
+        superTypes.add(entityDefParent2.getName());
+        entityDefChild.setSuperTypes(superTypes);
+        try {
+            ttr.updateType(entityDefChild);
+            fail("Child type cannot have two Parent types having same 
attribute names");
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+        } finally {
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testSkipInvalidAttributeNameForSubtype() throws 
AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+        AtlasStructType.skipCheckForParentChildAttributeName = true;
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild), 
Collections.singleton("entityDefParent"));
+
+        try {
+            ttr.addType(entityDefChild);
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+            fail("Parent attribute name and Child attribute name should be 
allowed to be same when skip-check flag is true");
+        } finally {
+            AtlasStructType.skipCheckForParentChildAttributeName = false;
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+
+    @Test
+    public void testSkipInvalidAttributeNameForSubtypeForMultipleParents() 
throws AtlasBaseException {
+        AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry();
+        AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate();
+        AtlasStructType.skipCheckForParentChildAttributeName = true;
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent = new AtlasEntityDef("entityDefParent", 
"entityDefParent desc", null, 
Collections.singletonList(attrDefForEntityDefParent));
+        ttr.addType(entityDefParent);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefParent2 = new 
AtlasStructDef.AtlasAttributeDef("attributeP", "string");
+        AtlasEntityDef entityDefParent2 = new 
AtlasEntityDef("entityDefParent2", "entityDefParent2 desc", null, 
Collections.singletonList(attrDefForEntityDefParent2));
+        ttr.addType(entityDefParent2);
+
+        AtlasStructDef.AtlasAttributeDef attrDefForEntityDefChild = new 
AtlasStructDef.AtlasAttributeDef("attributeC", "string");
+        Set<String> superTypes = new HashSet<>();
+        superTypes.add("entityDefParent");
+        superTypes.add("entityDefParent2");
+        AtlasEntityDef entityDefChild = new AtlasEntityDef("entityDefChild", 
"entityDefChild desc", null, 
Collections.singletonList(attrDefForEntityDefChild), superTypes);
+
+        try {
+            ttr.addType(entityDefChild);
+        } catch (AtlasBaseException e) {
+            assertEquals(e.getAtlasErrorCode().getErrorCode(), 
AtlasErrorCode.ATTRIBUTE_NAME_ALREADY_EXISTS_IN_ANOTHER_PARENT_TYPE.getErrorCode());
+            fail("Parent attribute name and Child attribute name should be 
allowed to be same when skip-check flag is true");
+        } finally {
+            AtlasStructType.skipCheckForParentChildAttributeName = false;
+            registry.releaseTypeRegistryForUpdate(ttr, false);
+        }
+    }
+}
\ No newline at end of file

Reply via email to