ATLAS-1852: create relationship-def Signed-off-by: Madhan Neethiraj <[email protected]>
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 <[email protected]> Authored: Sun Jun 11 11:57:50 2017 -0700 Committer: Madhan Neethiraj <[email protected]> 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; +}
