You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/06/11 19:27:15 UTC
[2/2] incubator-atlas git commit: ATLAS-1852: create relationship-def
ATLAS-1852: create relationship-def
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/6b9399e0
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/6b9399e0
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/6b9399e0
Branch: refs/heads/master
Commit: 6b9399e00dcd2fb2b231c91064dfe15f46feaf1d
Parents: e0072e5
Author: David Radley <da...@uk.ibm.com>
Authored: Sun Jun 11 11:57:50 2017 -0700
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Sun Jun 11 12:26:19 2017 -0700
----------------------------------------------------------------------
.../org/apache/atlas/repository/Constants.java | 6 +
.../java/org/apache/atlas/AtlasErrorCode.java | 9 +-
.../org/apache/atlas/model/TypeCategory.java | 2 +-
.../atlas/model/typedef/AtlasBaseTypeDef.java | 16 +
.../model/typedef/AtlasRelationshipDef.java | 279 +++++++++++++
.../typedef/AtlasRelationshipEndPointDef.java | 193 +++++++++
.../atlas/model/typedef/AtlasTypesDef.java | 66 ++-
.../apache/atlas/store/AtlasTypeDefStore.java | 10 +
.../atlas/type/AtlasRelationshipType.java | 151 +++++++
.../apache/atlas/type/AtlasTypeRegistry.java | 99 +++--
.../org/apache/atlas/type/AtlasTypeUtil.java | 39 +-
.../org/apache/atlas/model/ModelTestUtil.java | 68 ++-
.../model/typedef/TestAtlasRelationshipDef.java | 96 +++++
.../atlas/type/TestAtlasRelationshipType.java | 107 +++++
.../store/graph/AtlasRelationshipDefStore.java | 52 +++
.../store/graph/AtlasTypeDefGraphStore.java | 135 ++++--
.../graph/v1/AtlasRelationshipDefStoreV1.java | 409 +++++++++++++++++++
.../graph/v1/AtlasTypeDefGraphStoreV1.java | 58 +--
.../atlas/typesystem/types/DataTypes.java | 3 +-
.../examples/CreateTypesFromJsonFileUtil.java | 109 +++++
.../examples/UpdateTypesFromJsonFileUtil.java | 108 +++++
.../atlas/web/resources/TypesResource.java | 2 +-
.../org/apache/atlas/web/rest/TypesREST.java | 49 ++-
23 files changed, 1923 insertions(+), 143 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/common/src/main/java/org/apache/atlas/repository/Constants.java
----------------------------------------------------------------------
diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java b/common/src/main/java/org/apache/atlas/repository/Constants.java
index bcdf08c..b07934b 100644
--- a/common/src/main/java/org/apache/atlas/repository/Constants.java
+++ b/common/src/main/java/org/apache/atlas/repository/Constants.java
@@ -57,6 +57,11 @@ public final class Constants {
public static final String TYPEVERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.version";
public static final String TYPEOPTIONS_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.options";
+ // relationship def constants
+ public static final String RELATIONSHIPTYPE_ENDPOINT1_KEY = "endPointDef1";
+ public static final String RELATIONSHIPTYPE_ENDPOINT2_KEY = "endPointDef2";
+ public static final String RELATIONSHIPTYPE_CATEGORY_KEY = "relationshipCategory";
+ public static final String RELATIONSHIPTYPE_TAG_PROPAGATION_KEY = "tagPropagation";
/**
* Trait names property key and index name.
*/
@@ -92,6 +97,7 @@ public final class Constants {
public static final String QUALIFIED_NAME = "Referenceable.qualifiedName";
public static final String TYPE_NAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "typeName";
+
private Constants() {
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/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 d723b2a..ca2f3d0 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -71,7 +71,14 @@ public enum AtlasErrorCode {
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"),
-
+ RELATIONSHIPDEF_INSUFFICIENT_ENDPOINTS(400, "ATLAS-400-00-02C", "Relationship def {0} creation attempted without 2 end points"),
+ RELATIONSHIPDEF_DOUBLE_CONTAINERS(400, "ATLAS-400-00-02D", "Relationship def {0} creation attempted with both end points as containers"),
+ RELATIONSHIPDEF_UNSUPPORTED_ATTRIBUTE_TYPE(400, "ATLAS-400-00-02F", "Cannot set an Attribute with type {0} on relationship def {1}, as it is not a primitive type "),
+ RELATIONSHIPDEF_ASSOCIATION_AND_CONTAINER(400, "ATLAS-400-00-030", "ASSOCIATION relationship def {0} creation attempted with an endpoint specifying isContainer"),
+ RELATIONSHIPDEF_COMPOSITION_NO_CONTAINER(400, "ATLAS-400-00-031", "COMPOSITION relationship def {0} creation attempted without an endpoint specifying isContainer"),
+ RELATIONSHIPDEF_AGGREGATION_NO_CONTAINER(400, "ATLAS-400-00-032", "AGGREGATION relationship def {0} creation attempted without an endpoint specifying isContainer"),
+ RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER(400, "ATLAS-400-00-033", "COMPOSITION relationship def {0} cannot have a SET cardinality and be a container"),
+ RELATIONSHIPDEF_LIST_ON_ENDPOINT(400, "ATLAS-400-00-034", "relationship def {0} cannot have a LIST cardinality on an endpoint"),
// 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"),
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/model/TypeCategory.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/TypeCategory.java b/intg/src/main/java/org/apache/atlas/model/TypeCategory.java
index e47a8a7..f06f64f 100644
--- a/intg/src/main/java/org/apache/atlas/model/TypeCategory.java
+++ b/intg/src/main/java/org/apache/atlas/model/TypeCategory.java
@@ -18,5 +18,5 @@
package org.apache.atlas.model;
public enum TypeCategory {
- PRIMITIVE, OBJECT_ID_TYPE, ENUM, STRUCT, CLASSIFICATION, ENTITY, ARRAY, MAP
+ PRIMITIVE, OBJECT_ID_TYPE, ENUM, STRUCT, CLASSIFICATION, ENTITY, ARRAY, MAP, RELATIONSHIP
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
index 7308eb7..1ccab22 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasBaseTypeDef.java
@@ -91,6 +91,22 @@ public abstract class AtlasBaseTypeDef implements java.io.Serializable {
ATLAS_TYPE_BIGDECIMAL,
ATLAS_TYPE_STRING,
};
+ /**
+ * The list of types that are valid for relationships. These are the
+ * primitive attributes and date.
+ */
+ public static final String[] ATLAS_RELATIONSHIP_ATTRIBUTE_TYPES = { ATLAS_TYPE_BOOLEAN,
+ ATLAS_TYPE_BYTE,
+ ATLAS_TYPE_SHORT,
+ ATLAS_TYPE_INT,
+ ATLAS_TYPE_LONG,
+ ATLAS_TYPE_FLOAT,
+ ATLAS_TYPE_DOUBLE,
+ ATLAS_TYPE_BIGINTEGER,
+ ATLAS_TYPE_BIGDECIMAL,
+ ATLAS_TYPE_STRING,
+ ATLAS_TYPE_DATE
+ };
public static final String[] ATLAS_BUILTIN_TYPES = {
ATLAS_TYPE_BOOLEAN,
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipDef.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipDef.java
new file mode 100644
index 0000000..eb8330e
--- /dev/null
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipDef.java
@@ -0,0 +1,279 @@
+/**
+ * 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.model.typedef;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+
+/**
+ * AtlasRelationshipDef is a TypeDef that defines a relationship.
+ *
+ * As with other typeDefs the AtlasRelationshipDef has a name. Once created the RelationshipDef has a guid.
+ * The name and the guid are the 2 ways that the RelationshipDef is identified.
+ *
+ * RelationshipDefs have 2 endpoints, each of which specify cardinality, an EntityDef type name and name and optionally
+ * whether the endpoint is a container.
+ * RelationshipDefs can have AttributeDefs - though only primitive types are allowed.
+ * RelationshipDefs have a relationshipCategory specifying the UML type of relationship required
+ * RelationshipDefs also have a PropogateTag - indicating which way tags could flow over the relationships.
+ *
+ * The way EntityDefs and RelationshipDefs are intended to be used is that EntityDefs will define AttributeDefs these AttributeDefs
+ * will not specify an EntityDef type name as their types.
+ *
+ * RelationshipDefs introduce new atributes to the entity instances. For example
+ * EntityDef A might have attributes attr1,attr2,attr3
+ * EntityDef B might have attributes attr4,attr5,attr6
+ * RelationshipDef AtoB might define 2 endpoints
+ * endpoint1: type A, name attr7
+ * endpoint1: type B, name attr8
+ *
+ * When an instance of EntityDef A is created, it will have attributes attr1,attr2,attr3,attr7
+ * When an instance of EntityDef B is created, it will have attributes attr4,attr5,attr6,attr8
+ *
+ * In this way relationshipDefs can be authored separately from entityDefs and can inject relationship attributes into
+ * the entity instances
+ *
+ */
+@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class AtlasRelationshipDef extends AtlasStructDef implements java.io.Serializable {
+ private static final long serialVersionUID = 1L;
+
+
+ /**
+ * The Relationship category determines the style of relationship around containment and lifecycle.
+ * UML terminology is used for the values.
+ * ASSOCIATION is a relationship with no containment.
+ * COMPOSITION and AGGREGATION are containment relationships.
+ * The difference being in the lifecycles of the container and its children. In the COMPOSITION case,
+ * the children cannot exist without the container. For AGGREGATION, the life cycles
+ * of the container and children are totally independant.
+ */
+ public enum RelationshipCategory {
+ ASSOCIATION, AGGREGATION, COMPOSITION
+ };
+
+ /**
+ * PropagateTags indicates whether tags should propagate across the relationship instance.
+ * Tags can propagate:
+ * NONE - not at all
+ * ONE_TO_TWO - from endpoint 1 to 2
+ * TWO_TO_ONE - from endpoint 2 to 1
+ * BOTH - both ways
+ *
+ * Care needs to be taken when specifying. The use cases we are aware of this flag being useful are :
+ *
+ * - propagating confidentiality classifications from a table to columns - ONE_TO_TWO could be used here
+ * - propagating classifications around Glossary synonyms - BOTH could be used here.
+ *
+ * There is an expectation that further enhancements will allow more granular control of tag propagation and will
+ * address how to resolve conflicts.
+ */
+ public enum PropagateTags {
+ NONE, ONE_TO_TWO, TWO_TO_ONE, BOTH
+ };
+
+ private RelationshipCategory relationshipCategory;
+ private PropagateTags propagateTags;
+ private AtlasRelationshipEndPointDef endPointDef1;
+ private AtlasRelationshipEndPointDef endPointDef2;
+
+ /**
+ * AtlasRelationshipDef contructor
+ * @throws AtlasBaseException
+ */
+ public AtlasRelationshipDef() throws AtlasBaseException {
+ this(null, null, null, null,null, null, null);
+ }
+
+ /**
+ * Create a relationshipDef without attributeDefs
+ * @param name
+ * - the name of the relationship type
+ * @param description
+ * - an optional description
+ * @param typeVersion
+ * - version - that defaults to 1.0
+ * @param relationshipCategory
+ * - there are 3 sorts of relationship category ASSOCIATION, COMPOSITION
+ * and AGGREGATION
+ * @param propagatetags
+ * -
+ * @param endPointDef1
+ * - first endpoint. As endpoint specifies an entity
+ * type and an attribute name. the attribute name then appears in
+ * the relationship instance
+ * @param endPointDef2
+ * - second endpoint. The endpoints are defined as 1
+ * ad 2 to avoid implying a direction. So we do not use to and
+ * from.
+ * @throws AtlasBaseException
+ */
+ public AtlasRelationshipDef(String name, String description, String typeVersion,
+ RelationshipCategory relationshipCategory,
+ PropagateTags propagatetags,
+ AtlasRelationshipEndPointDef endPointDef1,
+ AtlasRelationshipEndPointDef endPointDef2) throws AtlasBaseException {
+ this(name, description, typeVersion, relationshipCategory,propagatetags, endPointDef1, endPointDef2,
+ new ArrayList<AtlasAttributeDef>());
+ }
+
+ /**
+ * Create a relationshipDef with attributeDefs
+ * @param name
+ * - the name of the relationship type
+ * @param description
+ * - an optional description
+ * @param typeVersion
+ * - version - that defaults to 1.0
+ * @param relationshipCategory
+ * - there are 3 sorts of relationship category ASSOCIATION, COMPOSITION
+ * and AGGREGATION
+ * @param propagatetags
+ * -
+ * @param endPointDef1
+ * - First endpoint. As endpoint specifies an entity
+ * type and an attribute name. the attribute name then appears in
+ * the relationship instance
+ * @param endPointDef2
+ * - Second endpoint. The endpoints are defined as 1
+ * ad 2 to avoid implying a direction. So we do not use to and
+ * from.
+ * @param attributeDefs
+ * - these are the attributes on the relationship itself.
+ */
+ public AtlasRelationshipDef(String name, String description, String typeVersion,
+ RelationshipCategory relationshipCategory,
+ PropagateTags propagatetags, AtlasRelationshipEndPointDef endPointDef1,
+ AtlasRelationshipEndPointDef endPointDef2, List<AtlasAttributeDef> attributeDefs)
+ {
+ super(TypeCategory.RELATIONSHIP, name, description, typeVersion, attributeDefs, null);
+
+ setRelationshipCategory(relationshipCategory);
+ setPropagateTags(propagatetags);
+ setEndPointDef1(endPointDef1);
+ setEndPointDef2(endPointDef2);
+ }
+
+ public void setRelationshipCategory(RelationshipCategory relationshipCategory) {
+ this.relationshipCategory = relationshipCategory;
+ }
+
+ public RelationshipCategory getRelationshipCategory() {
+ return this.relationshipCategory;
+ }
+
+ public void setPropagateTags(PropagateTags propagateTags) {
+ this.propagateTags=propagateTags;
+ }
+
+ public PropagateTags getPropagateTags() {
+ return this.propagateTags;
+ }
+
+ public void setEndPointDef1(AtlasRelationshipEndPointDef endPointDef1) {
+ this.endPointDef1 = endPointDef1;
+ }
+
+ public AtlasRelationshipEndPointDef getEndPointDef1() {
+ return this.endPointDef1;
+ }
+
+ public void setEndPointDef2(AtlasRelationshipEndPointDef endPointDef2) {
+ this.endPointDef2 = endPointDef2;
+ }
+
+ public AtlasRelationshipEndPointDef getEndPointDef2() {
+ return this.endPointDef2;
+ }
+
+ public AtlasRelationshipDef(AtlasRelationshipDef other) throws AtlasBaseException {
+ super(other);
+
+ if (other != null) {
+ setRelationshipCategory(other.getRelationshipCategory());
+ setPropagateTags(other.getPropagateTags());
+ setEndPointDef1(other.getEndPointDef1());
+ setEndPointDef2(other.getEndPointDef2());
+ }
+ }
+ @Override
+ public StringBuilder toString(StringBuilder sb) {
+ if (sb == null) {
+ sb = new StringBuilder();
+ }
+
+ sb.append("AtlasRelationshipDef{");
+ super.toString(sb);
+ sb.append(',');
+ sb.append(this.relationshipCategory);
+ sb.append(',');
+ sb.append(this.propagateTags);
+ sb.append(',');
+ sb.append(this.endPointDef1.toString());
+ sb.append(',');
+ sb.append(this.endPointDef2.toString());
+ sb.append('}');
+ return sb;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ //AttributeDefs are checked in the super
+ if (!super.equals(o))
+ return false;
+ AtlasRelationshipDef that = (AtlasRelationshipDef) o;
+ if (!Objects.equals(relationshipCategory, that.getRelationshipCategory()))
+ return false;
+ if (!Objects.equals(propagateTags, that.getPropagateTags()))
+ return false;
+ if (!Objects.equals(endPointDef1, that.getEndPointDef1()))
+ return false;
+ return (Objects.equals(endPointDef2, that.getEndPointDef2()));
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(super.hashCode(), relationshipCategory, propagateTags, endPointDef1, endPointDef2);
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndPointDef.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndPointDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndPointDef.java
new file mode 100644
index 0000000..dde8416
--- /dev/null
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndPointDef.java
@@ -0,0 +1,193 @@
+/**
+ * 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.model.typedef;
+
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.io.Serializable;
+import java.util.Objects;
+
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+
+/**
+ * The relationshipEndPointsDef represents an end of the relationship. The end of the relationship is defined by a type, an
+ * attribute name, cardinality and whether it is the container end of the relationship.
+ */
+@JsonAutoDetect(getterVisibility = PUBLIC_ONLY, setterVisibility = PUBLIC_ONLY, fieldVisibility = NONE)
+@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
+@XmlRootElement
+@XmlAccessorType(XmlAccessType.PROPERTY)
+public class AtlasRelationshipEndPointDef implements Serializable {
+ private static final long serialVersionUID = 1L;
+ /**
+ * The type associated with the endpoint.
+ */
+ private String type;
+ /**
+ * The name of the attribute for this endpoint
+ */
+ private String name;
+
+ /**
+ * When set this indicates that this end is the container end
+ */
+ private boolean isContainer;
+ /**
+ * This is the cardinality of the end point
+ */
+ private Cardinality cardinality;
+
+ /**
+ * Base constructor
+ */
+ public AtlasRelationshipEndPointDef() {
+ this(null, null, Cardinality.SINGLE, false);
+ }
+
+ /**
+ *
+ * @param typeName
+ * - The name of an entityDef type
+ * @param name
+ * - The name of the new attribute that the entity instance will pick up.
+ * @param cardinality
+ * - this indicates whether the end point is SINGLE (1) or SET (many)
+ */
+ public AtlasRelationshipEndPointDef(String typeName, String name, Cardinality cardinality) {
+ this(typeName, name, cardinality, false);
+ }
+
+ /**
+ *
+ * @param typeName
+ * - The name of an entityDef type
+ * @param name
+ * - The name of the new attribute that the entity instance will pick up.
+ * @param cardinality
+ * - whether the end point is SINGLE (1) or SET (many)
+ * @param isContainer
+ * - whether the end point is a container or not
+ */
+ public AtlasRelationshipEndPointDef(String typeName, String name, Cardinality cardinality, boolean isContainer) {
+ setType(typeName);
+ setName(name);
+ setCardinality(cardinality);
+ setIsContainer(isContainer);
+ }
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * set whether this endpoint is a container or not.
+ * @param isContainer
+ */
+ public void setIsContainer(boolean isContainer) {
+ this.isContainer = isContainer;
+ }
+
+ public boolean getIsContainer() {
+ return isContainer;
+ }
+
+ /**
+ * set the cardinality SINGLE or SET on the endpoint.
+ * @param cardinality
+ */
+ public void setCardinality(AtlasStructDef.AtlasAttributeDef.Cardinality cardinality) {
+ this.cardinality = cardinality;
+ }
+
+ /**
+ *
+ * @return the cardinality
+ */
+ public Cardinality getCardinality() {
+ return this.cardinality;
+ }
+
+ /**
+ * Construct using an existing AtlasRelationshipEndPointDef
+ * @param other
+ */
+ public AtlasRelationshipEndPointDef(AtlasRelationshipEndPointDef other) {
+ if (other != null) {
+ setType(other.getType());
+ setName(other.getName());
+ setIsContainer(other.getIsContainer());
+ setCardinality(other.getCardinality());
+ }
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ if (sb == null) {
+ sb = new StringBuilder();
+ }
+
+ sb.append("AtlasRelationshipEndPointsDef{");
+ sb.append("type='").append(type).append('\'');
+ sb.append(", name==>'").append(name).append('\'');
+ sb.append(", isContainer==>'").append(isContainer).append('\'');
+ sb.append(", cardinality==>'").append(cardinality).append('\'');
+ sb.append('}');
+
+ return sb;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ AtlasRelationshipEndPointDef that = (AtlasRelationshipEndPointDef) o;
+ return Objects.equals(type, that.type) && Objects.equals(name, that.name)
+ && (isContainer == that.isContainer) && (cardinality == that.cardinality);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type, getName(), isContainer, cardinality);
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/model/typedef/AtlasTypesDef.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasTypesDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasTypesDef.java
index af95bff..66ae503 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasTypesDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasTypesDef.java
@@ -17,11 +17,8 @@
*/
package org.apache.atlas.model.typedef;
-import org.apache.commons.collections.CollectionUtils;
-import org.codehaus.jackson.annotate.JsonAutoDetect;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.annotate.JsonIgnoreProperties;
-import org.codehaus.jackson.map.annotate.JsonSerialize;
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
+import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
import java.util.ArrayList;
import java.util.Collection;
@@ -31,8 +28,11 @@ import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
-import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
-import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
+import org.apache.commons.collections.CollectionUtils;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.annotate.JsonIgnoreProperties;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
@JsonAutoDetect(getterVisibility=PUBLIC_ONLY, setterVisibility=PUBLIC_ONLY, fieldVisibility=NONE)
@JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL)
@@ -44,29 +44,50 @@ public class AtlasTypesDef {
private List<AtlasStructDef> structDefs;
private List<AtlasClassificationDef> classificationDefs;
private List<AtlasEntityDef> entityDefs;
+ private List<AtlasRelationshipDef> relationshipDefs;
public AtlasTypesDef() {
enumDefs = new ArrayList<>();
structDefs = new ArrayList<>();
classificationDefs = new ArrayList<>();
entityDefs = new ArrayList<>();
- }
-
+ relationshipDefs = new ArrayList<>();
+ }
+
+ /**
+ * tolerate typeDef creations that do not contain relationshipDefs, so that
+ * the older calls will still work.
+ * @param enumDefs
+ * @param structDefs
+ * @param classificationDefs
+ * @param entityDefs
+ */
+ public AtlasTypesDef(List<AtlasEnumDef> enumDefs, List<AtlasStructDef> structDefs,
+ List<AtlasClassificationDef> classificationDefs, List<AtlasEntityDef> entityDefs) {
+ this(enumDefs, structDefs, classificationDefs, entityDefs,new ArrayList<AtlasRelationshipDef>());
+ }
+ /**
+ * Create the TypesDef. This created definitions for each of the types.
+ * @param enumDefs
+ * @param structDefs
+ * @param classificationDefs
+ * @param entityDefs
+ * @param relationshipDefs
+ */
public AtlasTypesDef(List<AtlasEnumDef> enumDefs,
List<AtlasStructDef> structDefs,
List<AtlasClassificationDef> classificationDefs,
- List<AtlasEntityDef> entityDefs) {
+ List<AtlasEntityDef> entityDefs,
+ List<AtlasRelationshipDef> relationshipDefs) {
this.enumDefs = enumDefs;
this.structDefs = structDefs;
this.classificationDefs = classificationDefs;
this.entityDefs = entityDefs;
+ this.relationshipDefs = relationshipDefs;
}
-
-
public List<AtlasEnumDef> getEnumDefs() {
return enumDefs;
}
-
public void setEnumDefs(List<AtlasEnumDef> enumDefs) {
this.enumDefs = enumDefs;
}
@@ -94,7 +115,13 @@ public class AtlasTypesDef {
public void setClassificationDefs(List<AtlasClassificationDef> classificationDefs) {
this.classificationDefs = classificationDefs;
}
+ public List<AtlasRelationshipDef> getRelationshipDefs() {
+ return relationshipDefs;
+ }
+ public void setRelationshipDefs(List<AtlasRelationshipDef> relationshipDefs) {
+ this.relationshipDefs = relationshipDefs;
+ }
public boolean hasClassificationDef(String name) {
return hasTypeDef(classificationDefs, name);
@@ -111,6 +138,9 @@ public class AtlasTypesDef {
public boolean hasEntityDef(String name) {
return hasTypeDef(entityDefs, name);
}
+ public boolean hasRelationshipDef(String name) {
+ return hasTypeDef(relationshipDefs, name);
+ }
private <T extends AtlasBaseTypeDef> boolean hasTypeDef(Collection<T> typeDefs, String name) {
@@ -130,7 +160,8 @@ public class AtlasTypesDef {
return CollectionUtils.isEmpty(enumDefs) &&
CollectionUtils.isEmpty(structDefs) &&
CollectionUtils.isEmpty(classificationDefs) &&
- CollectionUtils.isEmpty(entityDefs);
+ CollectionUtils.isEmpty(entityDefs) &&
+ CollectionUtils.isEmpty(relationshipDefs);
}
public void clear() {
@@ -149,8 +180,10 @@ public class AtlasTypesDef {
if (entityDefs != null) {
entityDefs.clear();
}
+ if (relationshipDefs != null) {
+ relationshipDefs.clear();
+ }
}
-
public StringBuilder toString(StringBuilder sb) {
if (sb == null) {
sb = new StringBuilder();
@@ -169,6 +202,9 @@ public class AtlasTypesDef {
sb.append("entityDefs={");
AtlasBaseTypeDef.dumpObjects(entityDefs, sb);
sb.append("}");
+ sb.append("relationshipDefs={");
+ AtlasBaseTypeDef.dumpObjects(relationshipDefs, sb);
+ sb.append("}");
return sb;
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java b/intg/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java
index 198bd8f..e1c5a7f 100644
--- a/intg/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java
+++ b/intg/src/main/java/org/apache/atlas/store/AtlasTypeDefStore.java
@@ -24,6 +24,7 @@ import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasClassificationDef.AtlasClassificationDefs;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasTypesDef;
@@ -76,6 +77,15 @@ public interface AtlasTypeDefStore {
AtlasEntityDef updateEntityDefByName(String name, AtlasEntityDef entityDef) throws AtlasBaseException;
AtlasEntityDef updateEntityDefByGuid(String guid, AtlasEntityDef entityDef) throws AtlasBaseException;
+ /* RelationshipDef operations */
+
+ AtlasRelationshipDef getRelationshipDefByName(String name) throws AtlasBaseException;
+
+ AtlasRelationshipDef getRelationshipDefByGuid(String guid) throws AtlasBaseException;
+
+ AtlasRelationshipDef updateRelationshipDefByName(String name, AtlasRelationshipDef structDef) throws AtlasBaseException;
+
+ AtlasRelationshipDef updateRelationshipDefByGuid(String guid, AtlasRelationshipDef structDef) throws AtlasBaseException;
/* Bulk Operations */
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
new file mode 100644
index 0000000..6328108
--- /dev/null
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
@@ -0,0 +1,151 @@
+/**
+ * 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.type;
+
+
+import org.apache.atlas.AtlasErrorCode;
+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.AtlasRelationshipEndPointDef;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * class that implements behaviour of an relationship-type.
+ */
+public class AtlasRelationshipType extends AtlasStructType {
+ private static final Logger LOG = LoggerFactory.getLogger(AtlasRelationshipType.class);
+
+ private final AtlasRelationshipDef relationshipDef;
+
+ public AtlasRelationshipType(AtlasRelationshipDef relationshipDef) {
+ super(relationshipDef);
+
+ this.relationshipDef = relationshipDef;
+ }
+
+ public AtlasRelationshipType(AtlasRelationshipDef relationshipDef, AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+ super(relationshipDef);
+
+ this.relationshipDef = relationshipDef;
+
+ resolveReferences(typeRegistry);
+ }
+ public AtlasRelationshipDef getRelationshipDef() { return relationshipDef; }
+
+ @Override
+ public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+ super.resolveReferences(typeRegistry);
+
+ validateAtlasRelationshipDef(this.relationshipDef);
+ }
+
+ @Override
+ public boolean isValidValue(Object obj) {
+ boolean ret = true;
+
+ if (obj != null) {
+ validateAtlasRelationshipType((AtlasRelationshipType) obj);
+ ret = super.isValidValue(obj);
+ }
+
+ return ret;
+ }
+
+ @Override
+ public boolean isValidValueForUpdate(Object obj) {
+ boolean ret = true;
+
+ if (obj != null) {
+ validateAtlasRelationshipType((AtlasRelationshipType) obj);
+ ret = super.isValidValueForUpdate(obj);
+ }
+
+ return ret;
+ }
+ /**
+ * Validate the fields in the the RelationshipType are consistent with respect to themselves.
+ * @param type
+ * @throws AtlasBaseException
+ */
+ private boolean validateAtlasRelationshipType(AtlasRelationshipType type) {
+ boolean isValid = false;
+ try {
+ validateAtlasRelationshipDef(type.getRelationshipDef());
+ isValid = true;
+ } catch (AtlasBaseException abe) {
+ LOG.error("Validation error for AtlasRelationshipType", abe);
+ }
+ return isValid;
+ }
+
+ /**
+ * Throw an exception so we can junit easily.
+ * @param relationshipDef
+ * @throws AtlasBaseException
+ */
+ public static void validateAtlasRelationshipDef(AtlasRelationshipDef relationshipDef) throws AtlasBaseException {
+ AtlasRelationshipEndPointDef endPointDef1 = relationshipDef.getEndPointDef1();
+ AtlasRelationshipEndPointDef endPointDef2 = relationshipDef.getEndPointDef2();
+ boolean isContainer1 = endPointDef1.getIsContainer();
+ boolean isContainer2 = endPointDef2.getIsContainer();
+ RelationshipCategory relationshipCategory = relationshipDef.getRelationshipCategory();
+ String name = relationshipDef.getName();
+
+ if (isContainer1 && isContainer2) {
+ // we support 0 or 1 of these flags.
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_DOUBLE_CONTAINERS, name);
+ }
+ if ((isContainer1 || isContainer2)) {
+ // we have an isContainer defined in an endpoint
+ if (relationshipCategory == RelationshipCategory.ASSOCIATION) {
+ // associations are not containment relaitonships - so do not allow an endpoiint with isContainer
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_ASSOCIATION_AND_CONTAINER, name);
+ }
+ } else {
+ // we do not have an isContainer defined in an endpoint
+ if (relationshipCategory == RelationshipCategory.COMPOSITION) {
+ // COMPOSITION needs one endpoint to be the container.
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_COMPOSITION_NO_CONTAINER, name);
+ } else if (relationshipCategory == RelationshipCategory.AGGREGATION) {
+ // AGGREGATION needs one endpoint to be the container.
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_AGGREGATION_NO_CONTAINER, name);
+ }
+ }
+ if (relationshipCategory == RelationshipCategory.COMPOSITION) {
+ // composition containers should not be multiple cardinality
+ if (endPointDef1 != null &&
+ endPointDef1.getCardinality() == AtlasAttributeDef.Cardinality.SET &&
+ endPointDef1.getIsContainer()) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER, name);
+ }
+ if (endPointDef2 != null && endPointDef2 != null &&
+ endPointDef2.getCardinality() == AtlasAttributeDef.Cardinality.SET &&
+ endPointDef2.getIsContainer()) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER, name);
+ }
+ }
+ if ((endPointDef1 != null && endPointDef1.getCardinality() == AtlasAttributeDef.Cardinality.LIST) ||
+ (endPointDef2 != null && endPointDef2.getCardinality() == AtlasAttributeDef.Cardinality.LIST)) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_LIST_ON_ENDPOINT, name);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java
index 1b3526b..aebd4d1 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeRegistry.java
@@ -17,12 +17,30 @@
*/
package org.apache.atlas.type;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_ARRAY_PREFIX;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_ARRAY_SUFFIX;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_KEY_VAL_SEP;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_PREFIX;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_SUFFIX;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantLock;
+
+import javax.inject.Singleton;
+
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.commons.collections.CollectionUtils;
@@ -30,19 +48,6 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
-
-import javax.inject.Singleton;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*;
-
/**
* registry for all types defined in Atlas.
*/
@@ -183,7 +188,6 @@ public class AtlasTypeRegistry {
public Collection<AtlasEntityDef> getAllEntityDefs() { return registryData.entityDefs.getAll(); }
-
public AtlasEntityDef getEntityDefByGuid(String guid) {
return registryData.entityDefs.getTypeDefByGuid(guid);
}
@@ -193,12 +197,20 @@ public class AtlasTypeRegistry {
}
public Collection<String> getAllEntityDefNames() { return registryData.entityDefs.getAllNames(); }
-
public Collection<AtlasEntityType> getAllEntityTypes() { return registryData.entityDefs.getAllTypes(); }
-
public AtlasEntityType getEntityTypeByName(String name) { return registryData.entityDefs.getTypeByName(name); }
+ /**
+ * @return relationshipTypes
+ */
+ public Collection<AtlasRelationshipType> getAllRelationshipTypes() { return registryData.relationshipDefs.getAllTypes(); }
-
+ public AtlasRelationshipDef getRelationshipDefByGuid(String guid) {
+ return registryData.relationshipDefs.getTypeDefByGuid(guid);
+ }
+ public AtlasRelationshipDef getRelationshipDefByName(String name) {
+ return registryData.relationshipDefs.getTypeDefByName(name);
+ }
+ public AtlasRelationshipType getRelationshipTypeByName(String name) { return registryData.relationshipDefs.getTypeByName(name); }
public AtlasTransientTypeRegistry lockTypeRegistryForUpdate() throws AtlasBaseException {
return lockTypeRegistryForUpdate(DEFAULT_LOCK_MAX_WAIT_TIME_IN_SECONDS);
}
@@ -218,6 +230,7 @@ public class AtlasTypeRegistry {
final TypeDefCache<AtlasStructDef, AtlasStructType> structDefs;
final TypeDefCache<AtlasClassificationDef, AtlasClassificationType> classificationDefs;
final TypeDefCache<AtlasEntityDef, AtlasEntityType> entityDefs;
+ final TypeDefCache<AtlasRelationshipDef, AtlasRelationshipType> relationshipDefs;
final TypeDefCache<? extends AtlasBaseTypeDef, ? extends AtlasType>[] allDefCaches;
RegistryData() {
@@ -226,7 +239,8 @@ public class AtlasTypeRegistry {
structDefs = new TypeDefCache<>(allTypes);
classificationDefs = new TypeDefCache<>(allTypes);
entityDefs = new TypeDefCache<>(allTypes);
- allDefCaches = new TypeDefCache[] { enumDefs, structDefs, classificationDefs, entityDefs };
+ relationshipDefs = new TypeDefCache<>(allTypes);
+ allDefCaches = new TypeDefCache[] { enumDefs, structDefs, classificationDefs, entityDefs, relationshipDefs };
init();
}
@@ -284,6 +298,7 @@ public class AtlasTypeRegistry {
structDefs.updateGuid(typeName, guid);
classificationDefs.updateGuid(typeName, guid);
entityDefs.updateGuid(typeName, guid);
+ relationshipDefs.updateGuid(typeName, guid);
}
}
@@ -293,6 +308,7 @@ public class AtlasTypeRegistry {
structDefs.removeTypeDefByGuid(guid);
classificationDefs.removeTypeDefByGuid(guid);
entityDefs.removeTypeDefByGuid(guid);
+ relationshipDefs.removeTypeDefByGuid(guid);
}
}
@@ -302,6 +318,7 @@ public class AtlasTypeRegistry {
structDefs.removeTypeDefByName(typeName);
classificationDefs.removeTypeDefByName(typeName);
entityDefs.removeTypeDefByName(typeName);
+ relationshipDefs.removeTypeDefByName(typeName);
}
}
@@ -311,6 +328,7 @@ public class AtlasTypeRegistry {
structDefs.clear();
classificationDefs.clear();
entityDefs.clear();
+ relationshipDefs.clear();
init();
}
@@ -403,6 +421,7 @@ public class AtlasTypeRegistry {
addTypesWithNoRefResolve(typesDef.getStructDefs());
addTypesWithNoRefResolve(typesDef.getClassificationDefs());
addTypesWithNoRefResolve(typesDef.getEntityDefs());
+ addTypesWithNoRefResolve(typesDef.getRelationshipDefs());
resolveReferences();
}
@@ -502,6 +521,7 @@ public class AtlasTypeRegistry {
updateTypesWithNoRefResolve(typesDef.getStructDefs());
updateTypesWithNoRefResolve(typesDef.getClassificationDefs());
updateTypesWithNoRefResolve(typesDef.getEntityDefs());
+ updateTypesWithNoRefResolve(typesDef.getRelationshipDefs());
}
if (LOG.isDebugEnabled()) {
@@ -515,6 +535,7 @@ public class AtlasTypeRegistry {
removeTypesWithNoRefResolve(typesDef.getStructDefs());
removeTypesWithNoRefResolve(typesDef.getClassificationDefs());
removeTypesWithNoRefResolve(typesDef.getEntityDefs());
+ removeTypesWithNoRefResolve(typesDef.getRelationshipDefs());
resolveReferences();
}
@@ -546,6 +567,9 @@ public class AtlasTypeRegistry {
case ENTITY:
registryData.entityDefs.removeTypeDefByName(typeDef.getName());
break;
+ case RELATIONSHIP:
+ registryData.relationshipDefs.removeTypeDefByName(typeDef.getName());
+ break;
}
deletedTypes.add(typeDef);
}
@@ -564,6 +588,9 @@ public class AtlasTypeRegistry {
case ENTITY:
registryData.entityDefs.removeTypeDefByGuid(typeDef.getGuid());
break;
+ case RELATIONSHIP:
+ registryData.relationshipDefs.removeTypeDefByGuid(typeDef.getGuid());
+ break;
}
deletedTypes.add(typeDef);
}
@@ -641,11 +668,15 @@ public class AtlasTypeRegistry {
AtlasClassificationDef classificationDef = (AtlasClassificationDef) typeDef;
registryData.classificationDefs.addType(classificationDef,
- new AtlasClassificationType(classificationDef));
+ new AtlasClassificationType(classificationDef));
} else if (typeDef.getClass().equals(AtlasEntityDef.class)) {
AtlasEntityDef entityDef = (AtlasEntityDef) typeDef;
registryData.entityDefs.addType(entityDef, new AtlasEntityType(entityDef));
+ } else if (typeDef.getClass().equals(AtlasRelationshipDef.class)) {
+ AtlasRelationshipDef relationshipDef = (AtlasRelationshipDef) typeDef;
+
+ registryData.relationshipDefs.addType(relationshipDef, new AtlasRelationshipType(relationshipDef));
}
addedTypes.add(typeDef);
@@ -659,7 +690,7 @@ public class AtlasTypeRegistry {
private void addTypesWithNoRefResolve(Collection<? extends AtlasBaseTypeDef> typeDefs) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("==> AtlasTypeRegistry.addTypesWithNoRefResolve(length={})",
- (typeDefs == null ? 0 : typeDefs.size()));
+ (typeDefs == null ? 0 : typeDefs.size()));
}
if (CollectionUtils.isNotEmpty(typeDefs)) {
@@ -670,7 +701,7 @@ public class AtlasTypeRegistry {
if (LOG.isDebugEnabled()) {
LOG.debug("<== AtlasTypeRegistry.addTypesWithNoRefResolve(length={})",
- (typeDefs == null ? 0 : typeDefs.size()));
+ (typeDefs == null ? 0 : typeDefs.size()));
}
}
@@ -714,12 +745,17 @@ public class AtlasTypeRegistry {
registryData.classificationDefs.removeTypeDefByGuid(guid);
registryData.classificationDefs.addType(classificationDef,
- new AtlasClassificationType(classificationDef));
+ new AtlasClassificationType(classificationDef));
} else if (typeDef.getClass().equals(AtlasEntityDef.class)) {
AtlasEntityDef entityDef = (AtlasEntityDef) typeDef;
registryData.entityDefs.removeTypeDefByGuid(guid);
registryData.entityDefs.addType(entityDef, new AtlasEntityType(entityDef));
+ } else if (typeDef.getClass().equals(AtlasRelationshipDef.class)) {
+ AtlasRelationshipDef relationshipDef = (AtlasRelationshipDef) typeDef;
+
+ registryData.relationshipDefs.removeTypeDefByGuid(guid);
+ registryData.relationshipDefs.addType(relationshipDef, new AtlasRelationshipType(relationshipDef));
}
updatedTypes.add(typeDef);
@@ -751,12 +787,17 @@ public class AtlasTypeRegistry {
registryData.classificationDefs.removeTypeDefByName(name);
registryData.classificationDefs.addType(classificationDef,
- new AtlasClassificationType(classificationDef));
+ new AtlasClassificationType(classificationDef));
} else if (typeDef.getClass().equals(AtlasEntityDef.class)) {
AtlasEntityDef entityDef = (AtlasEntityDef) typeDef;
registryData.entityDefs.removeTypeDefByName(name);
registryData.entityDefs.addType(entityDef, new AtlasEntityType(entityDef));
+ } else if (typeDef.getClass().equals(AtlasRelationshipDef.class)) {
+ AtlasRelationshipDef relationshipDef = (AtlasRelationshipDef) typeDef;
+
+ registryData.relationshipDefs.removeTypeDefByName(name);
+ registryData.relationshipDefs.addType(relationshipDef, new AtlasRelationshipType(relationshipDef));
}
updatedTypes.add(typeDef);
@@ -770,7 +811,7 @@ public class AtlasTypeRegistry {
private void updateTypesWithNoRefResolve(Collection<? extends AtlasBaseTypeDef> typeDefs) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> AtlasTypeRegistry.updateTypesWithNoRefResolve(length={})",
- (typeDefs == null ? 0 : typeDefs.size()));
+ (typeDefs == null ? 0 : typeDefs.size()));
}
if (CollectionUtils.isNotEmpty(typeDefs)) {
@@ -781,7 +822,7 @@ public class AtlasTypeRegistry {
if (LOG.isDebugEnabled()) {
LOG.debug("<== AtlasTypeRegistry.updateTypesWithNoRefResolve(length={})",
- (typeDefs == null ? 0 : typeDefs.size()));
+ (typeDefs == null ? 0 : typeDefs.size()));
}
}
}
@@ -808,7 +849,7 @@ public class AtlasTypeRegistry {
}
} else {
LOG.warn("lockTypeRegistryForUpdate(): already locked. currentLockCount={}",
- typeRegistryUpdateLock.getHoldCount());
+ typeRegistryUpdateLock.getHoldCount());
}
try {
@@ -842,8 +883,8 @@ public class AtlasTypeRegistry {
try {
if (typeRegistryUnderUpdate != ttr) {
LOG.error("releaseTypeRegistryForUpdate(): incorrect typeRegistry returned for release" +
- ": found=" + ttr + "; expected=" + typeRegistryUnderUpdate,
- new Exception().fillInStackTrace());
+ ": found=" + ttr + "; expected=" + typeRegistryUnderUpdate,
+ new Exception().fillInStackTrace());
} else if (typeRegistryUpdateLock.getHoldCount() == 1) {
if (ttr != null && commitUpdates) {
typeRegistry.registryData = ttr.registryData;
@@ -861,7 +902,7 @@ public class AtlasTypeRegistry {
}
} else {
LOG.error("releaseTypeRegistryForUpdate(): current thread does not hold the lock",
- new Exception().fillInStackTrace());
+ new Exception().fillInStackTrace());
}
LOG.debug("<== releaseTypeRegistryForUpdate()");
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/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 c0135f5..3125668 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasTypeUtil.java
@@ -18,47 +18,23 @@
package org.apache.atlas.type;
import com.google.common.collect.ImmutableSet;
-
-import org.apache.atlas.AtlasErrorCode;
-import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
-import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
-import org.apache.atlas.model.typedef.AtlasClassificationDef;
-import org.apache.atlas.model.typedef.AtlasEntityDef;
-import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.*;
import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef;
-import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasConstraintDef;
-import org.apache.atlas.model.typedef.AtlasTypeDefHeader;
-import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
-
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
+import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_ARRAY_PREFIX;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_ARRAY_SUFFIX;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_KEY_VAL_SEP;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_PREFIX;
-import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_MAP_SUFFIX;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.*;
/**
* Utility methods for AtlasType/AtlasTypeDef.
@@ -294,6 +270,11 @@ public class AtlasTypeUtil {
headerList.add(new AtlasTypeDefHeader(entityDef));
}
}
+ if (CollectionUtils.isNotEmpty(typesDef.getRelationshipDefs())) {
+ for (AtlasRelationshipDef relationshipDef : typesDef.getRelationshipDefs()) {
+ headerList.add(new AtlasTypeDefHeader(relationshipDef));
+ }
+ }
return headerList;
}
@@ -390,6 +371,10 @@ public class AtlasTypeUtil {
sb.append("entityDefs=[");
dumpTypeNames(typesDef.getEntityDefs(), sb);
sb.append("]");
+
+ sb.append("relationshipDefs=[");
+ dumpTypeNames(typesDef.getRelationshipDefs(), sb);
+ sb.append("]");
}
sb.append("}");
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/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 084bcc4..e1ca889 100644
--- a/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java
+++ b/intg/src/test/java/org/apache/atlas/model/ModelTestUtil.java
@@ -21,12 +21,8 @@ import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasStruct;
-import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
-import org.apache.atlas.model.typedef.AtlasClassificationDef;
-import org.apache.atlas.model.typedef.AtlasEntityDef;
-import org.apache.atlas.model.typedef.AtlasEnumDef;
+import org.apache.atlas.model.typedef.*;
import org.apache.atlas.model.typedef.AtlasEnumDef.AtlasEnumElementDef;
-import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.type.AtlasClassificationType;
import org.apache.atlas.type.AtlasEntityType;
@@ -43,6 +39,7 @@ import java.util.concurrent.atomic.AtomicInteger;
import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_BUILTIN_TYPES;
import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_PRIMITIVE_TYPES;
+import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_RELATIONSHIP_ATTRIBUTE_TYPES;
public final class ModelTestUtil {
@@ -441,6 +438,67 @@ public final class ModelTestUtil {
return ret;
}
+ /**
+ * Valid types for attributes in relationships. This has good coverage of all attribute type and includes enums
+ * maps and arrays.
+ * This test does not use getRandomBuiltInType() style - so that it is deterministic.
+ *
+ * It does cover very nested maps / arrays.
+ * @param attrNamePrefix
+ * @return
+ */
+ public static List<AtlasAttributeDef> newAttributeDefsWithAllBuiltInTypesForRelationship(String attrNamePrefix) {
+ List<AtlasAttributeDef> ret = new ArrayList<>();
+
+ // add enum types
+ ret.add(getAttributeDef(attrNamePrefix, ENUM_DEF.getName()));
+ ret.add(getAttributeDef(attrNamePrefix, ENUM_DEF_WITH_NO_DEFAULT.getName()));
+ // add array of enum types
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getArrayTypeName(ENUM_DEF.getName())));
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getArrayTypeName(ENUM_DEF_WITH_NO_DEFAULT.getName())));
+
+
+ for (String attributeType : ATLAS_RELATIONSHIP_ATTRIBUTE_TYPES) {
+
+ // simple attributes
+ ret.add(getAttributeDef(attrNamePrefix, attributeType));
+ // array
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getArrayTypeName(attributeType)));
+ // map types with enum as key
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getMapTypeName(ENUM_DEF.getName(), attributeType)));
+ // map types with enum as key no default
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getMapTypeName(ENUM_DEF_WITH_NO_DEFAULT.getName(), attributeType)));
+ // map types attribute as key enum no default as value
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getMapTypeName(attributeType, ENUM_DEF_WITH_NO_DEFAULT.getName())));
+ // map types with enum as value
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getMapTypeName(attributeType, ENUM_DEF.getName())));
+
+ for (String attributeType2 : ATLAS_RELATIONSHIP_ATTRIBUTE_TYPES) {
+ // add map types
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getMapTypeName(attributeType, attributeType2)));
+ // add array of arrays
+ ret.add(getAttributeDef(attrNamePrefix,
+ AtlasBaseTypeDef.getArrayTypeName(AtlasBaseTypeDef.getArrayTypeName(attributeType2))));
+ // add array of maps
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getArrayTypeName(
+ AtlasBaseTypeDef.getMapTypeName(attributeType, attributeType2))));
+ // add map of arrays
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getMapTypeName(attributeType,
+ AtlasBaseTypeDef.getArrayTypeName(attributeType2))));
+ // add map of maps
+ ret.add(getAttributeDef(attrNamePrefix, AtlasBaseTypeDef.getMapTypeName(attributeType,
+ AtlasBaseTypeDef.getMapTypeName(attributeType, attributeType2))));
+ }
+ }
+
+ return ret;
+ }
+
public static String getDefaultAttributeName(String attrType) {
return PREFIX_ATTRIBUTE_NAME + attrType;
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/test/java/org/apache/atlas/model/typedef/TestAtlasRelationshipDef.java
----------------------------------------------------------------------
diff --git a/intg/src/test/java/org/apache/atlas/model/typedef/TestAtlasRelationshipDef.java b/intg/src/test/java/org/apache/atlas/model/typedef/TestAtlasRelationshipDef.java
new file mode 100644
index 0000000..78efa6e
--- /dev/null
+++ b/intg/src/test/java/org/apache/atlas/model/typedef/TestAtlasRelationshipDef.java
@@ -0,0 +1,96 @@
+/**
+ * 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.model.typedef;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.ModelTestUtil;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
+import org.apache.atlas.type.AtlasType;
+import org.testng.annotations.Test;
+
+import java.util.List;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+
+public class TestAtlasRelationshipDef {
+
+ private static final String PREFIX_ATTRIBUTE_NAME = "reltests-";
+ private List<AtlasStructDef.AtlasAttributeDef> attributeDefs;
+
+ @Test
+ public void testRelationshipDefSerDeEmpty() throws AtlasBaseException {
+
+ AtlasRelationshipEndPointDef ep1 = new AtlasRelationshipEndPointDef("typeA", "attr1", Cardinality.SINGLE);
+ AtlasRelationshipEndPointDef ep2 = new AtlasRelationshipEndPointDef("typeB", "attr2", Cardinality.SINGLE);
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+
+ String jsonString = AtlasType.toJson(relationshipDef);
+ System.out.println(jsonString);
+ assertNotNull(jsonString);
+
+ AtlasRelationshipDef relationshipDef2 = AtlasType.fromJson(jsonString, AtlasRelationshipDef.class);
+ String jsonString2 = AtlasType.toJson(relationshipDef2);
+
+ assertEquals(jsonString, jsonString2);
+ assertEquals(relationshipDef2, relationshipDef,
+ "Incorrect serialization/deserialization of AtlasRelationshipDef");
+ }
+
+ @Test
+ public void testRelationshipDefSerDeAttributes() throws AtlasBaseException {
+
+ AtlasRelationshipEndPointDef ep1 = new AtlasRelationshipEndPointDef("typeA", "attr1", Cardinality.SINGLE);
+ AtlasRelationshipEndPointDef ep2 = new AtlasRelationshipEndPointDef("typeB", "attr2", Cardinality.SINGLE);
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ relationshipDef.setAttributeDefs(
+ ModelTestUtil.newAttributeDefsWithAllBuiltInTypesForRelationship(PREFIX_ATTRIBUTE_NAME));
+ String jsonString = AtlasType.toJson(relationshipDef);
+ assertNotNull(jsonString);
+
+ AtlasRelationshipDef relationshipDef2 = AtlasType.fromJson(jsonString, AtlasRelationshipDef.class);
+ String jsonString2 = AtlasType.toJson(relationshipDef2);
+
+ assertEquals(jsonString, jsonString2);
+ assertEquals(relationshipDef2, relationshipDef,
+ "Incorrect serialization/deserialization of AtlasRelationshipDef");
+ }
+ @Test
+ public void testRelationshipEquals() throws AtlasBaseException {
+
+ AtlasRelationshipEndPointDef ep1 = new AtlasRelationshipEndPointDef("typeA", "attr1", Cardinality.SINGLE);
+ AtlasRelationshipEndPointDef ep2 = new AtlasRelationshipEndPointDef("typeB", "attr2", Cardinality.SINGLE);
+ AtlasRelationshipDef relationshipDef1 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ List<AtlasStructDef.AtlasAttributeDef> attributeDefs = ModelTestUtil.newAttributeDefsWithAllBuiltInTypesForRelationship(PREFIX_ATTRIBUTE_NAME);
+ relationshipDef1.setAttributeDefs(attributeDefs);
+ AtlasRelationshipDef relationshipDef2 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ relationshipDef2.setAttributeDefs(attributeDefs);
+ assertEquals(relationshipDef1,relationshipDef2);
+
+ AtlasRelationshipDef relationshipDef3 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+
+ assertNotEquals(relationshipDef1,relationshipDef3);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
----------------------------------------------------------------------
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java b/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
new file mode 100644
index 0000000..6af374a
--- /dev/null
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
@@ -0,0 +1,107 @@
+/**
+ * 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.type;
+
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipEndPointDef;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.testng.annotations.Test;
+
+import static org.testng.AssertJUnit.fail;
+public class TestAtlasRelationshipType {
+ @Test
+ public void testvalidateAtlasRelationshipDef() throws AtlasBaseException {
+ AtlasRelationshipEndPointDef ep1 = new AtlasRelationshipEndPointDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE);
+ AtlasRelationshipEndPointDef ep2 = new AtlasRelationshipEndPointDef("typeB", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE);
+ AtlasRelationshipEndPointDef ep3 = new AtlasRelationshipEndPointDef("typeC", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, true);
+ AtlasRelationshipEndPointDef ep4 = new AtlasRelationshipEndPointDef("typeD", "attr2", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE, true);
+ AtlasRelationshipEndPointDef ep5 = new AtlasRelationshipEndPointDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SET,true);
+ AtlasRelationshipEndPointDef ep6 = new AtlasRelationshipEndPointDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.LIST,true);
+ AtlasRelationshipDef relationshipDef1 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ AtlasRelationshipDef relationshipDef2 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.COMPOSITION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep3);
+ AtlasRelationshipDef relationshipDef3 = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.AGGREGATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep3);
+
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.ASSOCIATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep3, ep2);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_ASSOCIATION_AND_CONTAINER)) {
+ fail("This call expected a different error");
+ }
+ }
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.COMPOSITION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_COMPOSITION_NO_CONTAINER)) {
+ fail("This call expected a different error");
+ }
+ }
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.AGGREGATION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep2);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_AGGREGATION_NO_CONTAINER)) {
+ fail("This call expected a different error");
+ }
+ }
+
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.COMPOSITION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep5);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_COMPOSITION_SET_CONTAINER)) {
+ fail("This call expected a different error");
+ }
+ }
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.COMPOSITION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep1, ep6);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_LIST_ON_ENDPOINT)) {
+ fail("This call expected a different error");
+ }
+ }
+ try {
+ AtlasRelationshipDef relationshipDef = new AtlasRelationshipDef("emptyRelationshipDef", "desc 1", "version1",
+ AtlasRelationshipDef.RelationshipCategory.COMPOSITION, AtlasRelationshipDef.PropagateTags.ONE_TO_TWO, ep6, ep1);
+ AtlasRelationshipType.validateAtlasRelationshipDef(relationshipDef);
+ fail("This call is expected to fail");
+ } catch (AtlasBaseException abe) {
+ if (!abe.getAtlasErrorCode().equals(AtlasErrorCode.RELATIONSHIPDEF_LIST_ON_ENDPOINT)) {
+ fail("This call expected a different error");
+ }
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/6b9399e0/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStore.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStore.java
new file mode 100644
index 0000000..df67958
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasRelationshipDefStore.java
@@ -0,0 +1,52 @@
+/**
+ * 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 java.util.List;
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+
+/**
+ * Interface for graph persistence store for AtlasRelationshipDef
+ */
+public interface AtlasRelationshipDefStore {
+ Object preCreate(AtlasRelationshipDef relationshipDef) throws AtlasBaseException;
+
+ AtlasRelationshipDef create(AtlasRelationshipDef relationshipDef, Object preCreateResult) throws AtlasBaseException;
+
+ List<AtlasRelationshipDef> getAll() throws AtlasBaseException;
+
+ AtlasRelationshipDef getByName(String name) throws AtlasBaseException;
+
+ AtlasRelationshipDef getByGuid(String guid) throws AtlasBaseException;
+
+ AtlasRelationshipDef update(AtlasRelationshipDef relationshipDef) throws AtlasBaseException;
+
+ AtlasRelationshipDef updateByName(String name, AtlasRelationshipDef relationshipDef) throws AtlasBaseException;
+
+ AtlasRelationshipDef updateByGuid(String guid, AtlasRelationshipDef relationshipDef) throws AtlasBaseException;
+
+ Object preDeleteByName(String name) throws AtlasBaseException;
+
+ void deleteByName(String name, Object preDeleteResult) throws AtlasBaseException;
+
+ Object preDeleteByGuid(String guid) throws AtlasBaseException;
+
+ void deleteByGuid(String guid, Object preDeleteResult) throws AtlasBaseException;
+}