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 74FAC200CB3 for ; Mon, 26 Jun 2017 16:49:50 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id 737F6160BDE; Mon, 26 Jun 2017 14:49:50 +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 70E34160BD9 for ; Mon, 26 Jun 2017 16:49:48 +0200 (CEST) Received: (qmail 50744 invoked by uid 500); 26 Jun 2017 14:49:47 -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 50724 invoked by uid 99); 26 Jun 2017 14:49:45 -0000 Received: from pnap-us-west-generic-nat.apache.org (HELO spamd1-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 26 Jun 2017 14:49:45 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd1-us-west.apache.org (ASF Mail Server at spamd1-us-west.apache.org) with ESMTP id 53022CF80B for ; Mon, 26 Jun 2017 14:49:45 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd1-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: -4.231 X-Spam-Level: X-Spam-Status: No, score=-4.231 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, RCVD_IN_DNSWL_HI=-5, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, SPF_PASS=-0.001, T_RP_MATCHES_RCVD=-0.01] autolearn=disabled Received: from mx1-lw-eu.apache.org ([10.40.0.8]) by localhost (spamd1-us-west.apache.org [10.40.0.7]) (amavisd-new, port 10024) with ESMTP id NB6_EOGXF4m4 for ; Mon, 26 Jun 2017 14:49:41 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-lw-eu.apache.org (ASF Mail Server at mx1-lw-eu.apache.org) with SMTP id 38BC45FCB9 for ; Mon, 26 Jun 2017 14:49:39 +0000 (UTC) Received: (qmail 50698 invoked by uid 99); 26 Jun 2017 14:49:38 -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; Mon, 26 Jun 2017 14:49:38 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 53571E00B3; Mon, 26 Jun 2017 14:49:38 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: madhan@apache.org To: commits@atlas.incubator.apache.org Message-Id: <5fddfd7e09bd4719a77f07d0943a4852@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: incubator-atlas git commit: ATLAS-1891: added RelationshipDef validation during typesystem updates Date: Mon, 26 Jun 2017 14:49:38 +0000 (UTC) archived-at: Mon, 26 Jun 2017 14:49:50 -0000 Repository: incubator-atlas Updated Branches: refs/heads/master 4f16db450 -> 5bb2dcbeb ATLAS-1891: added RelationshipDef validation during typesystem updates Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/5bb2dcbe Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/5bb2dcbe Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/5bb2dcbe Branch: refs/heads/master Commit: 5bb2dcbeb366a2e09423811506078b8e5ddf19f3 Parents: 4f16db4 Author: David Radley Authored: Mon Jun 26 07:35:54 2017 -0700 Committer: Madhan Neethiraj Committed: Mon Jun 26 07:49:31 2017 -0700 ---------------------------------------------------------------------- .../java/org/apache/atlas/AtlasErrorCode.java | 18 +- .../org/apache/atlas/type/AtlasTypeUtil.java | 14 + .../store/graph/AtlasTypeDefGraphStore.java | 12 +- .../store/graph/v1/AtlasEntityDefStoreV1.java | 10 + .../store/graph/v1/AtlasGraphUtilsV1.java | 17 + .../graph/v1/AtlasRelationshipDefStoreV1.java | 154 +++++++-- .../graph/v1/AtlasTypeDefGraphStoreV1.java | 22 ++ .../test/java/org/apache/atlas/TestModules.java | 12 +- .../graph/AtlasRelationshipDefStoreV1Test.java | 332 +++++++++++++++++++ .../examples/CreateTypesFromJsonFileUtil.java | 109 ------ .../examples/UpdateTypesFromJsonFileUtil.java | 108 ------ 11 files changed, 552 insertions(+), 256 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/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 70480df..49ead6e 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java +++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java @@ -67,7 +67,7 @@ public enum AtlasErrorCode { INVALID_STRUCT_VALUE(400, "ATLAS-400-00-025", "not a valid struct value {0}"), INSTANCE_LINEAGE_INVALID_PARAMS(400, "ATLAS-400-00-026", "Invalid lineage query parameters passed {0}: {1}"), ATTRIBUTE_UPDATE_NOT_SUPPORTED(400, "ATLAS-400-00-027", "{0}.{1} : attribute update not supported"), - INVALID_VALUE(400, "ATLAS-400-00-028", "invalid value: {0}"), + INVALID_VALUE(400, "ATLAS-400-00-028", "invalid value: {0}"), BAD_REQUEST(400, "ATLAS-400-00-029", "{0}"), PARAMETER_PARSING_FAILED(400, "ATLAS-400-00-02A", "Parameter parsing failed at: {0}"), MISSING_MANDATORY_ATTRIBUTE(400, "ATLAS-400-00-02B", "Mandatory field {0}.{1} has empty/null value"), @@ -80,7 +80,13 @@ public enum AtlasErrorCode { RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER(400, "ATLAS-400-00-033", "COMPOSITION relationshipDef {0} cannot have a SET cardinality and be a container"), RELATIONSHIPDEF_LIST_ON_END(400, "ATLAS-400-00-034", "relationshipDef {0} cannot have a LIST cardinality on an end"), RELATIONSHIPDEF_INVALID_END_TYPE(400, "ATLAS-400-00-035", "relationshipDef {0} has invalid end type {1}"), - INVALID_RELATIONSHIP_END_TYPE(400, "ATLAS-400-00-036", "invalid end type for relationship {0}: expected {1}, found {2}"), + INVALID_RELATIONSHIP_END_TYPE(400, "ATLAS-400-00-036", "invalid update for relationshipDef {0}: new end type {1}, existing end type {2}"), + RELATIONSHIPDEF_INVALID_END1_UPDATE(400, "ATLAS-400-00-037", "invalid update for relationshipDef {0}: new end1 {1}, existing end1 {2}"), + RELATIONSHIPDEF_INVALID_END2_UPDATE(400, "ATLAS-400-00-038", "invalid update for relationshipDef {0}: new end2 {1}, existing end2 {2}"), + RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE(400, "ATLAS-400-00-039", "invalid update for relationship {0}: new relationshipDef category {1}, existing relationshipDef category {2}"), + RELATIONSHIPDEF_INVALID_NAME_UPDATE(400, "ATLAS-400-00-040", "invalid relationshipDef rename for relationship guid {0}: new name {1}, existing name {2}"), + RELATIONSHIPDEF_END1_NAME_INVALID(400, "ATLAS-400-00-020", "{0}: invalid end1 name. Name must not contain query keywords"), + RELATIONSHIPDEF_END2_NAME_INVALID(400, "ATLAS-400-00-020", "{0}: invalid end2 name. Name must not contain query keywords"), // All Not found enums go here TYPE_NAME_NOT_FOUND(404, "ATLAS-404-00-001", "Given typename {0} was invalid"), TYPE_GUID_NOT_FOUND(404, "ATLAS-404-00-002", "Given type guid {0} was invalid"), @@ -94,14 +100,14 @@ public enum AtlasErrorCode { INSTANCE_NOT_FOUND(404, "ATLAS-404-00-00B", "Given instance is invalid/not found: {0}"), RELATIONSHIP_GUID_NOT_FOUND(404, "ATLAS-404-00-00C", "Given relationship guid {0} is invalid/not found"), RELATIONSHIP_CRUD_INVALID_PARAMS(404, "ATLAS-404-00-00D", "Invalid relationship creation/updation parameters passed : {0}"), - - // All data conflict errors go here + // All data conflict errors go here TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"), TYPE_HAS_REFERENCES(409, "ATLAS-409-00-002", "Given type {0} has references"), INSTANCE_ALREADY_EXISTS(409, "ATLAS-409-00-003", "failed to update entity: {0}"), RELATIONSHIP_ALREADY_EXISTS(409, "ATLAS-409-00-004", "relationship {0} already exists between entities {1} and {2}"), + TYPE_HAS_RELATIONSHIPS(409, "ATLAS-409-00-005", "Given type {0} has associated relationshipDefs"), - // All internal errors go here + // All internal errors go here INTERNAL_ERROR(500, "ATLAS-500-00-001", "Internal server error {0}"), INDEX_CREATION_FAILED(500, "ATLAS-500-00-002", "Index creation failed for {0}"), INDEX_ROLLBACK_FAILED(500, "ATLAS-500-00-003", "Index rollback failed for {0}"), @@ -155,4 +161,4 @@ public enum AtlasErrorCode { public String getErrorCode() { return errorCode; } -} +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/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 3125668..3f39541 100644 --- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java +++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java @@ -23,6 +23,8 @@ import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.typedef.*; import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef; +import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags; +import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory; 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; @@ -241,6 +243,18 @@ public class AtlasTypeUtil { return new AtlasEntityDef(name, description, version, Arrays.asList(attrDefs), superTypes); } + public static AtlasRelationshipDef createRelationshipTypeDef(String name, + String description, + String version, + RelationshipCategory relationshipCategory, + PropagateTags propagateTags, + AtlasRelationshipEndDef endDef1, + AtlasRelationshipEndDef endDef2, + AtlasAttributeDef... attrDefs) { + return new AtlasRelationshipDef(name, description, version, relationshipCategory, propagateTags, + endDef1, endDef2, Arrays.asList(attrDefs)); + } + public static AtlasTypesDef getTypesDef(List enums, List structs, List traits, http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java index aefd168..9d9c59d 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasTypeDefGraphStore.java @@ -412,11 +412,12 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore, Activ AtlasTypesDef ret = updateGraphStore(typesDef, ttr); if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasTypeDefGraphStore.updateTypesDef(enums={}, structs={}, classfications={}, entities={})", + LOG.debug("<== AtlasTypeDefGraphStore.updateTypesDef(enums={}, structs={}, classfications={}, entities={}, relationships={})", CollectionUtils.size(typesDef.getEnumDefs()), CollectionUtils.size(typesDef.getStructDefs()), CollectionUtils.size(typesDef.getClassificationDefs()), - CollectionUtils.size(typesDef.getEntityDefs())); + CollectionUtils.size(typesDef.getEntityDefs()), + CollectionUtils.size(typesDef.getRelationshipDefs())); } return ret; @@ -857,6 +858,7 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore, Activ AtlasStructDefStore structDefStore = getStructDefStore(ttr); AtlasClassificationDefStore classifiDefStore = getClassificationDefStore(ttr); AtlasEntityDefStore entityDefStore = getEntityDefStore(ttr); + AtlasRelationshipDefStore relationDefStore = getRelationshipDefStore(ttr); if (CollectionUtils.isNotEmpty(typesDef.getEnumDefs())) { for (AtlasEnumDef enumDef : typesDef.getEnumDefs()) { @@ -882,6 +884,12 @@ public abstract class AtlasTypeDefGraphStore implements AtlasTypeDefStore, Activ } } + if (CollectionUtils.isNotEmpty(typesDef.getRelationshipDefs())) { + for (AtlasRelationshipDef relationshipDef : typesDef.getRelationshipDefs()) { + ret.getRelationshipDefs().add(relationDefStore.update(relationshipDef)); + } + } + return ret; } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java index 8046234..d6cb2fd 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasEntityDefStoreV1.java @@ -265,6 +265,11 @@ public class AtlasEntityDefStoreV1 extends AtlasAbstractDefStoreV1 implements At throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } + // error if we are trying to delete an entityDef that has a relationshipDef + if (typeDefStore.hasIncomingEdgesWithLabel(ret, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL)){ + throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_RELATIONSHIPS, name); + } + typeDefStore.deleteTypeVertexOutEdges(ret); if (LOG.isDebugEnabled()) { @@ -313,6 +318,11 @@ public class AtlasEntityDefStoreV1 extends AtlasAbstractDefStoreV1 implements At throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); } + // error if we are trying to delete an entityDef that has a relationshipDef + if (typeDefStore.hasIncomingEdgesWithLabel(ret, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL)){ + throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_RELATIONSHIPS, typeName); + } + typeDefStore.deleteTypeVertexOutEdges(ret); if (LOG.isDebugEnabled()) { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/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 00fe94b..42bd58f 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 @@ -50,6 +50,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 VERTEX_TYPE = "typeSystem"; + public static final String RELATIONSHIPTYPE_EDGE_LABEL = PROPERTY_PREFIX + ".relationshipType"; public static String getTypeDefPropertyKey(AtlasBaseTypeDef typeDef) { @@ -289,6 +290,22 @@ public class AtlasGraphUtilsV1 { return vertex; } + public static boolean relationshipTypeHasInstanceEdges(String typeName) throws AtlasBaseException { + AtlasGraphQuery query = AtlasGraphProvider.getGraphInstance() + .query() + .has(Constants.TYPE_NAME_PROPERTY_KEY, AtlasGraphQuery.ComparisionOperator.EQUAL, typeName); + + Iterator results = query.edges().iterator(); + + boolean hasInstanceEdges = results != null && results.hasNext(); + + if (LOG.isDebugEnabled()) { + LOG.debug("relationshipType {} has instance edges {}", typeName, hasInstanceEdges); + } + + return hasInstanceEdges; + } + private static String toString(AtlasElement element) { if (element instanceof AtlasVertex) { return toString((AtlasVertex) element); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java index 6992e22..194c546 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipDefStoreV1.java @@ -17,13 +17,17 @@ */ package org.apache.atlas.repository.store.graph.v1; +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.typedef.AtlasRelationshipDef; import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory; import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags; import org.apache.atlas.model.typedef.AtlasRelationshipEndDef; +import org.apache.atlas.query.QueryParser; import org.apache.atlas.repository.Constants; +import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.store.graph.AtlasRelationshipDefStore; import org.apache.atlas.type.AtlasRelationshipType; @@ -34,6 +38,7 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.inject.Inject; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -44,6 +49,7 @@ import java.util.List; public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 implements AtlasRelationshipDefStore { private static final Logger LOG = LoggerFactory.getLogger(AtlasRelationshipDefStoreV1.class); + @Inject public AtlasRelationshipDefStoreV1(AtlasTypeDefGraphStoreV1 typeDefStore, AtlasTypeRegistry typeRegistry) { super(typeDefStore, typeRegistry); } @@ -62,21 +68,51 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme throw new AtlasBaseException(AtlasErrorCode.TYPE_MATCH_FAILED, relationshipDef.getName(), TypeCategory.RELATIONSHIP.name()); } - AtlasVertex ret = typeDefStore.findTypeVertexByName(relationshipDef.getName()); + AtlasVertex relationshipDefVertex = typeDefStore.findTypeVertexByName(relationshipDef.getName()); - if (ret != null) { + if (relationshipDefVertex != null) { throw new AtlasBaseException(AtlasErrorCode.TYPE_ALREADY_EXISTS, relationshipDef.getName()); } - ret = typeDefStore.createTypeVertex(relationshipDef); + relationshipDefVertex = typeDefStore.createTypeVertex(relationshipDef); - updateVertexPreCreate(relationshipDef, (AtlasRelationshipType) type, ret); + updateVertexPreCreate(relationshipDef, (AtlasRelationshipType) type, relationshipDefVertex); - if (LOG.isDebugEnabled()) { - LOG.debug("<== AtlasRelationshipDefStoreV1.preCreate({}): {}", relationshipDef, ret); + final AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1(); + final String type1 = endDef1.getType(); + final AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2(); + final String type2 = endDef2.getType(); + final String name1 = endDef1.getName(); + final String name2 = endDef2.getName(); + + AtlasVertex end1TypeVertex = typeDefStore.findTypeVertexByName(type1); + + AtlasVertex end2TypeVertex = typeDefStore.findTypeVertexByName(type2); + // create an edge between the relationshipDef and each of the entityDef vertices. + AtlasEdge edge1 = typeDefStore.getOrCreateEdge(relationshipDefVertex, end1TypeVertex, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL); + + /* + Where edge1 and edge2 have the same names and types we do not need a second edge. + We are not invoking the equals method on the AtlasRelationshipedDef, as we only want 1 edge even if propagateTags or other properties are different. + */ + + if (!type1.equals(type2) && name1.equals(name2)) { + AtlasEdge edge2 = typeDefStore.getOrCreateEdge(relationshipDefVertex, end2TypeVertex, AtlasGraphUtilsV1.RELATIONSHIPTYPE_EDGE_LABEL); + + if (LOG.isDebugEnabled()) { + LOG.debug("AtlasRelationshipDefStoreV1.preCreate({}): created relationshipDef vertex {}," + + " edge1 as {}, edge2 as {} ", relationshipDef, relationshipDefVertex, edge1, edge2); + } + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("AtlasRelationshipDefStoreV1.preCreate({}): created relationshipDef vertex {}," + + " and one edge as {} , because end1 and and end2 has same type and name", relationshipDef, relationshipDefVertex, edge1); + } } - return ret; + LOG.debug("<== AtlasRelationshipDefStoreV1.preCreate({}): {}", relationshipDef, relationshipDefVertex); + + return relationshipDefVertex; } @Override @@ -207,7 +243,7 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } - updateVertexPreUpdate(relationshipDef, (AtlasRelationshipType) type, vertex); + preUpdateCheck(relationshipDef, (AtlasRelationshipType) type, vertex); AtlasRelationshipDef ret = toRelationshipDef(vertex); @@ -239,8 +275,9 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme throw new AtlasBaseException(AtlasErrorCode.TYPE_GUID_NOT_FOUND, guid); } - updateVertexPreUpdate(relationshipDef, (AtlasRelationshipType) type, vertex); - // TODO delete / create edges to entitytypes + preUpdateCheck(relationshipDef, (AtlasRelationshipType) type, vertex); + // updates should not effect the edges between the types as we do not allow updates that change the endpoints. + AtlasRelationshipDef ret = toRelationshipDef(vertex); if (LOG.isDebugEnabled()) { @@ -262,11 +299,11 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_NOT_FOUND, name); } - if (AtlasGraphUtilsV1.typeHasInstanceVertex(name)) { + if (AtlasGraphUtilsV1.relationshipTypeHasInstanceEdges(name)) { throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, name); } - // TODO delete the edges to the other types + typeDefStore.deleteTypeVertexOutEdges(ret); if (LOG.isDebugEnabled()) { LOG.debug("<== AtlasRelationshipDefStoreV1.preDeleteByName({}): {}", name, ret); @@ -310,11 +347,11 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme String typeName = AtlasGraphUtilsV1.getProperty(ret, Constants.TYPENAME_PROPERTY_KEY, String.class); - if (AtlasGraphUtilsV1.typeHasInstanceVertex(typeName)) { + if (AtlasGraphUtilsV1.relationshipTypeHasInstanceEdges(typeName)) { throw new AtlasBaseException(AtlasErrorCode.TYPE_HAS_REFERENCES, typeName); } - // TODO delete the edges to the other types + typeDefStore.deleteTypeVertexOutEdges(ret); if (LOG.isDebugEnabled()) { LOG.debug("<== AtlasRelationshipDefStoreV1.preDeleteByGuid({}): {}", guid, ret); @@ -346,18 +383,91 @@ public class AtlasRelationshipDefStoreV1 extends AtlasAbstractDefStoreV1 impleme private void updateVertexPreCreate(AtlasRelationshipDef relationshipDef, AtlasRelationshipType relationshipType, AtlasVertex vertex) throws AtlasBaseException { + AtlasRelationshipEndDef end1 = relationshipDef.getEndDef1(); + AtlasRelationshipEndDef end2 = relationshipDef.getEndDef2(); + + // check whether the names added on the relationship Ends are reserved if required. + final boolean allowReservedKeywords; + try { + allowReservedKeywords = ApplicationProperties.get().getBoolean(ALLOW_RESERVED_KEYWORDS, true); + } catch (AtlasException e) { + throw new AtlasBaseException(e); + } + + if (!allowReservedKeywords) { + if (QueryParser.isKeyword(end1.getName())) { + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_END1_NAME_INVALID, end1.getName()); + } + + if (QueryParser.isKeyword(end2.getName())) { + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_END2_NAME_INVALID, end2.getName()); + } + } + AtlasStructDefStoreV1.updateVertexPreCreate(relationshipDef, relationshipType, vertex, typeDefStore); // Update ends - vertex.setProperty(Constants.RELATIONSHIPTYPE_END1_KEY, AtlasType.toJson(relationshipDef.getEndDef1())); - vertex.setProperty(Constants.RELATIONSHIPTYPE_END2_KEY, AtlasType.toJson(relationshipDef.getEndDef2())); - // Update RelationshipCategory - vertex.setProperty(Constants.RELATIONSHIPTYPE_CATEGORY_KEY, relationshipDef.getRelationshipCategory().name()); - vertex.setProperty(Constants.RELATIONSHIPTYPE_TAG_PROPAGATION_KEY, relationshipDef.getPropagateTags().name()); + setVertexPropertiesFromRelationshipDef(relationshipDef, vertex); } - private void updateVertexPreUpdate(AtlasRelationshipDef relationshipDef, AtlasRelationshipType relationshipType, - AtlasVertex vertex) throws AtlasBaseException { - AtlasStructDefStoreV1.updateVertexPreUpdate(relationshipDef, relationshipType, vertex, typeDefStore); + private void preUpdateCheck(AtlasRelationshipDef newRelationshipDef, AtlasRelationshipType relationshipType, + AtlasVertex vertex) throws AtlasBaseException { + // We will not support an update to endpoints or category key + AtlasRelationshipDef existingRelationshipDef = toRelationshipDef(vertex); + + preUpdateCheck(newRelationshipDef, existingRelationshipDef); + // we do allow change to tag propagation and the addition of new attributes. + + AtlasStructDefStoreV1.updateVertexPreUpdate(newRelationshipDef, relationshipType, vertex, typeDefStore); + + setVertexPropertiesFromRelationshipDef(newRelationshipDef, vertex); + } + + /** + * Check ends are the same and relationshipCategory is the same. + * + * We do this by comparing 2 relationshipDefs to avoid exposing the AtlasVertex to unit testing. + * + * @param newRelationshipDef + * @param existingRelationshipDef + * @throws AtlasBaseException + */ + public static void preUpdateCheck(AtlasRelationshipDef newRelationshipDef, AtlasRelationshipDef existingRelationshipDef) throws AtlasBaseException { + // do not allow renames of the Def. + String existingName = existingRelationshipDef.getName(); + String newName = newRelationshipDef.getName(); + + if (!existingName.equals(newName)) { + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_NAME_UPDATE, + newRelationshipDef.getGuid(),existingName, newName); + } + + RelationshipCategory existingRelationshipCategory = existingRelationshipDef.getRelationshipCategory(); + RelationshipCategory newRelationshipCategory = newRelationshipDef.getRelationshipCategory(); + + if ( !existingRelationshipCategory.equals(newRelationshipCategory)){ + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE, + newRelationshipDef.getName(),newRelationshipCategory.name(), + existingRelationshipCategory.name() ); + } + + AtlasRelationshipEndDef existingEnd1 = existingRelationshipDef.getEndDef1(); + AtlasRelationshipEndDef newEnd1 = newRelationshipDef.getEndDef1(); + + if ( !newEnd1.equals(existingEnd1) ) { + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END1_UPDATE, + newRelationshipDef.getName(), newEnd1.toString(), existingEnd1.toString()); + } + + AtlasRelationshipEndDef existingEnd2 = existingRelationshipDef.getEndDef2(); + AtlasRelationshipEndDef newEnd2 = newRelationshipDef.getEndDef2(); + + if ( !newEnd2.equals(existingEnd2) ) { + throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END2_UPDATE, + newRelationshipDef.getName(), newEnd2.toString(), existingEnd2.toString()); + } + } + + public static void setVertexPropertiesFromRelationshipDef(AtlasRelationshipDef relationshipDef, AtlasVertex vertex) { vertex.setProperty(Constants.RELATIONSHIPTYPE_END1_KEY, AtlasType.toJson(relationshipDef.getEndDef1())); vertex.setProperty(Constants.RELATIONSHIPTYPE_END2_KEY, AtlasType.toJson(relationshipDef.getEndDef2())); // Update RelationshipCategory http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/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 2ba4144..6037d43 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 @@ -242,6 +242,28 @@ public class AtlasTypeDefGraphStoreV1 extends AtlasTypeDefGraphStore { } } + /** + * Look to see if there are any IN edges with the supplied label + * @param vertex + * @param label + * @return + * @throws AtlasBaseException + */ + boolean hasIncomingEdgesWithLabel(AtlasVertex vertex, String label) throws AtlasBaseException { + boolean foundEdges = false; + Iterator inEdges = vertex.getEdges(AtlasEdgeDirection.IN).iterator(); + + while (inEdges.hasNext()) { + AtlasEdge edge = inEdges.next(); + + if (label.equals(edge.getLabel())) { + foundEdges = true; + break; + } + } + return foundEdges; + } + void deleteTypeVertex(AtlasVertex vertex) throws AtlasBaseException { Iterator inEdges = vertex.getEdges(AtlasEdgeDirection.IN).iterator(); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/repository/src/test/java/org/apache/atlas/TestModules.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/TestModules.java b/repository/src/test/java/org/apache/atlas/TestModules.java index d28956d..fa2ac0d 100644 --- a/repository/src/test/java/org/apache/atlas/TestModules.java +++ b/repository/src/test/java/org/apache/atlas/TestModules.java @@ -47,16 +47,9 @@ import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.impexp.ExportService; import org.apache.atlas.repository.store.graph.AtlasEntityDefStore; import org.apache.atlas.repository.store.graph.AtlasEntityStore; +import org.apache.atlas.repository.store.graph.AtlasRelationshipDefStore; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; -import org.apache.atlas.repository.store.graph.v1.AtlasEntityChangeNotifier; -import org.apache.atlas.repository.store.graph.v1.AtlasEntityDefStoreV1; -import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1; -import org.apache.atlas.repository.store.graph.v1.AtlasRelationshipStoreV1; -import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper; -import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.*; import org.apache.atlas.repository.typestore.GraphBackedTypeStore; import org.apache.atlas.repository.typestore.ITypeStore; import org.apache.atlas.repository.typestore.StoreBackedTypeCache; @@ -136,6 +129,7 @@ public class TestModules { //For testing bind(AtlasEntityDefStore.class).to(AtlasEntityDefStoreV1.class).asEagerSingleton(); + bind(AtlasRelationshipDefStore.class).to(AtlasRelationshipDefStoreV1.class).asEagerSingleton(); bind(AtlasTypeRegistry.class).asEagerSingleton(); bind(EntityGraphMapper.class).asEagerSingleton(); bind(ExportService.class).asEagerSingleton(); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java new file mode 100644 index 0000000..00d4977 --- /dev/null +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStoreV1Test.java @@ -0,0 +1,332 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.atlas.repository.store.graph; + +import com.google.inject.Inject; +import org.apache.atlas.ApplicationProperties; +import org.apache.atlas.AtlasErrorCode; +import org.apache.atlas.AtlasException; +import org.apache.atlas.TestModules; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.typedef.AtlasRelationshipDef; +import org.apache.atlas.model.typedef.AtlasRelationshipEndDef; +import org.apache.atlas.model.typedef.AtlasStructDef; +import org.apache.atlas.repository.graph.AtlasGraphProvider; +import org.apache.atlas.repository.store.graph.v1.AtlasAbstractDefStoreV1; +import org.apache.atlas.repository.store.graph.v1.AtlasRelationshipDefStoreV1; +import org.apache.atlas.type.AtlasTypeUtil; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import static org.testng.AssertJUnit.fail; + +/** + * Tests for AtlasRelationshipStoreV1 + */ +@Guice(modules = TestModules.TestOnlyModule.class) +public class AtlasRelationshipDefStoreV1Test { + + @Inject + private + AtlasRelationshipDefStore relationshipDefStore; + + @DataProvider + public Object[][] invalidAttributeNameWithReservedKeywords(){ + AtlasRelationshipDef invalidAttrNameType = + AtlasTypeUtil.createRelationshipTypeDef("Invalid_Attribute_Type", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeB", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("order", "string"), + AtlasTypeUtil.createRequiredAttrDef("limit", "string")); + + return new Object[][] {{ + invalidAttrNameType + }}; + } + @DataProvider + public Object[][] updateValidProperties(){ + AtlasRelationshipDef existingType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","0" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef newType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", + "description1", // updated + "1" , // updated + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, // updated + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + + return new Object[][] {{ + existingType, + newType + }}; + } + + + @DataProvider + public Object[][] updateRename(){ + AtlasRelationshipDef existingType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef newType = + AtlasTypeUtil.createRelationshipTypeDef("basicType2", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + + return new Object[][] {{ + existingType, + newType + }}; + } + @DataProvider + public Object[][] updateRelCat(){ + AtlasRelationshipDef existingType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef newType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.AGGREGATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + + return new Object[][] {{ + existingType, + newType + }}; + } + @DataProvider + public Object[][] updateEnd1(){ + AtlasRelationshipDef existingType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef changeType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef changeAttr = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef changeCardinality = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + + return new Object[][]{ + { + existingType, + changeType + }, + { + existingType, + changeAttr + }, + { + existingType, + changeCardinality + } + }; + } + @DataProvider + public Object[][] updateEnd2(){ + AtlasRelationshipDef existingType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + AtlasRelationshipDef changeType = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeE", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef changeAttr = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + AtlasRelationshipDef changeCardinality = + AtlasTypeUtil.createRelationshipTypeDef("basicType", "description","" , + AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, + AtlasRelationshipDef.PropagateTags.BOTH, + new AtlasRelationshipEndDef("typeC", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE), + new AtlasRelationshipEndDef("typeD", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST), + + AtlasTypeUtil.createRequiredAttrDef("aaaa", "string"), + AtlasTypeUtil.createRequiredAttrDef("bbbb", "string")); + + + return new Object[][]{ + { + existingType, + changeType + }, + { + existingType, + changeAttr + }, + { + existingType, + changeCardinality + } + }; + } + + @Test(dataProvider = "invalidAttributeNameWithReservedKeywords") + public void testCreateTypeWithReservedKeywords(AtlasRelationshipDef atlasRelationshipDef) throws AtlasException { + try { + ApplicationProperties.get().setProperty(AtlasAbstractDefStoreV1.ALLOW_RESERVED_KEYWORDS, false); + relationshipDefStore.create(atlasRelationshipDef, null); + } catch (AtlasBaseException e) { + Assert.assertEquals(e.getAtlasErrorCode(), AtlasErrorCode.ATTRIBUTE_NAME_INVALID); + } + } + + @Test(dataProvider = "updateValidProperties") + public void testupdateVertexPreUpdatepropagateTags(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) throws AtlasBaseException { + AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef); + } + + @Test(dataProvider = "updateRename") + public void testupdateVertexPreUpdateRename(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) { + + try { + AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef); + fail("expected error"); + } catch (AtlasBaseException e) { + if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_NAME_UPDATE)){ + fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode()); + } + } + } + @Test(dataProvider = "updateRelCat") + public void testupdateVertexPreUpdateRelcat(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) { + + try { + AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef); + fail("expected error"); + } catch (AtlasBaseException e) { + if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_CATEGORY_UPDATE)){ + fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode()); + } + } + } + @Test(dataProvider = "updateEnd1") + public void testupdateVertexPreUpdateEnd1(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) { + + try { + AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef); + fail("expected error"); + } catch (AtlasBaseException e) { + if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END1_UPDATE)){ + fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode()); + } + } + } + + @Test(dataProvider = "updateEnd2") + public void testupdateVertexPreUpdateEnd2(AtlasRelationshipDef existingRelationshipDef,AtlasRelationshipDef newRelationshipDef) { + + try { + AtlasRelationshipDefStoreV1.preUpdateCheck(existingRelationshipDef,newRelationshipDef); + fail("expected error"); + } catch (AtlasBaseException e) { + if (!e.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END2_UPDATE)){ + fail("unexpected AtlasErrorCode "+e.getAtlasErrorCode()); + } + } + } + @AfterClass + public void clear(){ + AtlasGraphProvider.cleanup(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java b/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java deleted file mode 100644 index 82d6f2e..0000000 --- a/webapp/src/main/java/org/apache/atlas/examples/CreateTypesFromJsonFileUtil.java +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.atlas.examples; - -import java.io.Console; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasBaseClient; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasException; -import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.configuration.Configuration; - -import com.google.common.annotations.VisibleForTesting; - -/** - * A driver that sets up types supplied in a file. - */ -public class CreateTypesFromJsonFileUtil extends AtlasBaseClient{ - public static final String ATLAS_REST_ADDRESS = "atlas.rest.address"; - - public static void main(String[] args) throws Exception { - - Console console = System.console(); - if (console == null) { - System.err.println("No console."); - System.exit(1); - } - String[] basicAuthUsernamePassword = null; - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput(); - } - AtlasClientV2 atlasClientV2 = getAtlasClientV2(args, basicAuthUsernamePassword); - - - String createFileName = console.readLine("Enter fileName containing TypeDefs for create:- "); - File createFile = new File(createFileName); - String createJsonStr = new String( Files.readAllBytes(createFile.toPath()), StandardCharsets.UTF_8); - - System.err.println("create json is :\n" + createJsonStr); - - runTypeCreation(createJsonStr,atlasClientV2); -// String updateFileName = console.readLine("Enter fileName containing TypeDefs for update:- "); -// File updateFile = new File(updateFileName); -// String updateJsonStr = new String( Files.readAllBytes(updateFile.toPath()), StandardCharsets.UTF_8); -// System.err.println("update json is :\n" + updateJsonStr); -// runTypeUpdate(updateJsonStr,atlasClientV2); - } - - @VisibleForTesting - static void runTypeCreation(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception { - AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class); - atlasClientV2.createAtlasTypeDefs(typesDef); - } - @VisibleForTesting - static void runTypeUpdate(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception { - AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class); - atlasClientV2.updateAtlasTypeDefs(typesDef); - } - - private static AtlasClientV2 getAtlasClientV2(String[] args, String[] basicAuthUsernamePassword) throws AtlasException { - String[] urls = getServerUrl(args); - - AtlasClientV2 atlasClientV2; - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClientV2 =new AtlasClientV2(urls,basicAuthUsernamePassword); - } else { - atlasClientV2 = new AtlasClientV2(urls); - } - return atlasClientV2; - } - - static String[] getServerUrl(String[] args) throws AtlasException { - if (args.length > 0) { - return args[0].split(","); - } - - Configuration configuration = ApplicationProperties.get(); - String[] urls = configuration.getStringArray(ATLAS_REST_ADDRESS); - if (urls == null || urls.length == 0) { - System.out.println("Usage: quick_start.py ://: like http://localhost:21000>"); - System.exit(-1); - } - - return urls; - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/5bb2dcbe/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java b/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java deleted file mode 100644 index 3b67706..0000000 --- a/webapp/src/main/java/org/apache/atlas/examples/UpdateTypesFromJsonFileUtil.java +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.atlas.examples; - -import com.google.common.annotations.VisibleForTesting; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasBaseClient; -import org.apache.atlas.AtlasClientV2; -import org.apache.atlas.AtlasException; -import org.apache.atlas.model.typedef.AtlasTypesDef; -import org.apache.atlas.type.AtlasType; -import org.apache.atlas.utils.AuthenticationUtil; -import org.apache.commons.configuration.Configuration; - -import java.io.Console; -import java.io.File; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; - -/** - * A driver that sets up types supplied in a file. - */ -public class UpdateTypesFromJsonFileUtil extends AtlasBaseClient{ - public static final String ATLAS_REST_ADDRESS = "atlas.rest.address"; - - public static void main(String[] args) throws Exception { - - Console console = System.console(); - if (console == null) { - System.err.println("No console."); - System.exit(1); - } - String[] basicAuthUsernamePassword = null; - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - basicAuthUsernamePassword = AuthenticationUtil.getBasicAuthenticationInput(); - } - AtlasClientV2 atlasClientV2 = getAtlasClientV2(args, basicAuthUsernamePassword); - - - String createFileName = console.readLine("Enter fileName containing TypeDefs for create:- "); - File createFile = new File(createFileName); - String createJsonStr = new String( Files.readAllBytes(createFile.toPath()), StandardCharsets.UTF_8); - - System.err.println("create json is :\n" + createJsonStr); - - runTypeCreation(createJsonStr,atlasClientV2); -// String updateFileName = console.readLine("Enter fileName containing TypeDefs for update:- "); -// File updateFile = new File(updateFileName); -// String updateJsonStr = new String( Files.readAllBytes(updateFile.toPath()), StandardCharsets.UTF_8); -// System.err.println("update json is :\n" + updateJsonStr); -// runTypeUpdate(updateJsonStr,atlasClientV2); - } - - @VisibleForTesting - static void runTypeCreation(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception { - AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class); - atlasClientV2.createAtlasTypeDefs(typesDef); - } - @VisibleForTesting - static void runTypeUpdate(String jsonStr,AtlasClientV2 atlasClientV2) throws Exception { - AtlasTypesDef typesDef = AtlasType.fromJson(jsonStr, AtlasTypesDef.class); - atlasClientV2.updateAtlasTypeDefs(typesDef); - } - - private static AtlasClientV2 getAtlasClientV2(String[] args, String[] basicAuthUsernamePassword) throws AtlasException { - String[] urls = getServerUrl(args); - - AtlasClientV2 atlasClientV2; - - if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) { - atlasClientV2 =new AtlasClientV2(urls,basicAuthUsernamePassword); - } else { - atlasClientV2 = new AtlasClientV2(urls); - } - return atlasClientV2; - } - - static String[] getServerUrl(String[] args) throws AtlasException { - if (args.length > 0) { - return args[0].split(","); - } - - Configuration configuration = ApplicationProperties.get(); - String[] urls = configuration.getStringArray(ATLAS_REST_ADDRESS); - if (urls == null || urls.length == 0) { - System.out.println("Usage: quick_start.py ://: like http://localhost:21000>"); - System.exit(-1); - } - - return urls; - } -} \ No newline at end of file