This is an automated email from the ASF dual-hosted git repository. pinal 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 92fdf29 ATLAS-3872 Restrict typedef creation when a child type attribute conflicts with parent type attribute of same name 92fdf29 is described below commit 92fdf298b5cfeb8e3d4b265085f9783af9d79cf6 Author: Mandar Ambawane <mandar.ambaw...@freestoneinfotech.com> AuthorDate: Thu Apr 8 18:21:59 2021 +0530 ATLAS-3872 Restrict typedef creation when a child type attribute conflicts with parent type attribute of same name Signed-off-by: Pinal <pinal-shah> --- .../main/java/org/apache/atlas/AtlasErrorCode.java | 1 + .../apache/atlas/type/AtlasClassificationType.java | 1 + .../org/apache/atlas/type/AtlasEntityType.java | 1 + .../org/apache/atlas/type/AtlasStructType.java | 12 ++++++++++++ .../test/java/org/apache/atlas/TestUtilsV2.java | 6 ++---- .../java/org/apache/atlas/model/ModelTestUtil.java | 21 +++++++++++++++++++++ repository/src/test/resources/logging-v1-full.zip | Bin 4853 -> 5106 bytes repository/src/test/resources/sales-v1-full.zip | Bin 10799 -> 11339 bytes .../src/test/resources/salesNewTypeAttrs-next.zip | Bin 2947 -> 3172 bytes .../src/test/resources/salesNewTypeAttrs.zip | Bin 2918 -> 3140 bytes .../java/org/apache/atlas/examples/QuickStart.java | 2 +- .../org/apache/atlas/examples/QuickStartV2.java | 5 ----- .../atlas/web/integration/BaseResourceIT.java | 3 +-- .../web/integration/TypedefsJerseyResourceIT.java | 4 ++-- .../web/integration/TypesJerseyResourceIT.java | 4 ++-- 15 files changed, 44 insertions(+), 16 deletions(-) diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index 773fae2..5ef62d3 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -172,6 +172,7 @@ public enum AtlasErrorCode { ATTRIBUTE_NAME_INVALID_CHARS(400, "ATLAS-400-00-09A", "{0}: invalid name. Attribute names must begin with a letter followed by a sequence of letters, numbers, or '_' characters"), NO_DATA_FOUND(400, "ATLAS-400-00-09B", "No data found in the uploaded file"), NOT_VALID_FILE(400, "ATLAS-400-00-09C", "Invalid {0} file"), + ATTRIBUTE_NAME_ALREADY_EXISTS_IN_PARENT_TYPE(400, "ATLAS-400-00-09D", "Invalid attribute name: {0}.{1}. Attribute already exists in parent type: {2}"), UNAUTHORIZED_ACCESS(403, "ATLAS-403-00-001", "{0} is not authorized to perform {1}"), // All Not found enums go here 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 22259bc..5b86b80 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java @@ -130,6 +130,7 @@ public class AtlasClassificationType extends AtlasStructType { @Override void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { super.resolveReferencesPhase2(typeRegistry); + ensureNoAttributeOverride(superTypes); for (AtlasClassificationType superType : superTypes) { superType.addSubType(this); 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 bfd5e98..ded6d63 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java @@ -212,6 +212,7 @@ public class AtlasEntityType extends AtlasStructType { @Override void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { super.resolveReferencesPhase2(typeRegistry); + ensureNoAttributeOverride(superTypes); for (AtlasEntityType superType : superTypes) { superType.addSubType(this); 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 d89aca2..21ce236 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java @@ -21,6 +21,8 @@ import org.apache.atlas.AtlasErrorCode; 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; @@ -718,6 +720,16 @@ 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/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java index d9e2d19..f0ec675 100755 --- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java +++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java @@ -969,8 +969,7 @@ public final class TestUtilsV2 { createRequiredAttrDef("tag", "string")); AtlasClassificationDef fetlClassificationTypeDefinition = - AtlasTypeUtil.createTraitTypeDef("fetl" + CLASSIFICATION, "fetl" + CLASSIFICATION + _description, Collections.singleton(CLASSIFICATION), - createRequiredAttrDef("tag", "string")); + AtlasTypeUtil.createTraitTypeDef("fetl" + CLASSIFICATION, "fetl" + CLASSIFICATION + _description, Collections.singleton(CLASSIFICATION)); AtlasClassificationDef phiTypeDefinition = AtlasTypeUtil.createTraitTypeDef(PHI, PHI + _description, Collections.<String>emptySet(), createRequiredAttrDef("stringAttr", "string"), @@ -1450,8 +1449,7 @@ public final class TestUtilsV2 { createRequiredAttrDef("level", "int")); AtlasClassificationDef janitorSecurityClearanceTypeDef = - AtlasTypeUtil.createTraitTypeDef("JanitorClearance", "JanitorClearance_description", Collections.singleton("SecurityClearance1"), - createRequiredAttrDef("level", "int")); + AtlasTypeUtil.createTraitTypeDef("JanitorClearance", "JanitorClearance_description", Collections.singleton("SecurityClearance1")); List<AtlasClassificationDef> ret = Arrays.asList(securityClearanceTypeDef, janitorSecurityClearanceTypeDef); diff --git a/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java b/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java index 5df9525..549512e 100644 --- a/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java +++ b/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java @@ -29,6 +29,7 @@ import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry; +import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -36,6 +37,7 @@ import java.util.ArrayList; import java.util.List; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_BUILTIN_TYPES; import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_PRIMITIVE_TYPES; @@ -228,8 +230,13 @@ public final class ModelTestUtil { ret.setDescription(ret.getName()); ret.setAttributeDefs(newAttributeDefsWithAllBuiltInTypes(PREFIX_ATTRIBUTE_NAME)); + List<AtlasAttributeDef> currentTypeAttrDefs = ret.getAttributeDefs(); + if (superTypes != null) { for (AtlasEntityDef superType : superTypes) { + List<AtlasAttributeDef> superTypeAttrDefs = superType.getAttributeDefs(); + removeAttributeIfExistedInSuperType(currentTypeAttrDefs, superTypeAttrDefs); + ret.addSuperType(superType.getName()); } } @@ -284,8 +291,13 @@ public final class ModelTestUtil { ret.setDescription(ret.getName()); ret.setAttributeDefs(newAttributeDefsWithAllBuiltInTypes(PREFIX_ATTRIBUTE_NAME)); + List<AtlasAttributeDef> currentTypeAttrDefs = ret.getAttributeDefs(); + if (superTypes != null) { for (AtlasClassificationDef superType : superTypes) { + List<AtlasAttributeDef> superTypeAttrDefs = superType.getAttributeDefs(); + removeAttributeIfExistedInSuperType(currentTypeAttrDefs, superTypeAttrDefs); + ret.addSuperType(superType.getName()); } } @@ -514,4 +526,13 @@ public final class ModelTestUtil { private static String getRandomBuiltInType() { return ATLAS_BUILTIN_TYPES[ThreadLocalRandom.current().nextInt(0, ATLAS_BUILTIN_TYPES.length)]; } + + private static void removeAttributeIfExistedInSuperType(List<AtlasAttributeDef> currentTypeAttrDefs, List<AtlasAttributeDef> superTypeAttrDefs) { + if (CollectionUtils.isNotEmpty(superTypeAttrDefs)) { + List<String> superTypeAttrNames = superTypeAttrDefs.stream() + .map(superTypeObj -> superTypeObj.getName()).collect(Collectors.toList()); + + currentTypeAttrDefs.removeIf(obj -> superTypeAttrNames.contains(obj.getName())); + } + } } diff --git a/repository/src/test/resources/logging-v1-full.zip b/repository/src/test/resources/logging-v1-full.zip index 69c54ee..dc983ca 100644 Binary files a/repository/src/test/resources/logging-v1-full.zip and b/repository/src/test/resources/logging-v1-full.zip differ diff --git a/repository/src/test/resources/sales-v1-full.zip b/repository/src/test/resources/sales-v1-full.zip index 07afbf6..296e11e 100644 Binary files a/repository/src/test/resources/sales-v1-full.zip and b/repository/src/test/resources/sales-v1-full.zip differ diff --git a/repository/src/test/resources/salesNewTypeAttrs-next.zip b/repository/src/test/resources/salesNewTypeAttrs-next.zip index e4c8505..c04b86c 100644 Binary files a/repository/src/test/resources/salesNewTypeAttrs-next.zip and b/repository/src/test/resources/salesNewTypeAttrs-next.zip differ diff --git a/repository/src/test/resources/salesNewTypeAttrs.zip b/repository/src/test/resources/salesNewTypeAttrs.zip index a4467e6..6f11b00 100644 Binary files a/repository/src/test/resources/salesNewTypeAttrs.zip and b/repository/src/test/resources/salesNewTypeAttrs.zip differ diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java index 82a9f5c..fcf5bd4 100755 --- a/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java +++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStart.java @@ -169,7 +169,7 @@ public class QuickStart { .createClassTypeDef(TABLE_TYPE, TABLE_TYPE, Collections.singleton("DataSet"), new AttributeDefinition(DB_ATTRIBUTE, DATABASE_TYPE, Multiplicity.REQUIRED, false, null), new AttributeDefinition("sd", STORAGE_DESC_TYPE, Multiplicity.REQUIRED, true, null), - attrDef("owner", AtlasBaseTypeDef.ATLAS_TYPE_STRING), attrDef("createTime", AtlasBaseTypeDef.ATLAS_TYPE_LONG), + attrDef("createTime", AtlasBaseTypeDef.ATLAS_TYPE_LONG), attrDef("lastAccessTime", AtlasBaseTypeDef.ATLAS_TYPE_LONG), attrDef("retention", AtlasBaseTypeDef.ATLAS_TYPE_LONG), attrDef("viewOriginalText", AtlasBaseTypeDef.ATLAS_TYPE_STRING), attrDef("viewExpandedText", AtlasBaseTypeDef.ATLAS_TYPE_STRING), attrDef("tableType", AtlasBaseTypeDef.ATLAS_TYPE_STRING), diff --git a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java index d5cf9b7..bc3efbe 100755 --- a/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java +++ b/webapp/src/main/java/org/apache/atlas/examples/QuickStartV2.java @@ -231,15 +231,11 @@ public class QuickStartV2 { AtlasTypesDef createTypeDefinitions() { // Entity-Definitions AtlasEntityDef dbTypeDef = createClassTypeDef(DATABASE_TYPE, DATABASE_TYPE, VERSION_1, Collections.singleton("DataSet"), - createUniqueRequiredAttrDef("name", "string"), - createOptionalAttrDef("description", "string"), createOptionalAttrDef("locationUri", "string"), - createOptionalAttrDef("owner", "string"), createOptionalAttrDef("createTime", "long")); AtlasEntityDef tableTypeDef = createClassTypeDef(TABLE_TYPE, TABLE_TYPE, VERSION_1, Collections.singleton("DataSet"), new HashMap<String, String>() {{ put("schemaElementsAttribute", "columns"); }} , - createOptionalAttrDef("owner", "string"), createOptionalAttrDef("createTime", "long"), createOptionalAttrDef("lastAccessTime", "long"), createOptionalAttrDef("retention", "long"), @@ -250,7 +246,6 @@ public class QuickStartV2 { AtlasEntityDef colTypeDef = createClassTypeDef(COLUMN_TYPE, COLUMN_TYPE, VERSION_1, Collections.singleton("DataSet"), new HashMap<String, String>() {{ put("schemaAttributes", "[\"name\", \"description\", \"owner\", \"type\", \"comment\", \"position\"]"); }}, - createOptionalAttrDef("name", "string"), createOptionalAttrDef("dataType", "string"), createOptionalAttrDef("comment", "string")); diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java index 6db6b58..50f93d9 100755 --- a/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/integration/BaseResourceIT.java @@ -354,7 +354,7 @@ public abstract class BaseResourceIT { ClassTypeDefinition tblClsDef = TypesUtil .createClassTypeDef(HIVE_TABLE_TYPE, null, Collections.singleton("DataSet"), - attrDef("owner", AtlasBaseTypeDef.ATLAS_TYPE_STRING), attrDef("createTime", AtlasBaseTypeDef.ATLAS_TYPE_LONG), + attrDef("createTime", AtlasBaseTypeDef.ATLAS_TYPE_LONG), attrDef("lastAccessTime", AtlasBaseTypeDef.ATLAS_TYPE_DATE), attrDef("temporary", AtlasBaseTypeDef.ATLAS_TYPE_BOOLEAN), new AttributeDefinition("db", DATABASE_TYPE, Multiplicity.OPTIONAL, true, "tables"), @@ -435,7 +435,6 @@ public abstract class BaseResourceIT { AtlasEntityDef tblClsDef = AtlasTypeUtil .createClassTypeDef(HIVE_TABLE_TYPE_V2, Collections.singleton("DataSet"), - AtlasTypeUtil.createOptionalAttrDef("owner", "string"), AtlasTypeUtil.createOptionalAttrDef("createTime", "long"), AtlasTypeUtil.createOptionalAttrDef("lastAccessTime", "date"), AtlasTypeUtil.createOptionalAttrDef("temporary", "boolean"), diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/TypedefsJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/TypedefsJerseyResourceIT.java index 0cd707f..9506c62 100644 --- a/webapp/src/test/java/org/apache/atlas/web/integration/TypedefsJerseyResourceIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/integration/TypedefsJerseyResourceIT.java @@ -339,9 +339,9 @@ public class TypedefsJerseyResourceIT extends BaseResourceIT { public void testListTypesByFilter() throws Exception { AtlasAttributeDef attr = AtlasTypeUtil.createOptionalAttrDef("attr", "string"); AtlasEntityDef classDefA = AtlasTypeUtil.createClassTypeDef("A" + randomString(), Collections.<String>emptySet(), attr); - AtlasEntityDef classDefA1 = AtlasTypeUtil.createClassTypeDef("A1" + randomString(), Collections.singleton(classDefA.getName()), attr); + AtlasEntityDef classDefA1 = AtlasTypeUtil.createClassTypeDef("A1" + randomString(), Collections.singleton(classDefA.getName())); AtlasEntityDef classDefB = AtlasTypeUtil.createClassTypeDef("B" + randomString(), Collections.<String>emptySet(), attr); - AtlasEntityDef classDefC = AtlasTypeUtil.createClassTypeDef("C" + randomString(), new HashSet<>(Arrays.asList(classDefB.getName(), classDefA.getName())), attr); + AtlasEntityDef classDefC = AtlasTypeUtil.createClassTypeDef("C" + randomString(), new HashSet<>(Arrays.asList(classDefB.getName(), classDefA.getName()))); AtlasTypesDef atlasTypesDef = new AtlasTypesDef(); atlasTypesDef.getEntityDefs().add(classDefA); diff --git a/webapp/src/test/java/org/apache/atlas/web/integration/TypesJerseyResourceIT.java b/webapp/src/test/java/org/apache/atlas/web/integration/TypesJerseyResourceIT.java index 7c820e7..6a0bbec 100755 --- a/webapp/src/test/java/org/apache/atlas/web/integration/TypesJerseyResourceIT.java +++ b/webapp/src/test/java/org/apache/atlas/web/integration/TypesJerseyResourceIT.java @@ -216,7 +216,7 @@ public class TypesJerseyResourceIT extends BaseResourceIT { TypesDef typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef)); String a = createType(AtlasType.toV1Json(typesDef)).get(0); - classTypeDef = TypesUtil.createClassTypeDef("A1" + randomString(), null, Collections.singleton(a), attr); + classTypeDef = TypesUtil.createClassTypeDef("A1" + randomString(), null, Collections.singleton(a)); typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef)); String a1 = createType(AtlasType.toV1Json(typesDef)).get(0); @@ -224,7 +224,7 @@ public class TypesJerseyResourceIT extends BaseResourceIT { typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef)); String b = createType(AtlasType.toV1Json(typesDef)).get(0); - classTypeDef = TypesUtil.createClassTypeDef("C" + randomString(), null, new HashSet<>(Arrays.asList(a, b)), attr); + classTypeDef = TypesUtil.createClassTypeDef("C" + randomString(), null, new HashSet<>(Arrays.asList(a, b))); typesDef = new TypesDef(Collections.emptyList(), Collections.emptyList(), Collections.emptyList(), Collections.singletonList(classTypeDef)); String c = createType(AtlasType.toV1Json(typesDef)).get(0);