Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id 6037F200CE6 for ; Fri, 15 Sep 2017 11:26:45 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 5ECC91609D1; Fri, 15 Sep 2017 09:26:45 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id 805A01609CF for ; Fri, 15 Sep 2017 11:26:43 +0200 (CEST) Received: (qmail 87876 invoked by uid 500); 15 Sep 2017 09:26:42 -0000 Mailing-List: contact commits-help@atlas.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@atlas.apache.org Delivered-To: mailing list commits@atlas.apache.org Received: (qmail 87866 invoked by uid 99); 15 Sep 2017 09:26:42 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 15 Sep 2017 09:26:42 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 41739F5546; Fri, 15 Sep 2017 09:26:42 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: davidrad@apache.org To: commits@atlas.apache.org Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: atlas git commit: ATLAS-2029: Restrict entities, classifications can be applied to Date: Fri, 15 Sep 2017 09:26:42 +0000 (UTC) archived-at: Fri, 15 Sep 2017 09:26:45 -0000 Repository: atlas Updated Branches: refs/heads/master 6e5618520 -> 586b5eb20 ATLAS-2029: Restrict entities, classifications can be applied to =update Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/586b5eb2 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/586b5eb2 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/586b5eb2 Branch: refs/heads/master Commit: 586b5eb209d146397dc05b5af44716c877d56c2a Parents: 6e56185 Author: David Radley Authored: Tue Sep 12 12:20:06 2017 +0100 Committer: David Radley Committed: Fri Sep 15 09:29:45 2017 +0100 ---------------------------------------------------------------------- .../java/org/apache/atlas/AtlasErrorCode.java | 5 + .../model/typedef/AtlasClassificationDef.java | 73 ++++++++- .../atlas/type/AtlasClassificationType.java | 137 +++++++++++++++- .../org/apache/atlas/type/AtlasEntityType.java | 22 +++ .../org/apache/atlas/type/AtlasTypeUtil.java | 4 + .../test/java/org/apache/atlas/TestUtilsV2.java | 45 ++++++ .../org/apache/atlas/model/ModelTestUtil.java | 2 +- .../atlas/type/TestAtlasClassificationType.java | 127 +++++++++++++++ .../graph/v1/AtlasClassificationDefStoreV1.java | 3 + .../store/graph/v1/AtlasEntityStoreV1.java | 11 +- .../store/graph/v1/AtlasGraphUtilsV1.java | 1 + .../graph/v1/AtlasTypeDefGraphStoreV1.java | 38 ++++- .../store/graph/AtlasTypeDefGraphStoreTest.java | 155 +++++++++++++++++-- .../store/graph/v1/AtlasEntityStoreV1Test.java | 2 +- 14 files changed, 603 insertions(+), 22 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java index f529739..6979040 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -95,6 +95,11 @@ public enum AtlasErrorCode { INVALID_RELATIONSHIP_ATTRIBUTE(400, "ATLAS-400-00-048", "Expected attribute {0} to be a relationship but found type {1}"), INVALID_RELATIONSHIP_TYPE(400, "ATLAS-400-00-049", "Invalid entity type '{0}', guid '{1}' in relationship search"), INVALID_IMPORT_ATTRIBUTE_TYPE_CHANGED(400, "ATLAS-400-00-050", "Attribute {0}.{1} is of type {2}. Import has this attribute type as {3}"), + ENTITYTYPE_REMOVAL_NOT_SUPPORTED(400, "ATLAS-400-00-051", "EntityTypes cannot be removed from ClassificationDef ‘{0}‘"), + CLASSIFICATIONDEF_INVALID_ENTITYTYPES(400, "ATLAS-400-00-052", "ClassificationDef ‘{0}‘ has invalid ‘{1}‘ in entityTypes"), + CLASSIFICATIONDEF_PARENTS_ENTITYTYPES_DISJOINT(400, "ATLAS-400-00-053", "ClassificationDef ‘{0}‘ has supertypes whose entityTypes are disjoint; e.g. 2 supertypes that are not related by inheritance specify different non empty entityType lists. This means the child cannot honour the restrictions specified in both parents."), + CLASSIFICATIONDEF_ENTITYTYPES_NOT_PARENTS_SUBSET(400, "ATLAS-400-00-054", "ClassificationDef ‘{0}‘ has entityTypes ‘{1}‘ which are not subsets of it's supertypes entityTypes"), + INVALID_ENTITY_FOR_CLASSIFICATION (400, "ATLAS-400-00-055", "Entity (guid=‘{0}‘,typename=‘{1}‘) cannot be classified by Classification ‘{2}‘, because ‘{1}‘ is not in the ClassificationDef's restrictions."), // All Not found enums go here TYPE_NAME_NOT_FOUND(404, "ATLAS-404-00-001", "Given typename {0} was invalid"), http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/main/java/org/apache/atlas/model/typedef/AtlasClassificationDef.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasClassificationDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasClassificationDef.java index eeaf714..7b411e0 100644 --- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasClassificationDef.java +++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasClassificationDef.java @@ -51,6 +51,7 @@ public class AtlasClassificationDef extends AtlasStructDef implements java.io.Se private static final long serialVersionUID = 1L; private Set superTypes; + private Set entityTypes; public AtlasClassificationDef() { @@ -82,9 +83,16 @@ public class AtlasClassificationDef extends AtlasStructDef implements java.io.Se public AtlasClassificationDef(String name, String description, String typeVersion, List attributeDefs, Set superTypes, Map options) { + this(name, description, typeVersion, attributeDefs, superTypes, null, options); + } + + public AtlasClassificationDef(String name, String description, String typeVersion, + List attributeDefs, Set superTypes, + Set entityTypes, Map options) { super(TypeCategory.CLASSIFICATION, name, description, typeVersion, attributeDefs, options); setSuperTypes(superTypes); + setEntityTypes(entityTypes); } public AtlasClassificationDef(AtlasClassificationDef other) { @@ -141,6 +149,66 @@ public class AtlasClassificationDef extends AtlasStructDef implements java.io.Se return superTypes != null && typeName != null && superTypes.contains(typeName); } + /** + * Specifying a list of entityType names in the classificationDef, ensures that classifications can + * only be applied to those entityTypes. + *
    + *
  • Any subtypes of the entity types inherit the restriction
  • + *
  • Any classificationDef subtypes inherit the parents entityTypes restrictions
  • + *
  • Any classificationDef subtypes can further restrict the parents entityTypes restrictions by specifying a subset of the entityTypes
  • + *
  • An empty entityTypes list when there are no parent restrictions means there are no restrictions
  • + *
  • An empty entityTypes list when there are parent restrictions means that the subtype picks up the parents restrictions
  • + *
  • If a list of entityTypes are supplied, where one inherits from another, this will be rejected. This should encourage cleaner classificationsDefs
  • + *
+ */ + public Set getEntityTypes() { + return entityTypes; + } + + public void setEntityTypes(Set entityTypes) { + if (entityTypes != null && this.entityTypes == entityTypes) { + return; + } + + if (CollectionUtils.isEmpty(entityTypes)) { + this.entityTypes = new HashSet<>(); + } else { + this.entityTypes = new HashSet<>(entityTypes); + } + } + + public boolean hasEntityType(String typeName) { + return hasEntityType(entityTypes, typeName); + } + + public void addEntityType(String typeName) { + Set s = this.entityTypes; + + if (!hasEntityType(s, typeName)) { + s = new HashSet<>(s); + + s.add(typeName); + + this.entityTypes = s; + } + } + + public void removeEntityType(String typeName) { + Set s = this.entityTypes; + + if (hasEntityType(s, typeName)) { + s = new HashSet<>(s); + + s.remove(typeName); + + this.entityTypes = s; + } + } + + private static boolean hasEntityType(Set entityTypes, String typeName) { + return entityTypes != null && typeName != null && entityTypes.contains(typeName); + } + @Override public StringBuilder toString(StringBuilder sb) { if (sb == null) { @@ -151,6 +219,8 @@ public class AtlasClassificationDef extends AtlasStructDef implements java.io.Se super.toString(sb); sb.append(", superTypes=["); dumpObjects(superTypes, sb); + sb.append("], entityTypes=["); + dumpObjects(entityTypes, sb); sb.append("]"); sb.append('}'); @@ -164,7 +234,8 @@ public class AtlasClassificationDef extends AtlasStructDef implements java.io.Se if (!super.equals(o)) { return false; } AtlasClassificationDef that = (AtlasClassificationDef) o; - return Objects.equals(superTypes, that.superTypes); + + return Objects.equals(superTypes, that.superTypes) && Objects.equals(entityTypes,that.entityTypes); } @Override http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java ---------------------------------------------------------------------- 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 cc3e45e..9f39423 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java @@ -28,13 +28,7 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -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 java.util.*; /** @@ -51,12 +45,28 @@ public class AtlasClassificationType extends AtlasStructType { private Set typeAndAllSubTypes = Collections.emptySet(); private String typeAndAllSubTypesQryStr = ""; + // we need to store the entityTypes specified in our supertypes. i.e. our parent classificationDefs may specify more entityTypes + // that we also need to allow + private Set entityTypes = Collections.emptySet(); + + /** + * Note this constructor does NOT run resolveReferences - so some fields are not setup. + * @param classificationDef + */ public AtlasClassificationType(AtlasClassificationDef classificationDef) { super(classificationDef); this.classificationDef = classificationDef; } + /** + * ClassificationType needs to be constructed with a type registry so that is can resolve references + * at constructor time. This is only used by junits. + * + * @param classificationDef + * @param typeRegistry + * @throws AtlasBaseException + */ public AtlasClassificationType(AtlasClassificationDef classificationDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { super(classificationDef); @@ -95,6 +105,7 @@ public class AtlasClassificationType extends AtlasStructType { this.uniqAttributes = getUniqueAttributes(this.allAttributes); this.allSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2() this.typeAndAllSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2() + this.entityTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase3() this.typeAndAllSubTypes.add(this.getTypeName()); } @@ -109,11 +120,92 @@ public class AtlasClassificationType extends AtlasStructType { } } + /** + * This method processes the entityTypes to ensure they are valid, using the following principles: + * - entityTypes are supplied on the classificationDef to restrict the types of entities that this classification can be applied to + * - Any subtypes of the specified entity type can also have this classification applied + * - Any subtypes of the classificationDef inherit the parents entityTypes restrictions + * - Any subtypes of the classificationDef can further restrict the parents entityTypes restrictions + * - An empty entityTypes list when there are no parent restrictions means there are no restrictions + * - An empty entityTypes list when there are parent restrictions means that the subtype picks up the parents restrictions + * + * This method validates that these priniciples are adhered to. + * + * Note that if duplicate Strings in the entityTypes are specified on an add / update, the duplicates are ignored - as Java Sets cannot have duplicates. + * Note if an entityType is supplied in the list that is a subtype of one of the other supplied entityTypes, we are not policing this case as invalid. + * + * @param typeRegistry + * @throws AtlasBaseException + */ @Override void resolveReferencesPhase3(AtlasTypeRegistry typeRegistry) throws AtlasBaseException { allSubTypes = Collections.unmodifiableSet(allSubTypes); typeAndAllSubTypes = Collections.unmodifiableSet(typeAndAllSubTypes); typeAndAllSubTypesQryStr = ""; // will be computed on next access + + /* + Add any entityTypes defined in our parents as restrictions. + */ + Set superTypeEntityTypes = null; + + final Set classificationDefEntityTypes = classificationDef.getEntityTypes(); + + // Here we find the intersection of the entityTypes specified in all our supertypes; in this way we will honour our parents restrictions. + // This following logic assumes typeAndAllSubTypes is populated so needs to be run after resolveReferencesPhase2(). + + for (String superType : this.allSuperTypes) { + AtlasClassificationDef superTypeDef = typeRegistry.getClassificationDefByName(superType); + Set entityTypeNames = superTypeDef.getEntityTypes(); + + if (CollectionUtils.isEmpty(entityTypeNames)) { // no restrictions specified + continue; + } + + // classification is applicable for specified entityTypes and their sub-entityTypes + Set typesAndSubEntityTypes = AtlasEntityType.getEntityTypesAndAllSubTypes(entityTypeNames, typeRegistry); + + if (superTypeEntityTypes == null) { + superTypeEntityTypes = new HashSet<>(typesAndSubEntityTypes); + } else { + // retain only the intersections. + superTypeEntityTypes.retainAll(typesAndSubEntityTypes); + } + if (superTypeEntityTypes.isEmpty()) { + // if we have no intersections then we are disjoint - so no need to check other supertypes + break; + } + } + + if (superTypeEntityTypes == null) { // no supertype restrictions; use current classification restrictions + this.entityTypes = AtlasEntityType.getEntityTypesAndAllSubTypes(classificationDefEntityTypes, typeRegistry); + } else { // restrictions are specified in super-types + if (CollectionUtils.isEmpty(superTypeEntityTypes)) { + /* + Restrictions in superTypes are disjoint! This means that the child cannot exist as it cannot be a restriction of it's parents. + + For example: + parent1 specifies entityTypes ["EntityA"] + parent2 specifies entityTypes ["EntityB"] + + In order to be a valid child of Parent1 the child could only be applied to EntityAs. + In order to be a valid child of Parent2 the child could only be applied to EntityBs. + + Reject the creation of the classificationDef - as it would compromise Atlas's integrity. + */ + throw new AtlasBaseException(AtlasErrorCode.CLASSIFICATIONDEF_PARENTS_ENTITYTYPES_DISJOINT, this.classificationDef.getName()); + } + + if (CollectionUtils.isEmpty(classificationDefEntityTypes)) { // no restriction specified; use the restrictions from super-types + this.entityTypes = superTypeEntityTypes; + } else { + this.entityTypes = AtlasEntityType.getEntityTypesAndAllSubTypes(classificationDefEntityTypes,typeRegistry); + // Compatible parents and entityTypes, now check whether the specified entityTypes are the same as the effective entityTypes due to our parents or a subset. + // Only allowed to restrict our parents. + if (!superTypeEntityTypes.containsAll(this.entityTypes)) { + throw new AtlasBaseException(AtlasErrorCode.CLASSIFICATIONDEF_ENTITYTYPES_NOT_PARENTS_SUBSET, classificationDef.getName(), classificationDefEntityTypes.toString()); + } + } + } } private void addSubType(AtlasClassificationType subType) { @@ -155,6 +247,16 @@ public class AtlasClassificationType extends AtlasStructType { return StringUtils.isNotEmpty(classificationName) && allSuperTypes.contains(classificationName); } + /** + * List of all the entity type names that are valid for this classification type. + * + * An empty list means there are no restrictions on which entities can be classified by these classifications. + * @return + */ + public Set getEntityTypes() { + return entityTypes; + } + @Override public AtlasClassification createDefaultValue() { AtlasClassification ret = new AtlasClassification(classificationDef.getName()); @@ -313,6 +415,27 @@ public class AtlasClassificationType extends AtlasStructType { } } + /** + * Check whether the supplied entityType can be applied to this classification. + * + * We can apply this classification to the supplied entityType if + * - we have no restrictions (entityTypes empty including null) + * or + * - the entityType is in our list of restricted entityTypes (which includes our parent classification restrictions) + * + * @param entityType + * @return whether can apply + */ + /** + * Check whether the supplied entityType can be applied to this classification. + * + * @param entityType + * @return whether can apply + */ + public boolean canApplyToEntityType(AtlasEntityType entityType) { + return CollectionUtils.isEmpty(this.entityTypes) || this.entityTypes.contains(entityType.getTypeName()); + } + private void getTypeHierarchyInfo(AtlasTypeRegistry typeRegistry, Set allSuperTypeNames, Map allAttributes) throws AtlasBaseException { http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java ---------------------------------------------------------------------- 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 28215fd..205e5b9 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java @@ -522,6 +522,28 @@ public class AtlasEntityType extends AtlasStructType { return true; } + /** + * Takes a set of entityType names and a registry and returns a set of the entitytype names and the names of all their subTypes. + * + * @param entityTypes + * @param typeRegistry + * @return set of strings of the types and their subtypes. + */ + static public Set getEntityTypesAndAllSubTypes(Set entityTypes, AtlasTypeRegistry typeRegistry) throws AtlasBaseException { + Set ret = new HashSet<>(); + + for (String typeName : entityTypes) { + AtlasEntityType entityType = typeRegistry.getEntityTypeByName(typeName); + if (entityType == null) { + throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, typeName); + } + + ret.addAll(entityType.getTypeAndAllSubTypes()); + } + + return ret; + } + private boolean isAssignableValue(Object value, AtlasAttributeDef attributeDef) { boolean ret = true; http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java index ab063e2..5f3cefd 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java @@ -220,6 +220,10 @@ public class AtlasTypeUtil { return new AtlasClassificationDef(name, description, version, Arrays.asList(attrDefs), superTypes); } + public static AtlasClassificationDef createAtlasClassificationDef(String name, String description, String version, ImmutableSet superTypes, ImmutableSet entityTypes, AtlasAttributeDef... attrDefs) { + return new AtlasClassificationDef(name, description, version, Arrays.asList(attrDefs), superTypes, entityTypes, null); + } + public static AtlasStructDef createStructTypeDef(String name, AtlasAttributeDef... attrDefs) { return createStructTypeDef(name, null, attrDefs); } http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/test/java/org/apache/atlas/TestUtilsV2.java ---------------------------------------------------------------------- diff --git a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java index fc65af0..91fdb47 100755 --- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java +++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java @@ -1004,6 +1004,29 @@ public final class TestUtilsV2 { return ret; } + public static List getClassificationWithName(String name) { + AtlasClassificationDef classificationTypeDef = + AtlasTypeUtil.createTraitTypeDef(name, "s_description", ImmutableSet.of(), + AtlasTypeUtil.createRequiredAttrDef("level", "int")); + + + List ret = Arrays.asList(classificationTypeDef); + + populateSystemAttributes(ret); + + return ret; + } + + public static AtlasClassificationDef getSingleClassificationWithName(String name) { + AtlasClassificationDef classificaitonTypeDef = + AtlasTypeUtil.createTraitTypeDef(name, "s_description", ImmutableSet.of(), + AtlasTypeUtil.createRequiredAttrDef("level", "int")); + + populateSystemAttributes(classificaitonTypeDef); + + return classificaitonTypeDef; + } + public static List getClassificationWithValidAttribute(){ return getClassificationWithValidSuperType(); } @@ -1021,6 +1044,28 @@ public final class TestUtilsV2 { return ret; } + public static List getEntityWithName(String name) { + AtlasEntityDef developerTypeDef = AtlasTypeUtil.createClassTypeDef(name, "Developer_description", ImmutableSet.of(), + new AtlasAttributeDef("language", String.format("array<%s>", "string"), false, AtlasAttributeDef.Cardinality.SET, + 1, 10, false, false, + Collections.emptyList())); + + List ret = Arrays.asList(developerTypeDef); + + populateSystemAttributes(ret); + + return ret; + } + + public static AtlasEntityDef getSingleEntityWithName(String name) { + AtlasEntityDef developerTypeDef = AtlasTypeUtil.createClassTypeDef(name, "Developer_description", ImmutableSet.of(), + new AtlasAttributeDef("language", String.format("array<%s>", "string"), false, AtlasAttributeDef.Cardinality.SET, + 1, 10, false, false, + Collections.emptyList())); + + return developerTypeDef; + } + public static List getEntityWithValidAttribute() { List entityDefs = getEntityWithValidSuperType(); entityDefs.get(1).getSuperTypes().clear(); http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java ---------------------------------------------------------------------- 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 e1ca889..5df9525 100644 --- a/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java +++ b/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java @@ -216,7 +216,7 @@ public final class ModelTestUtil { } public static AtlasEntityDef newEntityDef(AtlasTypeRegistry typesRegistry) { - return newEntityDef(getTypesRegistry(), null); + return newEntityDef(typesRegistry, null); } public static AtlasEntityDef newEntityDef(AtlasTypeRegistry typesRegistry, AtlasEntityDef[] superTypes) { http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java ---------------------------------------------------------------------- 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 aaf4a6a..0badfcf 100644 --- a/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java +++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasClassificationType.java @@ -24,6 +24,8 @@ import org.apache.atlas.model.ModelTestUtil; 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.type.AtlasTypeRegistry.AtlasTransientTypeRegistry; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -70,6 +72,131 @@ public class TestAtlasClassificationType { assertEquals(defValue.getTypeName(), classificationType.getTypeName()); } + // EntityA EntityB EntityE + // / \ / + // / \ / + // EntityC EntityF + // / + // / + // EntityD + + // Classify1(EntityA) Classify6(EntityB) Classify2 Classify9(EntityE) Classify5(EntityA,EntityC) Classify5(EntityC,EntityA) + // / \ / \ + // / \ / \ + // Classify3 Classify7 **invalid** Classify8(EntityA) **invalid** + // / + // / + // Classify4((EntityD) + + @Test + public void testcanApplyToEntityType() throws AtlasBaseException { + AtlasEntityDef entityDefA = new AtlasEntityDef("EntityA"); + AtlasEntityDef entityDefB = new AtlasEntityDef("EntityB"); + AtlasEntityDef entityDefC = new AtlasEntityDef("EntityC", null, null, null, new HashSet<>(Arrays.asList(entityDefA.getName()))); + AtlasEntityDef entityDefD = new AtlasEntityDef("EntityD", null, null, null, new HashSet<>(Arrays.asList(entityDefC.getName()))); + AtlasEntityDef entityDefE = new AtlasEntityDef("EntityE"); + AtlasEntityDef entityDefF = new AtlasEntityDef("EntityF", null, null, null, new HashSet<>(Arrays.asList(entityDefB.getName(),entityDefE.getName()))); + + AtlasClassificationDef classifyDef1 = new AtlasClassificationDef("Classify1", null, null, null, null, new HashSet<>(Arrays.asList(entityDefA.getName())), null); + AtlasClassificationDef classifyDef2 = new AtlasClassificationDef("Classify2"); + AtlasClassificationDef classifyDef3 = new AtlasClassificationDef("Classify3", null, null, null, new HashSet<>(Arrays.asList(classifyDef1.getName())), null, null); + AtlasClassificationDef classifyDef4 = new AtlasClassificationDef("Classify4", null, null, null, new HashSet<>(Arrays.asList(classifyDef1.getName())), new HashSet<>(Arrays.asList(entityDefD.getName())), null); + AtlasClassificationDef classifyDef5 = new AtlasClassificationDef("Classify5", null, null, null, null, new HashSet<>(Arrays.asList(entityDefA.getName(),entityDefC.getName())), null); + AtlasClassificationDef classifyDef6 = new AtlasClassificationDef("Classify6", null, null, null, null, new HashSet<>(Arrays.asList(entityDefB.getName())), null); + AtlasClassificationDef classifyDef7 = new AtlasClassificationDef("Classify7", null, null, null, new HashSet<>(Arrays.asList(classifyDef1.getName(),classifyDef6.getName())),null, null); + AtlasClassificationDef classifyDef8 = new AtlasClassificationDef("Classify8", null, null, null, new HashSet<>(Arrays.asList(classifyDef6.getName())),new HashSet<>(Arrays.asList(entityDefA.getName())), null); + AtlasClassificationDef classifyDef9 = new AtlasClassificationDef("Classify9", null, null, null, null, new HashSet<>(Arrays.asList(entityDefE.getName())), null); + AtlasClassificationDef classifyDef10 = new AtlasClassificationDef("Classify10", null, null, null, null, new HashSet<>(Arrays.asList(entityDefC.getName(),entityDefA.getName())), null); + + AtlasTypeRegistry registry = ModelTestUtil.getTypesRegistry(); + AtlasTransientTypeRegistry ttr = registry.lockTypeRegistryForUpdate(); + + ttr.addType(entityDefA); + ttr.addType(entityDefB); + ttr.addType(entityDefC); + ttr.addType(entityDefD); + ttr.addType(entityDefE); + ttr.addType(entityDefF); + + ttr.addType(classifyDef1); + ttr.addType(classifyDef2); + ttr.addType(classifyDef3); + ttr.addType(classifyDef4); + ttr.addType(classifyDef5); + ttr.addType(classifyDef6); + ttr.addType(classifyDef9); + ttr.addType(classifyDef10); + registry.releaseTypeRegistryForUpdate(ttr, true); + + // test invalid adds + ttr = registry.lockTypeRegistryForUpdate(); + try { + ttr.addType(classifyDef7); + fail("Fail disjoined parent case"); + } catch (AtlasBaseException ae) { + registry.releaseTypeRegistryForUpdate(ttr, false); + } + ttr = registry.lockTypeRegistryForUpdate(); + try { + ttr.addType(classifyDef8); + fail("Fail trying to add an entity type that is not in the parent"); + } catch (AtlasBaseException ae) { + registry.releaseTypeRegistryForUpdate(ttr, false); + } + + AtlasEntityType entityTypeA = registry.getEntityTypeByName(entityDefA.getName()); + AtlasEntityType entityTypeB = registry.getEntityTypeByName(entityDefB.getName()); + AtlasEntityType entityTypeC = registry.getEntityTypeByName(entityDefC.getName()); + AtlasEntityType entityTypeD = registry.getEntityTypeByName(entityDefD.getName()); + AtlasEntityType entityTypeE = registry.getEntityTypeByName(entityDefE.getName()); + AtlasEntityType entityTypeF = registry.getEntityTypeByName(entityDefF.getName()); + AtlasClassificationType classifyType1 = registry.getClassificationTypeByName(classifyDef1.getName()); + AtlasClassificationType classifyType2 = registry.getClassificationTypeByName(classifyDef2.getName()); + AtlasClassificationType classifyType3 = registry.getClassificationTypeByName(classifyDef3.getName()); + AtlasClassificationType classifyType4 = registry.getClassificationTypeByName(classifyDef4.getName()); + AtlasClassificationType classifyType5 = registry.getClassificationTypeByName(classifyDef5.getName()); + AtlasClassificationType classifyType6 = registry.getClassificationTypeByName(classifyDef6.getName()); + AtlasClassificationType classifyType9 = registry.getClassificationTypeByName(classifyDef9.getName()); + AtlasClassificationType classifyType10 = registry.getClassificationTypeByName(classifyDef10.getName()); + + // verify restrictions on Classify1 + assertTrue(classifyType1.canApplyToEntityType(entityTypeA)); // Classify1 has EntityA as an allowed type + assertFalse(classifyType1.canApplyToEntityType(entityTypeB)); // Classify1 neither has EntityB as an allowed type nor any of super-types of EntityB + assertTrue(classifyType1.canApplyToEntityType(entityTypeC)); // Classify1 has EntityA as an allowed type and EntityC is a sub-type of EntityA + assertTrue(classifyType1.canApplyToEntityType(entityTypeD)); // Classify1 has EntityA as an allowed type and EntityD is a grand-sub-type of EntityA (via EntityC) + + // verify restrictions on Classify2 + assertTrue(classifyType2.canApplyToEntityType(entityTypeA)); // EntityA is allowed in Classify2 + assertTrue(classifyType2.canApplyToEntityType(entityTypeB)); // EntityB is allowed in Classify2 + assertTrue(classifyType2.canApplyToEntityType(entityTypeC)); // EntityC is allowed in Classify2 + assertTrue(classifyType2.canApplyToEntityType(entityTypeD)); // EntityD is allowed in Classify2 + + // verify restrictions on Classify3; should be same as its super-type Classify1 + assertTrue(classifyType3.canApplyToEntityType(entityTypeA)); // EntityA is allowed in Classify3, since it is allowed in Classify1 + assertFalse(classifyType3.canApplyToEntityType(entityTypeB)); // EntityB is not an allowed type in Classify3 and Classify1 + assertTrue(classifyType3.canApplyToEntityType(entityTypeC)); // EntityC is allowed in Classify3, since its super-type EntityA is allowed in Classify1 + assertTrue(classifyType3.canApplyToEntityType(entityTypeD)); // EntityD is allowed in Classify3. since its grand-super-type EntityA is allowed in Classify1 + + // verify restrictions on Classify3; should be same as its super-type Classify1 + assertFalse(classifyType4.canApplyToEntityType(entityTypeA)); // EntityA is not allowed in Classify4, though it is allowed in its super-types + assertFalse(classifyType4.canApplyToEntityType(entityTypeB)); // EntityB is not an allowed type in Classify4 + assertFalse(classifyType4.canApplyToEntityType(entityTypeC)); // EntityC is allowed in Classify4, though it is allowed in its super-types + assertTrue(classifyType4.canApplyToEntityType(entityTypeD)); // EntityD is allowed in Classify4 + + // Trying to duplicate the pattern where a classification(Classify6) is defined on Reference(EntityB) and a classification (Classify9) is defined on asset (EntityE), + // dataset (EntityF) inherits from both entityDefs. + assertTrue(classifyType6.canApplyToEntityType(entityTypeF)); // EntityF can be classified by Classify6 + assertTrue(classifyType9.canApplyToEntityType(entityTypeF)); // EntityF can be classified by Classify9 + + // check the that listing 2 entitytypes (with inheritance relaitonship) in any order allows classification to be applied to either entitytype. + assertTrue(classifyType5.canApplyToEntityType(entityTypeA)); // EntityA can be classified by Classify5 + assertTrue(classifyType5.canApplyToEntityType(entityTypeC)); // EntityC can be classified by Classify5 + assertTrue(classifyType10.canApplyToEntityType(entityTypeA)); // EntityA can be classified by Classify10 + assertTrue(classifyType10.canApplyToEntityType(entityTypeC)); // EntityC can be classified by Classify10 + + + } + @Test public void testClassificationTypeIsValidValue() { for (Object value : validValues) { http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasClassificationDefStoreV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasClassificationDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasClassificationDefStoreV1.java index e3aa4e0..8214cea 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasClassificationDefStoreV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasClassificationDefStoreV1.java @@ -316,6 +316,8 @@ class AtlasClassificationDefStoreV1 extends AtlasAbstractDefStoreV1 classifications) throws AtlasBaseException { - List entityClassifications = getClassificationNames(guid); + List entityClassifications = getClassificationNames(guid); + String entityTypeName = AtlasGraphUtilsV1.getTypeNameFromGuid(guid); + AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityTypeName); for (AtlasClassification classification : classifications) { String newClassification = classification.getTypeName(); @@ -737,6 +739,13 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "entity: " + guid + ", already associated with classification: " + newClassification); } + + // for each classification, check whether there are entities it should be restricted to + AtlasClassificationType classificationType = typeRegistry.getClassificationTypeByName(newClassification); + + if (!classificationType.canApplyToEntityType(entityType)) { + throw new AtlasBaseException(AtlasErrorCode.INVALID_ENTITY_FOR_CLASSIFICATION, guid, entityTypeName, newClassification); + } } } http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java index 227f7cd..1eb4183 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasGraphUtilsV1.java @@ -57,6 +57,7 @@ public class AtlasGraphUtilsV1 { public static final String PROPERTY_PREFIX = Constants.INTERNAL_PROPERTY_KEY_PREFIX + "type."; public static final String SUPERTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".supertype"; + public static final String ENTITYTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".entitytype"; public static final String VERTEX_TYPE = "typeSystem"; public static final String RELATIONSHIPTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".relationshipType"; http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java index f639ea5..603516d 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasTypeDefGraphStoreV1.java @@ -380,9 +380,43 @@ public class AtlasTypeDefGraphStoreV1 extends AtlasTypeDefGraphStore { } } - Set getSuperTypeNames(AtlasVertex vertex) { + public void createEntityTypeEdges(AtlasVertex classificationVertex, Set entityTypes) throws AtlasBaseException { + Set currentEntityTypes = getEntityTypeNames(classificationVertex); + String classificationTypeName = classificationVertex.getProperty(Constants.TYPENAME_PROPERTY_KEY, String.class); + + if (CollectionUtils.isNotEmpty(entityTypes)) { + if (!entityTypes.containsAll(currentEntityTypes)) { + throw new AtlasBaseException(AtlasErrorCode.ENTITYTYPE_REMOVAL_NOT_SUPPORTED, classificationTypeName); + } + + for (String entityType : entityTypes) { + AtlasVertex entityTypeVertex = findTypeVertexByNameAndCategory(entityType, TypeCategory.CLASS); + if (entityTypeVertex == null) { + throw new AtlasBaseException(AtlasErrorCode.CLASSIFICATIONDEF_INVALID_ENTITYTYPES, classificationTypeName,entityType); + + } + getOrCreateEdge(classificationVertex, entityTypeVertex, AtlasGraphUtilsV1.ENTITYTYPE_EDGE_LABEL); + } + } + } + + Set getSuperTypeNames(AtlasVertex vertex) { + return getTypeNamesFromEdges(vertex,AtlasGraphUtilsV1.SUPERTYPE_EDGE_LABEL); + } + + Set getEntityTypeNames(AtlasVertex vertex) { + return getTypeNamesFromEdges(vertex,AtlasGraphUtilsV1.ENTITYTYPE_EDGE_LABEL); + } + + /** + * Get the typename properties from the edges, that are associated with the vertex and have the supplied edge label. + * @param vertex + * @param edgeLabel + * @return set of type names + */ + private Set getTypeNamesFromEdges(AtlasVertex vertex,String edgeLabel) { Set ret = new HashSet<>(); - Iterable edges = vertex.getEdges(AtlasEdgeDirection.OUT, AtlasGraphUtilsV1.SUPERTYPE_EDGE_LABEL); + Iterable edges = vertex.getEdges(AtlasEdgeDirection.OUT, edgeLabel); for (AtlasEdge edge : edges) { ret.add(edge.getInVertex().getProperty(Constants.TYPENAME_PROPERTY_KEY, String.class)); http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java index 8638a7f..a7ed075 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStoreTest.java @@ -18,17 +18,13 @@ package org.apache.atlas.repository.store.graph; import com.google.inject.Inject; +import org.apache.atlas.RequestContextV1; import org.apache.atlas.TestModules; import org.apache.atlas.TestUtilsV2; -import org.apache.atlas.RequestContextV1; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.SearchFilter; -import org.apache.atlas.model.typedef.AtlasClassificationDef; -import org.apache.atlas.model.typedef.AtlasEntityDef; -import org.apache.atlas.model.typedef.AtlasEnumDef; -import org.apache.atlas.model.typedef.AtlasStructDef; +import org.apache.atlas.model.typedef.*; import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; -import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasType; import org.slf4j.Logger; @@ -38,11 +34,12 @@ import org.testng.annotations.BeforeTest; import org.testng.annotations.DataProvider; import org.testng.annotations.Guice; import org.testng.annotations.Test; - -import java.util.Arrays; import java.util.Collections; -import java.util.Date; import java.util.List; +import java.util.Set; +import java.util.HashSet; +import java.util.Arrays; +import java.util.Date; import static org.testng.Assert.*; @@ -389,6 +386,146 @@ public class AtlasTypeDefGraphStoreTest { } @Test(dependsOnMethods = "testGet") + public void testCreateClassificationDefWithValidEntityType(){ + final String entityTypeName ="testCreateClassificationDefWithValidEntityTypeEntity1"; + final String classificationTypeName ="testCreateClassificationDefWithValidEntityTypeClassification1"; + + List entityDefs = TestUtilsV2.getEntityWithName(entityTypeName); + + // Test Classification with entitytype + List classificationDefs = TestUtilsV2.getClassificationWithName(classificationTypeName); + + Set entityTypeNames = new HashSet(); + entityTypeNames.add(entityTypeName); + classificationDefs.get(0).setEntityTypes(entityTypeNames); + AtlasTypesDef toCreate = new AtlasTypesDef(Collections.emptyList(), + Collections.emptyList(), + classificationDefs, + entityDefs); + try { + AtlasTypesDef created = typeDefStore.createTypesDef(toCreate); + assertEquals(created.getClassificationDefs(), toCreate.getClassificationDefs(), + "Classification creation with valid entitytype should've succeeded"); + } catch (AtlasBaseException e) { + fail("Classification creation with valid entitytype should've succeeded. Failed with " + e.getMessage()); + } + } + + @Test(dependsOnMethods = "testGet") + public void testCreateWithInvalidEntityType(){ + final String classificationTypeName ="testCreateClassificationDefWithInvalidEntityTypeClassification1"; + // Test Classification with entitytype + List classificationDefs = TestUtilsV2.getClassificationWithName(classificationTypeName); + + Set entityTypeNames = new HashSet(); + entityTypeNames.add("cccc"); + classificationDefs.get(0).setEntityTypes(entityTypeNames); + AtlasTypesDef toCreate = new AtlasTypesDef(Collections.emptyList(), + Collections.emptyList(), + classificationDefs, + Collections.emptyList()); + try { + AtlasTypesDef created = typeDefStore.createTypesDef(toCreate); + fail("Classification creation with invalid entitytype should've failed"); + } catch (AtlasBaseException e) { + + } + } + + /** + * test that specifying an entitytype in a child classificationDef when then parent has unrestricted entityTypes fails. + */ + @Test(dependsOnMethods = "testGet") + public void testCreateWithInvalidEntityType2(){ + final String classificationTypeName1 ="testCreateClassificationDefWithInvalidEntityType2Classification1"; + final String classificationTypeName2 ="testCreateClassificationDefWithInvalidEntityType2Classification2"; + final String entityTypeName1 ="testCreateClassificationDefWithInvalidEntityType2Entity1"; + + // Test Classification with entitytype + AtlasClassificationDef classificationDef1 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName1); + AtlasClassificationDef classificationDef2 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName2); + List entityDefs = TestUtilsV2.getEntityWithName(entityTypeName1); + + + Set entityTypeNames = new HashSet(); + entityTypeNames.add(entityTypeName1); + + Set superTypes = new HashSet(); + superTypes.add(classificationTypeName1); + + classificationDef2.setSuperTypes(superTypes); + classificationDef1.setEntityTypes(entityTypeNames); + + TestUtilsV2.populateSystemAttributes(classificationDef1); + TestUtilsV2.populateSystemAttributes(classificationDef2); + + List classificationDefs = Arrays.asList(classificationDef1,classificationDef2); + + AtlasTypesDef toCreate = new AtlasTypesDef(Collections.emptyList(), + Collections.emptyList(), + classificationDefs, + Collections.emptyList()); + try { + AtlasTypesDef created = typeDefStore.createTypesDef(toCreate); + fail("Classification creation with invalid entitytype should've failed"); + } catch (AtlasBaseException e) { + + } + } + + /** + * test that specifying an entitytype in a child classificationDef which is not in the parent fails + */ + @Test(dependsOnMethods = "testGet") + public void testCreateWithInvalidEntityType3(){ + final String classificationTypeName1 ="testCreateClassificationDefWithInvalidEntityType3Classification1"; + final String classificationTypeName2 ="testCreateClassificationDefWithInvalidEntityType3Classification2"; + final String entityTypeName1 ="testCreateClassificationDefWithInvalidEntityType3Entity1"; + final String entityTypeName2 ="testCreateClassificationDefWithInvalidEntityType3Entity2"; + + + // Test Classification with entitytype + AtlasClassificationDef classificationDef1 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName1); + AtlasClassificationDef classificationDef2 = TestUtilsV2.getSingleClassificationWithName(classificationTypeName2); + AtlasEntityDef entityDef1 = TestUtilsV2.getSingleEntityWithName(entityTypeName1); + AtlasEntityDef entityDef2 = TestUtilsV2.getSingleEntityWithName(entityTypeName2); + + Set entityTypeNames1 = new HashSet(); + entityTypeNames1.add(entityTypeName1); + + Set entityTypeNames2 = new HashSet(); + entityTypeNames2.add(entityTypeName2); + + Set superTypes = new HashSet(); + superTypes.add(classificationTypeName1); + + classificationDef1.setEntityTypes(entityTypeNames1); + + + classificationDef2.setSuperTypes(superTypes); + classificationDef2.setEntityTypes(entityTypeNames2); + + TestUtilsV2.populateSystemAttributes(classificationDef1); + TestUtilsV2.populateSystemAttributes(classificationDef2); + TestUtilsV2.populateSystemAttributes(entityDef1); + TestUtilsV2.populateSystemAttributes(entityDef2); + + List classificationDefs = Arrays.asList(classificationDef1,classificationDef2); + List entityDefs = Arrays.asList(entityDef1,entityDef2); + + AtlasTypesDef toCreate = new AtlasTypesDef(Collections.emptyList(), + Collections.emptyList(), + classificationDefs, + entityDefs); + try { + AtlasTypesDef created = typeDefStore.createTypesDef(toCreate); + fail("Classification creation with invalid entitytype should've failed"); + } catch (AtlasBaseException e) { + + } + } + + @Test(dependsOnMethods = "testGet") public void testSearchFunctionality() { SearchFilter searchFilter = new SearchFilter(); searchFilter.setParam(SearchFilter.PARAM_SUPERTYPE, "Person"); http://git-wip-us.apache.org/repos/asf/atlas/blob/586b5eb2/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java index 62fad5b..8d04094 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityStoreV1Test.java @@ -941,7 +941,7 @@ public class AtlasEntityStoreV1Test { String guid = createdEntity.get(0).getGuid(); entityStore.addClassification(Arrays.asList(guid), new AtlasClassification(aTag.getName(), "testAttribute", "test-string")); } catch (AtlasBaseException e) { - fail("DB entity creation should've succeeded"); + fail("DB entity creation should've succeeded, e.getMessage() => " + e.getMessage()); } }