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