ATLAS-1892: update AtlasEntityType to populate relationship attributes during resolve
Signed-off-by: Madhan Neethiraj <madhan@apache.org>
diff --git a/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java b/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java
index 925b6b1..9902685 100644
--- a/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java
+++ b/authorization/src/main/java/org/apache/atlas/authorize/AtlasResourceTypes.java
@@ -19,5 +19,5 @@
package org.apache.atlas.authorize;
public enum AtlasResourceTypes {
- UNKNOWN, ENTITY, TYPE, OPERATION, TAXONOMY, TERM, RELATION
+ UNKNOWN, ENTITY, TYPE, OPERATION, TAXONOMY, TERM, RELATIONSHIP
}
diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java
index bb3157a..d67376f 100644
--- a/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java
+++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/AtlasAuthorizationUtils.java
@@ -1,4 +1,5 @@
/**
+/**
* 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
@@ -31,7 +32,6 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.HashSet;
-import java.util.Objects;
import java.util.Set;
import java.util.regex.Pattern;
@@ -139,8 +139,8 @@
if (contextPath.contains("/terms")) {
resourceTypes.add(AtlasResourceTypes.TERM);
}
- } else if (api.startsWith("relation")) {
- resourceTypes.add(AtlasResourceTypes.RELATION);
+ } else if (api.startsWith("relationship")) {
+ resourceTypes.add(AtlasResourceTypes.RELATIONSHIP);
} else {
LOG.error("Unable to find Atlas Resource corresponding to : {}\nSetting {}"
, api, AtlasResourceTypes.UNKNOWN.name());
diff --git a/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java
index acf7388..fc611c8 100644
--- a/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java
+++ b/authorization/src/main/java/org/apache/atlas/authorize/simple/PolicyParser.java
@@ -231,8 +231,8 @@
resourceType = AtlasResourceTypes.TAXONOMY;
} else if (type.equalsIgnoreCase("TERM")) {
resourceType = AtlasResourceTypes.TERM;
- } else if (type.equalsIgnoreCase("RELATION")) {
- resourceType = AtlasResourceTypes.RELATION;
+ } else if (type.equalsIgnoreCase("RELATIONSHIP")) {
+ resourceType = AtlasResourceTypes.RELATIONSHIP;
} else {
Log.warn(type + " is invalid resource please check PolicyStore file");
continue;
diff --git a/distro/src/conf/policy-store.txt b/distro/src/conf/policy-store.txt
index 47583c1..c804b8d 100644
--- a/distro/src/conf/policy-store.txt
+++ b/distro/src/conf/policy-store.txt
@@ -2,8 +2,8 @@
##r-READ, w-WRITE, u-UPDATE, d-DELETE
##Policy_Name;;User_Name1:Operations_Allowed,User_Name2:Operations_Allowed;;Group_Name1:Operations_Allowed,Group_Name2:Operations_Allowed;;Resource_Type1:Resource_Name,Resource_Type2:Resource_Name
##
-adminPolicy;;admin:rwud;;ROLE_ADMIN:rwud;;type:*,entity:*,operation:*,taxonomy:*,term:*
-dataScientistPolicy;;;;DATA_SCIENTIST:r;;type:*,entity:*,taxonomy:*,term:*
-dataStewardPolicy;;;;DATA_STEWARD:rwu;;type:*,entity:*,taxonomy:*,term:*
-hadoopPolicy;;;;hadoop:rwud;;type:*,entity:*,operation:*,taxonomy:*,term:*
+adminPolicy;;admin:rwud;;ROLE_ADMIN:rwud;;type:*,entity:*,operation:*,taxonomy:*,term:*,relationship:*
+dataScientistPolicy;;;;DATA_SCIENTIST:r;;type:*,entity:*,taxonomy:*,term:*,relationship:*
+dataStewardPolicy;;;;DATA_STEWARD:rwu;;type:*,entity:*,taxonomy:*,term:*,relationship:*
+hadoopPolicy;;;;hadoop:rwud;;type:*,entity:*,operation:*,taxonomy:*,term:*,relationship:*
rangerTagSyncPolicy;;;;RANGER_TAG_SYNC:r;;type:*,entity:*
diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
index e8971a8..70480df 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -93,6 +93,7 @@
REFERENCED_ENTITY_NOT_FOUND(404, "ATLAS-404-00-00A", "Referenced entity {0} is not found"),
INSTANCE_NOT_FOUND(404, "ATLAS-404-00-00B", "Given instance is invalid/not found: {0}"),
RELATIONSHIP_GUID_NOT_FOUND(404, "ATLAS-404-00-00C", "Given relationship guid {0} is invalid/not found"),
+ RELATIONSHIP_CRUD_INVALID_PARAMS(404, "ATLAS-404-00-00D", "Invalid relationship creation/updation parameters passed : {0}"),
// All data conflict errors go here
TYPE_ALREADY_EXISTS(409, "ATLAS-409-00-001", "Given type {0} already exists"),
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndDef.java
index 34e932e..f80ea89 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasRelationshipEndDef.java
@@ -166,10 +166,6 @@
return this.cardinality;
}
- public boolean isContainer() { return isContainer; }
-
- public void setContainer(boolean container) { isContainer = container; }
-
public String getLegacyLabel() { return legacyLabel; }
public void setLegacyLabel(String legacyLabel) { this.legacyLabel = legacyLabel; }
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
index a29f7fb..70e3067 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
@@ -47,10 +47,11 @@
private final AtlasEntityDef entityDef;
- private List<AtlasEntityType> superTypes = Collections.emptyList();
- private Set<String> allSuperTypes = Collections.emptySet();
- private Set<String> allSubTypes = Collections.emptySet();
- private Set<String> typeAndAllSubTypes = Collections.emptySet();
+ private List<AtlasEntityType> superTypes = Collections.emptyList();
+ private Set<String> allSuperTypes = Collections.emptySet();
+ private Set<String> allSubTypes = Collections.emptySet();
+ private Set<String> typeAndAllSubTypes = Collections.emptySet();
+ private Map<String, AtlasAttribute> relationshipAttributes = Collections.emptyMap();
public AtlasEntityType(AtlasEntityDef entityDef) {
super(entityDef);
@@ -88,12 +89,13 @@
}
}
- this.superTypes = Collections.unmodifiableList(s);
- this.allSuperTypes = Collections.unmodifiableSet(allS);
- this.allAttributes = Collections.unmodifiableMap(allA);
- this.uniqAttributes = getUniqueAttributes(this.allAttributes);
- this.allSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2()
- this.typeAndAllSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2()
+ this.superTypes = Collections.unmodifiableList(s);
+ this.allSuperTypes = Collections.unmodifiableSet(allS);
+ this.allAttributes = Collections.unmodifiableMap(allA);
+ this.uniqAttributes = getUniqueAttributes(this.allAttributes);
+ this.allSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2()
+ this.typeAndAllSubTypes = new HashSet<>(); // this will be populated in resolveReferencesPhase2()
+ this.relationshipAttributes = new HashMap<>(); // this will be populated in resolveReferencesPhase2()
this.typeAndAllSubTypes.add(this.getTypeName());
}
@@ -140,6 +142,12 @@
return StringUtils.isNotEmpty(entityTypeName) && allSuperTypes.contains(entityTypeName);
}
+ public Map<String, AtlasAttribute> getRelationshipAttributes() { return Collections.unmodifiableMap(relationshipAttributes); }
+
+ public void addRelationshipAttribute(String attributeName, AtlasAttribute attribute) {
+ relationshipAttributes.put(attributeName, attribute);
+ }
+
@Override
public AtlasEntity createDefaultValue() {
AtlasEntity ret = new AtlasEntity(entityDef.getName());
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
index 38b68bb..f85cf35 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasRelationshipType.java
@@ -20,14 +20,16 @@
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasRelationshipDef;
import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory;
import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-
/**
* class that implements behaviour of an relationship-type.
*/
@@ -57,20 +59,26 @@
public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
super.resolveReferences(typeRegistry);
- String end1TypeName = relationshipDef != null && relationshipDef.getEndDef1() != null ? relationshipDef.getEndDef1().getType() : null;
- String end2TypeName = relationshipDef != null && relationshipDef.getEndDef2() != null ? relationshipDef.getEndDef2().getType() : null;
+ if (relationshipDef == null) {
+ throw new AtlasBaseException(AtlasErrorCode.INVALID_VALUE, "relationshipDef is null");
+ }
+
+ String end1TypeName = relationshipDef.getEndDef1() != null ? relationshipDef.getEndDef1().getType() : null;
+ String end2TypeName = relationshipDef.getEndDef2() != null ? relationshipDef.getEndDef2().getType() : null;
AtlasType type1 = typeRegistry.getType(end1TypeName);
AtlasType type2 = typeRegistry.getType(end2TypeName);
if (type1 instanceof AtlasEntityType) {
- end1Type = (AtlasEntityType)type1;
+ end1Type = (AtlasEntityType) type1;
+
} else {
throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END_TYPE, getTypeName(), end1TypeName);
}
if (type2 instanceof AtlasEntityType) {
- end2Type = (AtlasEntityType)type2;
+ end2Type = (AtlasEntityType) type2;
+
} else {
throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID_END_TYPE, getTypeName(), end2TypeName);
}
@@ -79,12 +87,25 @@
}
@Override
+ public void resolveReferencesPhase2(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+ super.resolveReferencesPhase2(typeRegistry);
+
+ addRelationshipAttributeToEndType(relationshipDef.getEndDef1(), end1Type, end2Type.getTypeName(), typeRegistry);
+
+ addRelationshipAttributeToEndType(relationshipDef.getEndDef2(), end2Type, end1Type.getTypeName(), typeRegistry);
+ }
+
+ @Override
public boolean isValidValue(Object obj) {
boolean ret = true;
if (obj != null) {
- validateAtlasRelationshipType((AtlasRelationshipType) obj);
- ret = super.isValidValue(obj);
+
+ if (obj instanceof AtlasRelationshipType) {
+ validateAtlasRelationshipType((AtlasRelationshipType) obj);
+ }
+
+ ret = super.isValidValue(obj);
}
return ret;
@@ -176,4 +197,29 @@
}
}
}
+
+ private void addRelationshipAttributeToEndType(AtlasRelationshipEndDef endDef,
+ AtlasEntityType entityType,
+ String attrTypeName,
+ AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
+
+ String attrName = (endDef != null) ? endDef.getName() : null;
+
+ if (StringUtils.isEmpty(attrName)) {
+ return;
+ }
+
+ AtlasAttribute attribute = entityType.getAttribute(attrName);
+
+ if (attribute == null) { //attr doesn't exist in type - is a new relationship attribute
+
+ if (endDef.getCardinality() == Cardinality.SET) {
+ attrTypeName = AtlasBaseTypeDef.getArrayTypeName(attrTypeName);
+ }
+
+ attribute = new AtlasAttribute(entityType, new AtlasAttributeDef(attrName, attrTypeName), typeRegistry.getType(attrTypeName));
+ }
+
+ entityType.addRelationshipAttribute(attrName, attribute);
+ }
}
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java b/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
index 7a4e9fd..41aac8f 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasRelationshipType.java
@@ -17,15 +17,48 @@
*/
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.typedef.AtlasBaseTypeDef;
+import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
+import org.apache.atlas.type.AtlasTypeRegistry.AtlasTransientTypeRegistry;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasRelationshipDef;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.PropagateTags;
+import org.apache.atlas.model.typedef.AtlasRelationshipDef.RelationshipCategory;
import org.apache.atlas.model.typedef.AtlasRelationshipEndDef;
import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef.Cardinality;
+import org.testng.Assert;
import org.testng.annotations.Test;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
import static org.testng.Assert.fail;
+
public class TestAtlasRelationshipType {
+
+ private AtlasTypeRegistry typeRegistry = new AtlasTypeRegistry();
+
+ private static final String EMPLOYEE_TYPE = "employee";
+ private static final String DEPARTMENT_TYPE = "department";
+ private static final String ADDRESS_TYPE = "address";
+ private static final String PHONE_TYPE = "phone";
+ private static final String DEPT_EMPLOYEE_RELATION_TYPE = "departmentEmployee";
+ private static final String EMPLOYEE_ADDRESS_RELATION_TYPE = "employeeAddress";
+ private static final String EMPLOYEE_PHONE_RELATION_TYPE = "employeePhone";
+
+ @Test
+ public void createTypesAndRelationships() throws AtlasBaseException {
+ createEmployeeTypes();
+
+ createRelationshipTypes();
+ }
+
@Test
public void testvalidateAtlasRelationshipDef() throws AtlasBaseException {
AtlasRelationshipEndDef ep1 = new AtlasRelationshipEndDef("typeA", "attr1", AtlasStructDef.AtlasAttributeDef.Cardinality.SINGLE);
@@ -104,4 +137,119 @@
}
}
+
+ @Test(dependsOnMethods = "createTypesAndRelationships")
+ public void testRelationshipAttributes() throws Exception {
+ Map<String, AtlasAttribute> employeeRelationAttrs = getRelationAttrsForType(EMPLOYEE_TYPE);
+
+ Assert.assertNotNull(employeeRelationAttrs);
+ Assert.assertEquals(employeeRelationAttrs.size(), 2);
+
+ Assert.assertTrue(employeeRelationAttrs.containsKey("department"));
+ Assert.assertTrue(employeeRelationAttrs.containsKey("address"));
+
+ AtlasAttribute deptAttr = employeeRelationAttrs.get("department");
+ Assert.assertEquals(deptAttr.getTypeName(), DEPARTMENT_TYPE);
+
+ AtlasAttribute addrAttr = employeeRelationAttrs.get("address");
+ Assert.assertEquals(addrAttr.getTypeName(), ADDRESS_TYPE);
+
+ Map<String, AtlasAttribute> deptRelationAttrs = getRelationAttrsForType(DEPARTMENT_TYPE);
+
+ Assert.assertNotNull(deptRelationAttrs);
+ Assert.assertEquals(deptRelationAttrs.size(), 1);
+ Assert.assertTrue(deptRelationAttrs.containsKey("employees"));
+
+ AtlasAttribute employeesAttr = deptRelationAttrs.get("employees");
+ Assert.assertEquals(employeesAttr.getTypeName(),AtlasBaseTypeDef.getArrayTypeName(EMPLOYEE_TYPE));
+
+ Map<String, AtlasAttribute> addressRelationAttrs = getRelationAttrsForType(ADDRESS_TYPE);
+
+ Assert.assertNotNull(addressRelationAttrs);
+ Assert.assertEquals(addressRelationAttrs.size(), 1);
+ Assert.assertTrue(addressRelationAttrs.containsKey("employees"));
+
+ AtlasAttribute employeesAttr1 = addressRelationAttrs.get("employees");
+ Assert.assertEquals(employeesAttr1.getTypeName(),AtlasBaseTypeDef.getArrayTypeName(EMPLOYEE_TYPE));
+ }
+
+ @Test(dependsOnMethods = "testRelationshipAttributes")
+ public void testRelationshipAttributesOnExistingAttributes() throws Exception {
+ AtlasRelationshipDef employeePhoneRelationDef = new AtlasRelationshipDef(EMPLOYEE_PHONE_RELATION_TYPE, getDescription(EMPLOYEE_PHONE_RELATION_TYPE), "1.0",
+ RelationshipCategory.ASSOCIATION, PropagateTags.ONE_TO_TWO,
+ new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "phone_no", Cardinality.SINGLE),
+ new AtlasRelationshipEndDef(PHONE_TYPE, "owner", Cardinality.SINGLE));
+
+ createType(employeePhoneRelationDef);
+
+ Map<String, AtlasAttribute> employeeRelationshipAttrs = getRelationAttrsForType(EMPLOYEE_TYPE);
+ Map<String, AtlasAttribute> employeeAttrs = getAttrsForType(EMPLOYEE_TYPE);
+
+ // validate if phone_no exists in both relationAttributes and attributes
+ Assert.assertTrue(employeeRelationshipAttrs.containsKey("phone_no"));
+ Assert.assertTrue(employeeAttrs.containsKey("phone_no"));
+ }
+
+ private void createEmployeeTypes() throws AtlasBaseException {
+ AtlasEntityDef phoneDef = AtlasTypeUtil.createClassTypeDef(PHONE_TYPE, getDescription(PHONE_TYPE), ImmutableSet.<String>of(),
+ AtlasTypeUtil.createRequiredAttrDef("phone_number", "int"),
+ AtlasTypeUtil.createOptionalAttrDef("area_code", "int"),
+ AtlasTypeUtil.createOptionalAttrDef("owner", EMPLOYEE_TYPE));
+
+ AtlasEntityDef employeeDef = AtlasTypeUtil.createClassTypeDef(EMPLOYEE_TYPE, getDescription(EMPLOYEE_TYPE), ImmutableSet.<String>of(),
+ AtlasTypeUtil.createRequiredAttrDef("name", "string"),
+ AtlasTypeUtil.createOptionalAttrDef("dob", "date"),
+ AtlasTypeUtil.createOptionalAttrDef("age", "int"),
+ AtlasTypeUtil.createRequiredAttrDef("phone_no", PHONE_TYPE));
+
+ AtlasEntityDef departmentDef = AtlasTypeUtil.createClassTypeDef(DEPARTMENT_TYPE, getDescription(DEPARTMENT_TYPE), ImmutableSet.<String>of(),
+ AtlasTypeUtil.createRequiredAttrDef("name", "string"),
+ AtlasTypeUtil.createOptionalAttrDef("count", "int"));
+
+ AtlasEntityDef addressDef = AtlasTypeUtil.createClassTypeDef(ADDRESS_TYPE, getDescription(ADDRESS_TYPE), ImmutableSet.<String>of(),
+ AtlasTypeUtil.createOptionalAttrDef("street", "string"),
+ AtlasTypeUtil.createRequiredAttrDef("city", "string"),
+ AtlasTypeUtil.createRequiredAttrDef("state", "string"),
+ AtlasTypeUtil.createOptionalAttrDef("zip", "int"));
+
+ createTypes(new ArrayList<>(Arrays.asList(phoneDef, employeeDef, departmentDef, addressDef)));
+ }
+
+ private void createRelationshipTypes() throws AtlasBaseException {
+ AtlasRelationshipDef deptEmployeeRelationDef = new AtlasRelationshipDef(DEPT_EMPLOYEE_RELATION_TYPE, getDescription(DEPT_EMPLOYEE_RELATION_TYPE), "1.0",
+ RelationshipCategory.ASSOCIATION, PropagateTags.ONE_TO_TWO,
+ new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "department", Cardinality.SINGLE),
+ new AtlasRelationshipEndDef(DEPARTMENT_TYPE, "employees", Cardinality.SET));
+
+ AtlasRelationshipDef employeeAddrRelationDef = new AtlasRelationshipDef(EMPLOYEE_ADDRESS_RELATION_TYPE, getDescription(EMPLOYEE_ADDRESS_RELATION_TYPE), "1.0",
+ RelationshipCategory.ASSOCIATION, PropagateTags.ONE_TO_TWO,
+ new AtlasRelationshipEndDef(EMPLOYEE_TYPE, "address", Cardinality.SINGLE),
+ new AtlasRelationshipEndDef(ADDRESS_TYPE, "employees", Cardinality.SET));
+
+ createTypes(new ArrayList<>(Arrays.asList(deptEmployeeRelationDef, employeeAddrRelationDef)));
+ }
+
+ private void createType(AtlasBaseTypeDef typeDef) throws AtlasBaseException {
+ createTypes(new ArrayList<>(Arrays.asList(typeDef)));
+ }
+
+ private void createTypes(List<? extends AtlasBaseTypeDef> typeDefs) throws AtlasBaseException {
+ AtlasTransientTypeRegistry ttr = typeRegistry.lockTypeRegistryForUpdate();
+
+ ttr.addTypes(typeDefs);
+
+ typeRegistry.releaseTypeRegistryForUpdate(ttr, true);
+ }
+
+ private String getDescription(String typeName) {
+ return typeName + " description";
+ }
+
+ private Map<String, AtlasAttribute> getRelationAttrsForType(String typeName) {
+ return typeRegistry.getEntityTypeByName(typeName).getRelationshipAttributes();
+ }
+
+ private Map<String, AtlasAttribute> getAttrsForType(String typeName) {
+ return typeRegistry.getEntityTypeByName(typeName).getAllAttributes();
+ }
}
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
index 8fe4888..8621233 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1.java
@@ -20,6 +20,7 @@
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.annotation.GraphTransaction;
import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasRelationship;
import org.apache.atlas.model.typedef.AtlasRelationshipDef;
@@ -29,11 +30,9 @@
import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasVertex;
-import org.apache.atlas.repository.store.graph.AtlasRelationshipDefStore;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasRelationshipType;
-import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
@@ -46,13 +45,16 @@
import org.springframework.stereotype.Component;
import javax.inject.Inject;
+import java.util.ArrayList;
import java.util.Date;
+import java.util.List;
import java.util.Map;
import java.util.UUID;
@Component
public class AtlasRelationshipStoreV1 implements AtlasRelationshipStore {
private static final Logger LOG = LoggerFactory.getLogger(AtlasRelationshipStoreV1.class);
+ private static final int DEFAULT_RELATIONSHIP_VERSION = 0;
private final AtlasTypeRegistry typeRegistry;
private final EntityGraphRetriever entityRetriever;
@@ -182,7 +184,7 @@
AtlasRelationshipType relationshipType = typeRegistry.getRelationshipTypeByName(relationshipName);
if (relationshipType == null) {
- throw new AtlasBaseException(AtlasErrorCode.INVALID_VALUE, "unknown relationship '" + relationshipName + "'");
+ throw new AtlasBaseException(AtlasErrorCode.INVALID_VALUE, "unknown relationship type'" + relationshipName + "'");
}
AtlasObjectId end1 = relationship.getEnd1();
@@ -222,6 +224,8 @@
validateEnd(end1);
validateEnd(end2);
+
+ validateAndNormalize(relationship);
}
private void validateEnd(AtlasObjectId end) throws AtlasBaseException {
@@ -241,6 +245,28 @@
}
}
+ private void validateAndNormalize(AtlasRelationship relationship) throws AtlasBaseException {
+ List<String> messages = new ArrayList<>();
+
+ if (! AtlasTypeUtil.isValidGuid(relationship.getGuid())) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_GUID_NOT_FOUND, relationship.getGuid());
+ }
+
+ AtlasRelationshipType type = typeRegistry.getRelationshipTypeByName(relationship.getTypeName());
+
+ if (type == null) {
+ throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.RELATIONSHIP.name(), relationship.getTypeName());
+ }
+
+ type.validateValue(relationship, relationship.getTypeName(), messages);
+
+ if (!messages.isEmpty()) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIP_CRUD_INVALID_PARAMS, messages);
+ }
+
+ type.getNormalizedValue(relationship);
+ }
+
private AtlasEdge getRelationshipEdge(AtlasVertex fromVertex, AtlasVertex toVertex, String relationshipLabel) {
AtlasEdge ret = graphHelper.getEdgeForLabel(fromVertex, relationshipLabel);
@@ -261,7 +287,7 @@
private int getRelationVersion(AtlasRelationship relationship) {
Long ret = relationship != null ? relationship.getVersion() : null;
- return (ret != null) ? ret.intValue() : 0;
+ return (ret != null) ? ret.intValue() : DEFAULT_RELATIONSHIP_VERSION;
}
private AtlasVertex getVertexFromEndPoint(AtlasObjectId endPoint) {
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java b/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
index 144080a..7174543 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/RelationshipREST.java
@@ -40,7 +40,7 @@
/**
* REST interface for entity relationships.
*/
-@Path("v2/relation")
+@Path("v2/relationship")
@Singleton
@Service
public class RelationshipREST {
@@ -68,6 +68,7 @@
}
return relationshipStore.create(relationship);
+
} finally {
AtlasPerfTracer.log(perf);
}
@@ -88,6 +89,7 @@
}
return relationshipStore.update(relationship);
+
} finally {
AtlasPerfTracer.log(perf);
}
@@ -109,6 +111,7 @@
}
return relationshipStore.getById(guid);
+
} finally {
AtlasPerfTracer.log(perf);
}
@@ -134,4 +137,4 @@
AtlasPerfTracer.log(perf);
}
}
-}
+}
\ No newline at end of file