You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/07/24 15:57:33 UTC
[28/39] atlas git commit: ATLAS-1959: Enhance relationship attributes
to support cardinality mappings
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
index 157f8cd..1282be5 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphMapper.java
@@ -45,6 +45,7 @@ import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasMapType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
+import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil;
@@ -63,7 +64,11 @@ import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.DE
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.PARTIAL_UPDATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.UPDATE;
import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY;
+import static org.apache.atlas.repository.graph.GraphHelper.getTypeName;
+import static org.apache.atlas.repository.graph.GraphHelper.isRelationshipEdge;
import static org.apache.atlas.repository.graph.GraphHelper.string;
+import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection.IN;
@Component
public class EntityGraphMapper {
@@ -144,6 +149,8 @@ public class EntityGraphMapper {
mapAttributes(createdEntity, vertex, CREATE, context);
+ mapRelationshipAttributes(createdEntity, vertex, CREATE, context);
+
resp.addEntity(CREATE, constructHeader(createdEntity, entityType, vertex));
addClassifications(context, guid, createdEntity.getClassifications());
}
@@ -157,6 +164,8 @@ public class EntityGraphMapper {
mapAttributes(updatedEntity, vertex, UPDATE, context);
+ mapRelationshipAttributes(updatedEntity, vertex, UPDATE, context);
+
if (isPartialUpdate) {
resp.addEntity(PARTIAL_UPDATE, constructHeader(updatedEntity, entityType, vertex));
} else {
@@ -238,6 +247,7 @@ public class EntityGraphMapper {
mapAttribute(attribute, attrValue, vertex, op, context);
}
+
} else if (op.equals(UPDATE)) {
for (String attrName : struct.getAttributes().keySet()) {
AtlasAttribute attribute = structType.getAttribute(attrName);
@@ -260,6 +270,41 @@ public class EntityGraphMapper {
}
}
+ private void mapRelationshipAttributes(AtlasEntity entity, AtlasVertex vertex, EntityOperation op,
+ EntityMutationContext context) throws AtlasBaseException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("==> mapRelationshipAttributes({}, {})", op, entity.getTypeName());
+ }
+
+ if (MapUtils.isNotEmpty(entity.getRelationshipAttributes())) {
+ AtlasEntityType entityType = getEntityType(entity.getTypeName());
+
+ if (op.equals(CREATE)) {
+ for (AtlasAttribute attribute : entityType.getRelationshipAttributes().values()) {
+ Object attrValue = entity.getRelationshipAttribute(attribute.getName());
+
+ mapAttribute(attribute, attrValue, vertex, op, context);
+ }
+
+ } else if (op.equals(UPDATE)) {
+ // relationship attributes mapping
+ for (AtlasAttribute attribute : entityType.getRelationshipAttributes().values()) {
+ if (attribute != null && entity.hasRelationshipAttribute(attribute.getName())) {
+ Object attrValue = entity.getRelationshipAttribute(attribute.getName());
+
+ mapAttribute(attribute, attrValue, vertex, op, context);
+ }
+ }
+ }
+
+ updateModificationMetadata(vertex);
+ }
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("<== mapRelationshipAttributes({}, {})", op, entity.getTypeName());
+ }
+ }
+
private void mapAttribute(AtlasAttribute attribute, Object attrValue, AtlasVertex vertex, EntityOperation op, EntityMutationContext context) throws AtlasBaseException {
if (attrValue == null) {
AtlasAttributeDef attributeDef = attribute.getAttributeDef();
@@ -309,14 +354,15 @@ public class EntityGraphMapper {
}
case OBJECT_ID_TYPE: {
- String edgeLabel = ctx.getAttribute().getRelationshipEdgeLabel();
+ String edgeLabel = ctx.getAttribute().getRelationshipEdgeLabel();
+ AtlasRelationshipEdgeDirection edgeDirection = ctx.getAttribute().getRelationshipEdgeDirection();
// legacy case - if relationship attribute doesn't exist, use legacy edge label.
if (StringUtils.isEmpty(edgeLabel)) {
edgeLabel = AtlasGraphUtilsV1.getEdgeLabel(ctx.getVertexProperty());
}
- AtlasEdge currentEdge = graphHelper.getEdgeForLabel(ctx.getReferringVertex(), edgeLabel);
+ AtlasEdge currentEdge = graphHelper.getEdgeForLabel(ctx.getReferringVertex(), edgeLabel, edgeDirection);
AtlasEdge newEdge = null;
if (ctx.getValue() != null) {
@@ -328,14 +374,41 @@ public class EntityGraphMapper {
newEdge = mapObjectIdValueUsingRelationship(ctx, context);
- if (newEdge != null && ctx.getAttribute().getInverseRefAttribute() != null) {
+ // legacy case update inverse attribute
+ if (ctx.getAttribute().getInverseRefAttribute() != null) {
// Update the inverse reference using relationship on the target entity
addInverseReference(ctx.getAttribute().getInverseRefAttribute(), newEdge);
}
}
+ // created new relationship,
+ // record entity update on both vertices of the new relationship
+ if (currentEdge == null && newEdge != null) {
+
+ // based on relationship edge direction record update only on attribute vertex
+ if (edgeDirection == IN) {
+ recordEntityUpdate(newEdge.getOutVertex());
+
+ } else {
+ recordEntityUpdate(newEdge.getInVertex());
+ }
+ }
+
+ // update references, if current and new edge don't match
+ // record entity update on new reference and delete(edge) old reference.
if (currentEdge != null && !currentEdge.equals(newEdge)) {
- deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(), true);
+
+ //record entity update on new edge
+ if (isRelationshipEdge(newEdge)) {
+ AtlasVertex attrVertex = context.getDiscoveryContext().getResolvedEntityVertex(getGuid(ctx.getValue()));
+
+ recordEntityUpdate(attrVertex);
+ updateModificationMetadata(attrVertex);
+ }
+
+ //delete old reference
+ deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(),
+ true, ctx.getAttribute().getRelationshipEdgeDirection());
}
return newEdge;
@@ -402,7 +475,7 @@ public class EntityGraphMapper {
if (inverseUpdated) {
updateModificationMetadata(inverseVertex);
- AtlasObjectId inverseEntityId = new AtlasObjectId(AtlasGraphUtilsV1.getIdFromVertex(inverseVertex), inverseType.getTypeName());
+ AtlasObjectId inverseEntityId = new AtlasObjectId(getIdFromVertex(inverseVertex), inverseType.getTypeName());
RequestContextV1.get().recordEntityUpdate(inverseEntityId);
}
}
@@ -424,7 +497,7 @@ public class EntityGraphMapper {
if (entityType.hasRelationshipAttribute(inverseAttributeName)) {
String relationshipName = graphHelper.getRelationshipDefName(inverseVertex, entityType, inverseAttributeName);
- ret = getOrCreateRelationship(inverseVertex, vertex, relationshipName);
+ ret = getOrCreateRelationship(inverseVertex, vertex, relationshipName, inverseAttribute);
} else {
if (LOG.isDebugEnabled()) {
@@ -576,24 +649,47 @@ public class EntityGraphMapper {
String attributeName = ctx.getAttribute().getName();
AtlasType type = typeRegistry.getType(AtlasGraphUtilsV1.getTypeName(entityVertex));
+ AtlasRelationshipEdgeDirection edgeDirection = ctx.getAttribute().getRelationshipEdgeDirection();
+ String edgeLabel = ctx.getAttribute().getRelationshipEdgeLabel();
+
if (type instanceof AtlasEntityType) {
AtlasEntityType entityType = (AtlasEntityType) type;
// use relationship to create/update edges
if (entityType.hasRelationshipAttribute(attributeName)) {
if (ctx.getCurrentEdge() != null) {
- ret = updateRelationship(ctx.getCurrentEdge(), attributeVertex);
+ ret = updateRelationship(ctx.getCurrentEdge(), attributeVertex, edgeDirection, ctx.getAttribute());
+
+ recordEntityUpdate(attributeVertex);
} else {
- String relationshipName = graphHelper.getRelationshipDefName(entityVertex, entityType, attributeName);
- ret = getOrCreateRelationship(entityVertex, attributeVertex, relationshipName);
- }
+ String relationshipName = graphHelper.getRelationshipDefName(entityVertex, entityType, attributeName);
+ AtlasVertex fromVertex;
+ AtlasVertex toVertex;
+
+ if (edgeDirection == IN) {
+ fromVertex = attributeVertex;
+ toVertex = entityVertex;
+
+ } else {
+ fromVertex = entityVertex;
+ toVertex = attributeVertex;
+ }
+ boolean relationshipExists = isRelationshipExists(fromVertex, toVertex, edgeLabel);
+
+ ret = getOrCreateRelationship(fromVertex, toVertex, relationshipName, ctx.getAttribute());
+ // if relationship did not exist before and new relationship was created
+ // record entity update on both relationship vertices
+ if (!relationshipExists) {
+ recordEntityUpdate(attributeVertex);
+ }
+ }
} else {
// use legacy way to create/update edges
if (LOG.isDebugEnabled()) {
- LOG.debug("No RelationshipDef defined between {} and {} on attribute: {}", AtlasGraphUtilsV1.getTypeName(entityVertex),
- AtlasGraphUtilsV1.getTypeName(attributeVertex), attributeName);
+ LOG.debug("No RelationshipDef defined between {} and {} on attribute: {}", getTypeName(entityVertex),
+ getTypeName(attributeVertex), attributeName);
}
ret = mapObjectIdValue(ctx, context);
@@ -728,6 +824,21 @@ public class EntityGraphMapper {
return newElementsCreated;
}
+ private boolean isRelationshipAttribute(AtlasAttribute attribute) {
+ boolean ret = false;
+
+ if (attribute != null) {
+ AtlasStructType structType = attribute.getDefinedInType();
+ String attributeName = attribute.getName();
+
+ if (structType instanceof AtlasEntityType) {
+ ret = ((AtlasEntityType) structType).hasRelationshipAttribute(attributeName);
+ }
+ }
+
+ return ret;
+ }
+
private AtlasEdge createVertex(AtlasStruct struct, AtlasVertex referringVertex, String edgeLabel, EntityMutationContext context) throws AtlasBaseException {
AtlasVertex vertex = createStructVertex(struct);
@@ -767,6 +878,16 @@ public class EntityGraphMapper {
return (AtlasStructType)objType;
}
+ private AtlasEntityType getEntityType(String typeName) throws AtlasBaseException {
+ AtlasType objType = typeRegistry.getType(typeName);
+
+ if (!(objType instanceof AtlasEntityType)) {
+ throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, typeName);
+ }
+
+ return (AtlasEntityType)objType;
+ }
+
private Object mapCollectionElementsToVertex(AttributeMutationContext ctx, EntityMutationContext context) throws AtlasBaseException {
switch(ctx.getAttrType().getTypeCategory()) {
case PRIMITIVE:
@@ -918,8 +1039,8 @@ public class EntityGraphMapper {
// Update edge if it exists
AtlasVertex currentVertex = currentEdge.getInVertex();
- String currentEntityId = AtlasGraphUtilsV1.getIdFromVertex(currentVertex);
- String newEntityId = AtlasGraphUtilsV1.getIdFromVertex(entityVertex);
+ String currentEntityId = getIdFromVertex(currentVertex);
+ String newEntityId = getIdFromVertex(entityVertex);
AtlasEdge newEdge = currentEdge;
if (!currentEntityId.equals(newEntityId)) {
@@ -936,16 +1057,25 @@ public class EntityGraphMapper {
return newEdge;
}
- private AtlasEdge updateRelationship(AtlasEdge currentEdge, final AtlasVertex entityVertex) throws AtlasBaseException {
+ private AtlasEdge updateRelationship(AtlasEdge currentEdge, final AtlasVertex newEntityVertex,
+ AtlasRelationshipEdgeDirection edgeDirection, AtlasAttribute attribute)
+ throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
- LOG.debug("Updating entity reference using relationship {} for reference attribute {}", AtlasGraphUtilsV1.getTypeName(entityVertex));
+ LOG.debug("Updating entity reference using relationship {} for reference attribute {}", getTypeName(newEntityVertex));
}
- String currentEntityId = AtlasGraphUtilsV1.getIdFromVertex(currentEdge.getInVertex());
- String newEntityId = AtlasGraphUtilsV1.getIdFromVertex(entityVertex);
- AtlasEdge ret = currentEdge;
+ // Max's manager updated from Jane to Julius (Max.manager --> Jane.subordinates)
+ // manager attribute (OUT direction), current manager vertex (Jane) (IN vertex)
- if (!currentEntityId.equals(newEntityId)) {
+ // Max's mentor updated from John to Jane (John.mentee --> Max.mentor)
+ // mentor attribute (IN direction), current mentee vertex (John) (OUT vertex)
+ String currentEntityId = (edgeDirection == IN) ? getIdFromVertex(currentEdge.getOutVertex()) :
+ getIdFromVertex(currentEdge.getInVertex());
+
+ String newEntityId = getIdFromVertex(newEntityVertex);
+ AtlasEdge ret = currentEdge;
+
+ if (!currentEntityId.equals(newEntityId) && newEntityVertex != null) {
// create a new relationship edge to the new attribute vertex from the instance
String relationshipName = AtlasGraphUtilsV1.getTypeName(currentEdge);
@@ -953,7 +1083,8 @@ public class EntityGraphMapper {
relationshipName = currentEdge.getLabel();
}
- ret = getOrCreateRelationship(currentEdge.getOutVertex(), entityVertex, relationshipName);
+ ret = (edgeDirection == IN) ? getOrCreateRelationship(newEntityVertex, currentEdge.getInVertex(), relationshipName, attribute) :
+ getOrCreateRelationship(currentEdge.getOutVertex(), newEntityVertex, relationshipName, attribute);
}
return ret;
@@ -983,8 +1114,7 @@ public class EntityGraphMapper {
//Removes unused edges from the old collection, compared to the new collection
private List<AtlasEdge> removeUnusedArrayEntries(AtlasAttribute attribute, List<AtlasEdge> currentEntries, List<AtlasEdge> newEntries) throws AtlasBaseException {
if (CollectionUtils.isNotEmpty(currentEntries)) {
- AtlasStructType entityType = attribute.getDefinedInType();
- AtlasType entryType = ((AtlasArrayType)attribute.getAttributeType()).getElementType();
+ AtlasType entryType = ((AtlasArrayType) attribute.getAttributeType()).getElementType();
if (AtlasGraphUtilsV1.isReference(entryType)) {
Collection<AtlasEdge> edgesToRemove = CollectionUtils.subtract(currentEntries, newEntries);
@@ -993,7 +1123,8 @@ public class EntityGraphMapper {
List<AtlasEdge> additionalElements = new ArrayList<>();
for (AtlasEdge edge : edgesToRemove) {
- boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(), true);
+ boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(),
+ true, attribute.getRelationshipEdgeDirection());
if (!deleted) {
additionalElements.add(edge);
@@ -1021,7 +1152,7 @@ public class EntityGraphMapper {
private AtlasEntityHeader constructHeader(AtlasEntity entity, final AtlasEntityType type, AtlasVertex vertex) {
AtlasEntityHeader header = new AtlasEntityHeader(entity.getTypeName());
- header.setGuid(AtlasGraphUtilsV1.getIdFromVertex(vertex));
+ header.setGuid(getIdFromVertex(vertex));
for (AtlasAttribute attribute : type.getUniqAttributes().values()) {
header.setAttribute(attribute.getName(), entity.getAttribute(attribute.getName()));
@@ -1148,7 +1279,7 @@ public class EntityGraphMapper {
for (String classificationName : classificationNames) {
try {
- final String entityTypeName = GraphHelper.getTypeName(instanceVertex);
+ final String entityTypeName = getTypeName(instanceVertex);
String relationshipLabel = GraphHelper.getTraitLabel(entityTypeName, classificationName);
AtlasEdge edge = graphHelper.getEdgeForLabel(instanceVertex, relationshipLabel);
if (edge != null) {
@@ -1182,20 +1313,20 @@ public class EntityGraphMapper {
}
}
- private AtlasEdge getOrCreateRelationship(AtlasVertex end1Vertex, AtlasVertex end2Vertex, String relationshipName) throws AtlasBaseException {
- AtlasEdge ret = null;
- AtlasObjectId end1 = new AtlasObjectId(AtlasGraphUtilsV1.getIdFromVertex(end1Vertex), AtlasGraphUtilsV1.getTypeName(end1Vertex));
- AtlasObjectId end2 = new AtlasObjectId(AtlasGraphUtilsV1.getIdFromVertex(end2Vertex), AtlasGraphUtilsV1.getTypeName(end2Vertex));
- AtlasRelationship relationship = relationshipStore.getOrCreate(new AtlasRelationship(relationshipName, end1, end2));
+ private AtlasEdge getOrCreateRelationship(AtlasVertex end1Vertex, AtlasVertex end2Vertex, String relationshipName, AtlasAttribute attribute) throws AtlasBaseException {
+ AtlasEdge ret = null;
+ AtlasObjectId end1 = new AtlasObjectId(getIdFromVertex(end1Vertex), AtlasGraphUtilsV1.getTypeName(end1Vertex));
+ AtlasObjectId end2 = new AtlasObjectId(getIdFromVertex(end2Vertex), AtlasGraphUtilsV1.getTypeName(end2Vertex));
+ AtlasRelationship relationship = relationshipStore.getOrCreate(new AtlasRelationship(relationshipName, end1, end2));
// return newly created AtlasEdge
- // if multiple edges are returned, compare using id to pick the right one
+ // if multiple edges are returned, compare using guid to pick the right one
Iterator<AtlasEdge> outEdges = graphHelper.getOutGoingEdgesByLabel(end1Vertex, relationship.getLabel());
while (outEdges.hasNext()) {
AtlasEdge edge = outEdges.next();
- if (AtlasGraphUtilsV1.getIdFromVertex(end2Vertex).equals(AtlasGraphUtilsV1.getIdFromVertex(edge.getInVertex()))) {
+ if (getIdFromVertex(end2Vertex).equals(getIdFromVertex(edge.getInVertex()))) {
ret = edge;
break;
}
@@ -1203,4 +1334,47 @@ public class EntityGraphMapper {
return ret;
}
+
+ private boolean isRelationshipExists(AtlasVertex fromVertex, AtlasVertex toVertex, String edgeLabel) {
+ boolean ret = false;
+ Iterator<AtlasEdge> edges = graphHelper.getOutGoingEdgesByLabel(fromVertex, edgeLabel);
+
+ while (edges != null && edges.hasNext()) {
+ AtlasEdge edge = edges.next();
+ AtlasVertex inVertex = edge.getInVertex();
+
+ if (inVertex != null && StringUtils.equals(getIdFromVertex(inVertex), getIdFromVertex(toVertex))) {
+ ret = true;
+ }
+ }
+
+ return ret;
+ }
+
+ private void recordEntityUpdate(AtlasVertex vertex) {
+ AtlasObjectId objectId = new AtlasObjectId(GraphHelper.getGuid(vertex), GraphHelper.getTypeName(vertex));
+ RequestContextV1 req = RequestContextV1.get();
+
+ if (!objectIdsContain(req.getUpdatedEntityIds(), objectId)) {
+ req.recordEntityUpdate(objectId);
+ }
+ }
+
+ private boolean objectIdsContain(Collection<AtlasObjectId> objectIds, AtlasObjectId objectId) {
+ boolean ret = false;
+
+ if (objectIds != null && objectIds.isEmpty()) {
+ ret = false;
+
+ } else {
+ for (AtlasObjectId id : objectIds) {
+ if (StringUtils.equals(id.getGuid(), objectId.getGuid())) {
+ ret = true;
+ break;
+ }
+ }
+ }
+
+ return ret;
+ }
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
index f4257be..31fc837 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/EntityGraphRetriever.java
@@ -69,6 +69,7 @@ import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_SHORT;
import static org.apache.atlas.model.typedef.AtlasBaseTypeDef.ATLAS_TYPE_STRING;
import static org.apache.atlas.repository.graph.GraphHelper.EDGE_LABEL_PREFIX;
import static org.apache.atlas.repository.store.graph.v1.AtlasGraphUtilsV1.getIdFromVertex;
+import static org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
public final class EntityGraphRetriever {
@@ -136,6 +137,10 @@ public final class EntityGraphRetriever {
return toAtlasEntityHeader(entityVertex, Collections.<String>emptySet());
}
+ public AtlasEntityHeader toAtlasEntityHeader(AtlasVertex atlasVertex, Set<String> attributes) throws AtlasBaseException {
+ return atlasVertex != null ? mapVertexToAtlasEntityHeader(atlasVertex, attributes) : null;
+ }
+
private AtlasVertex getEntityVertex(String guid) throws AtlasBaseException {
AtlasVertex ret = AtlasGraphUtilsV1.findByGuid(guid);
@@ -188,7 +193,7 @@ public final class EntityGraphRetriever {
mapAttributes(entityVertex, entity, entityExtInfo);
- mapRelationshipAttributes(entityVertex, entity, entityExtInfo);
+ mapRelationshipAttributes(entityVertex, entity);
mapClassifications(entityVertex, entity, entityExtInfo);
}
@@ -300,23 +305,6 @@ public final class EntityGraphRetriever {
}
}
- private void mapRelationshipAttributes(AtlasVertex entityVertex, AtlasEntity entity, AtlasEntityExtInfo entityExtInfo) throws AtlasBaseException {
- AtlasType objType = typeRegistry.getType(entity.getTypeName());
-
- if (!(objType instanceof AtlasEntityType)) {
- throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, entity.getTypeName());
- }
-
- AtlasEntityType entityType = (AtlasEntityType) objType;
-
- for (AtlasAttribute attribute : entityType.getRelationshipAttributes().values()) {
-
- Object attrValue = mapVertexToRelationshipAttribute(entityVertex, entityType, attribute, entityExtInfo);
-
- entity.addRelationshipAttribute(attribute.getName(), attrValue);
- }
- }
-
public List<AtlasClassification> getClassifications(String guid) throws AtlasBaseException {
AtlasVertex instanceVertex = AtlasGraphUtilsV1.findByGuid(guid);
@@ -401,6 +389,7 @@ public final class EntityGraphRetriever {
String vertexPropertyName = attribute.getQualifiedName();
String edgeLabel = EDGE_LABEL_PREFIX + vertexPropertyName;
boolean isOwnedAttribute = attribute.isOwnedRef();
+ AtlasRelationshipEdgeDirection edgeDirection = attribute.getRelationshipEdgeDirection();
if (LOG.isDebugEnabled()) {
LOG.debug("Mapping vertex {} to atlas entity {}.{}", entityVertex, attribute.getDefinedInDef().getName(), attribute.getName());
@@ -417,13 +406,13 @@ public final class EntityGraphRetriever {
ret = mapVertexToStruct(entityVertex, edgeLabel, null, entityExtInfo);
break;
case OBJECT_ID_TYPE:
- ret = mapVertexToObjectId(entityVertex, edgeLabel, null, entityExtInfo, isOwnedAttribute);
+ ret = mapVertexToObjectId(entityVertex, edgeLabel, null, entityExtInfo, isOwnedAttribute, edgeDirection);
break;
case ARRAY:
- ret = mapVertexToArray(entityVertex, (AtlasArrayType) attrType, vertexPropertyName, entityExtInfo, isOwnedAttribute);
+ ret = mapVertexToArray(entityVertex, (AtlasArrayType) attrType, vertexPropertyName, entityExtInfo, isOwnedAttribute, edgeDirection);
break;
case MAP:
- ret = mapVertexToMap(entityVertex, (AtlasMapType) attrType, vertexPropertyName, entityExtInfo, isOwnedAttribute);
+ ret = mapVertexToMap(entityVertex, (AtlasMapType) attrType, vertexPropertyName, entityExtInfo, isOwnedAttribute, edgeDirection);
break;
case CLASSIFICATION:
// do nothing
@@ -433,51 +422,10 @@ public final class EntityGraphRetriever {
return ret;
}
- private Object mapVertexToRelationshipAttribute(AtlasVertex entityVertex, AtlasEntityType entityType, AtlasAttribute attribute,
- AtlasEntityExtInfo entityExtInfo) throws AtlasBaseException {
- Object ret = null;
- AtlasRelationshipDef relationshipDef = graphHelper.getRelationshipDef(entityVertex, entityType, attribute.getName());
-
- if (relationshipDef == null) {
- throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID, "relationshipDef is null");
- }
-
- AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1();
- AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2();
- AtlasEntityType endDef1Type = typeRegistry.getEntityTypeByName(endDef1.getType());
- AtlasEntityType endDef2Type = typeRegistry.getEntityTypeByName(endDef2.getType());
- AtlasRelationshipEndDef attributeEndDef = null;
-
- if (endDef1Type.isTypeOrSuperTypeOf(entityType.getTypeName()) && StringUtils.equals(endDef1.getName(), attribute.getName())) {
- attributeEndDef = endDef1;
-
- } else if (endDef2Type.isTypeOrSuperTypeOf(entityType.getTypeName()) && StringUtils.equals(endDef2.getName(), attribute.getName())) {
- attributeEndDef = endDef2;
- }
-
- if (attributeEndDef == null) {
- throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID, relationshipDef.toString());
- }
-
- String relationshipLabel = attribute.getRelationshipEdgeLabel();
-
- switch (attributeEndDef.getCardinality()) {
- case SINGLE:
- ret = mapVertexToObjectId(entityVertex, relationshipLabel, null, entityExtInfo, attributeEndDef.getIsContainer());
- break;
-
- case LIST:
- case SET:
- ret = mapVertexToRelationshipArrayAttribute(entityVertex, (AtlasArrayType) attribute.getAttributeType(), relationshipLabel,
- entityExtInfo, attributeEndDef.getIsContainer());
- break;
- }
-
- return ret;
- }
-
private Map<String, Object> mapVertexToMap(AtlasVertex entityVertex, AtlasMapType atlasMapType, final String propertyName,
- AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute) throws AtlasBaseException {
+ AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute,
+ AtlasRelationshipEdgeDirection edgeDirection) throws AtlasBaseException {
+
List<String> mapKeys = GraphHelper.getListProperty(entityVertex, propertyName);
if (CollectionUtils.isEmpty(mapKeys)) {
@@ -496,7 +444,9 @@ public final class EntityGraphRetriever {
final String edgeLabel = EDGE_LABEL_PREFIX + keyPropertyName;
final Object keyValue = GraphHelper.getMapValueProperty(mapValueType, entityVertex, keyPropertyName);
- Object mapValue = mapVertexToCollectionEntry(entityVertex, mapValueType, keyValue, edgeLabel, entityExtInfo, isOwnedAttribute);
+ Object mapValue = mapVertexToCollectionEntry(entityVertex, mapValueType, keyValue, edgeLabel,
+ entityExtInfo, isOwnedAttribute, edgeDirection);
+
if (mapValue != null) {
ret.put(mapKey, mapValue);
}
@@ -506,7 +456,9 @@ public final class EntityGraphRetriever {
}
private List<Object> mapVertexToArray(AtlasVertex entityVertex, AtlasArrayType arrayType, String propertyName,
- AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute) throws AtlasBaseException {
+ AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute,
+ AtlasRelationshipEdgeDirection edgeDirection) throws AtlasBaseException {
+
AtlasType arrayElementType = arrayType.getElementType();
List<Object> arrayElements = GraphHelper.getArrayElementsProperty(arrayElementType, entityVertex, propertyName);
@@ -522,8 +474,8 @@ public final class EntityGraphRetriever {
String edgeLabel = EDGE_LABEL_PREFIX + propertyName;
for (Object element : arrayElements) {
- Object arrValue = mapVertexToCollectionEntry(entityVertex, arrayElementType, element,
- edgeLabel, entityExtInfo, isOwnedAttribute);
+ Object arrValue = mapVertexToCollectionEntry(entityVertex, arrayElementType, element, edgeLabel,
+ entityExtInfo, isOwnedAttribute, edgeDirection);
if (arrValue != null) {
arrValues.add(arrValue);
@@ -533,42 +485,9 @@ public final class EntityGraphRetriever {
return arrValues;
}
- private List<Object> mapVertexToRelationshipArrayAttribute(AtlasVertex entityVertex, AtlasArrayType arrayType,
- String relationshipName, AtlasEntityExtInfo entityExtInfo,
- boolean isContainer) throws AtlasBaseException {
-
- Iterator<AtlasEdge> relationshipEdges = graphHelper.getBothEdgesByLabel(entityVertex, relationshipName);
- AtlasType arrayElementType = arrayType.getElementType();
- List<AtlasEdge> arrayElements = new ArrayList<>();
-
- if (LOG.isDebugEnabled()) {
- LOG.debug("Mapping array attribute {} for vertex {}", arrayElementType.getTypeName(), entityVertex);
- }
-
- while (relationshipEdges.hasNext()) {
- arrayElements.add(relationshipEdges.next());
- }
-
- if (CollectionUtils.isEmpty(arrayElements)) {
- return null;
- }
-
- List arrValues = new ArrayList(arrayElements.size());
-
- for (Object element : arrayElements) {
- Object arrValue = mapVertexToCollectionEntry(entityVertex, arrayElementType, element, relationshipName,
- entityExtInfo, isContainer);
-
- if (arrValue != null) {
- arrValues.add(arrValue);
- }
- }
-
- return arrValues;
- }
-
- private Object mapVertexToCollectionEntry(AtlasVertex entityVertex, AtlasType arrayElement, Object value, String edgeLabel,
- AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute) throws AtlasBaseException {
+ private Object mapVertexToCollectionEntry(AtlasVertex entityVertex, AtlasType arrayElement, Object value,
+ String edgeLabel, AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute,
+ AtlasRelationshipEdgeDirection edgeDirection) throws AtlasBaseException {
Object ret = null;
switch (arrayElement.getTypeCategory()) {
@@ -587,7 +506,7 @@ public final class EntityGraphRetriever {
break;
case OBJECT_ID_TYPE:
- ret = mapVertexToObjectId(entityVertex, edgeLabel, (AtlasEdge) value, entityExtInfo, isOwnedAttribute);
+ ret = mapVertexToObjectId(entityVertex, edgeLabel, (AtlasEdge) value, entityExtInfo, isOwnedAttribute, edgeDirection);
break;
default:
@@ -646,11 +565,12 @@ public final class EntityGraphRetriever {
}
private AtlasObjectId mapVertexToObjectId(AtlasVertex entityVertex, String edgeLabel, AtlasEdge edge,
- AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute) throws AtlasBaseException {
+ AtlasEntityExtInfo entityExtInfo, boolean isOwnedAttribute,
+ AtlasRelationshipEdgeDirection edgeDirection) throws AtlasBaseException {
AtlasObjectId ret = null;
if (edge == null) {
- edge = graphHelper.getEdgeForLabel(entityVertex, edgeLabel);
+ edge = graphHelper.getEdgeForLabel(entityVertex, edgeLabel, edgeDirection);
}
if (GraphHelper.elementExists(edge)) {
@@ -697,7 +617,102 @@ public final class EntityGraphRetriever {
return vertex != null && attribute != null ? mapVertexToAttribute(vertex, attribute, null) : null;
}
- public AtlasEntityHeader toAtlasEntityHeader(AtlasVertex atlasVertex, Set<String> attributes) throws AtlasBaseException {
- return atlasVertex != null ? mapVertexToAtlasEntityHeader(atlasVertex, attributes) : null;
+ private void mapRelationshipAttributes(AtlasVertex entityVertex, AtlasEntity entity) throws AtlasBaseException {
+ AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
+
+ if (entityType == null) {
+ throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, entity.getTypeName());
+ }
+
+ for (AtlasAttribute attribute : entityType.getRelationshipAttributes().values()) {
+ Object attrValue = mapVertexToRelationshipAttribute(entityVertex, entityType, attribute);
+
+ entity.setRelationshipAttribute(attribute.getName(), attrValue);
+ }
+ }
+
+ private Object mapVertexToRelationshipAttribute(AtlasVertex entityVertex, AtlasEntityType entityType, AtlasAttribute attribute) throws AtlasBaseException {
+ Object ret = null;
+ AtlasRelationshipDef relationshipDef = graphHelper.getRelationshipDef(entityVertex, entityType, attribute.getName());
+
+ if (relationshipDef == null) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID, "relationshipDef is null");
+ }
+
+ AtlasRelationshipEndDef endDef1 = relationshipDef.getEndDef1();
+ AtlasRelationshipEndDef endDef2 = relationshipDef.getEndDef2();
+ AtlasEntityType endDef1Type = typeRegistry.getEntityTypeByName(endDef1.getType());
+ AtlasEntityType endDef2Type = typeRegistry.getEntityTypeByName(endDef2.getType());
+ AtlasRelationshipEndDef attributeEndDef = null;
+
+ if (endDef1Type.isTypeOrSuperTypeOf(entityType.getTypeName()) && StringUtils.equals(endDef1.getName(), attribute.getName())) {
+ attributeEndDef = endDef1;
+ } else if (endDef2Type.isTypeOrSuperTypeOf(entityType.getTypeName()) && StringUtils.equals(endDef2.getName(), attribute.getName())) {
+ attributeEndDef = endDef2;
+ }
+
+ if (attributeEndDef == null) {
+ throw new AtlasBaseException(AtlasErrorCode.RELATIONSHIPDEF_INVALID, relationshipDef.toString());
+ }
+
+ switch (attributeEndDef.getCardinality()) {
+ case SINGLE:
+ ret = mapRelatedVertexToObjectId(entityVertex, attribute);
+ break;
+
+ case LIST:
+ case SET:
+ ret = mapRelationshipArrayAttribute(entityVertex, attribute);
+ break;
+ }
+
+ return ret;
+ }
+
+ private AtlasObjectId mapRelatedVertexToObjectId(AtlasVertex entityVertex, AtlasAttribute attribute) throws AtlasBaseException {
+ AtlasEdge edge = graphHelper.getEdgeForLabel(entityVertex, attribute.getRelationshipEdgeLabel(), attribute.getRelationshipEdgeDirection());
+
+ return mapRelatedVertexToObjectId(entityVertex, edge);
+ }
+
+ private List<AtlasObjectId> mapRelationshipArrayAttribute(AtlasVertex entityVertex, AtlasAttribute attribute) throws AtlasBaseException {
+ List<AtlasObjectId> ret = new ArrayList<>();
+ Iterator<AtlasEdge> edges = null;
+
+ if (attribute.getRelationshipEdgeDirection() == AtlasRelationshipEdgeDirection.IN) {
+ edges = graphHelper.getIncomingEdgesByLabel(entityVertex, attribute.getRelationshipEdgeLabel());
+ } else if (attribute.getRelationshipEdgeDirection() == AtlasRelationshipEdgeDirection.OUT) {
+ edges = graphHelper.getOutGoingEdgesByLabel(entityVertex, attribute.getRelationshipEdgeLabel());
+ }
+
+ if (edges != null) {
+ while (edges.hasNext()) {
+ AtlasEdge relationshipEdge = edges.next();
+
+ AtlasObjectId objectId = mapRelatedVertexToObjectId(entityVertex, relationshipEdge);
+
+ ret.add(objectId);
+ }
+ }
+
+ return ret;
+ }
+
+ private AtlasObjectId mapRelatedVertexToObjectId(AtlasVertex entityVertex, AtlasEdge edge) throws AtlasBaseException {
+ AtlasObjectId ret = null;
+
+ if (GraphHelper.elementExists(edge)) {
+ AtlasVertex referenceVertex = edge.getInVertex();
+
+ if (StringUtils.equals(getIdFromVertex(referenceVertex), getIdFromVertex(entityVertex))) {
+ referenceVertex = edge.getOutVertex();
+ }
+
+ if (referenceVertex != null) {
+ ret = new AtlasObjectId(GraphHelper.getGuid(referenceVertex), GraphHelper.getTypeName(referenceVertex));
+ }
+ }
+
+ return ret;
}
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
index 404225c..7210799 100644
--- a/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ImportServiceTest.java
@@ -18,6 +18,7 @@
package org.apache.atlas.repository.impexp;
import com.google.inject.Inject;
+import org.apache.atlas.RequestContextV1;
import org.apache.atlas.TestModules;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasImportRequest;
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
index d901731..82692cf 100644
--- a/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
+++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ZipFileResourceTestUtils.java
@@ -18,6 +18,7 @@
package org.apache.atlas.repository.impexp;
import com.google.common.collect.Sets;
+import org.apache.atlas.RequestContextV1;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.impexp.AtlasExportResult;
import org.apache.atlas.model.impexp.AtlasImportRequest;
@@ -149,6 +150,8 @@ public class ZipFileResourceTestUtils {
AtlasExportResult exportResult = zipSource.getExportResult();
List<String> creationOrder = zipSource.getCreationOrder();
+ RequestContextV1.clear();
+
AtlasImportRequest request = getDefaultImportRequest();
AtlasImportResult result = runImportWithParameters(importService, request, zipSource);
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
new file mode 100644
index 0000000..2c31140
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreHardDeleteV1Test.java
@@ -0,0 +1,54 @@
+/**
+ * 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.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.testng.annotations.Guice;
+
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+
+/**
+ * Inverse reference update test with {@link HardDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.HardDeleteModule.class)
+public class AtlasRelationshipStoreHardDeleteV1Test extends AtlasRelationshipStoreV1Test {
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+ // Max should have been removed from the subordinates list, leaving only John.
+ verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John")));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
+ AtlasEntity a3, AtlasEntity b) {
+
+ verifyRelationshipAttributeValue(a1, "oneB", null);
+
+ verifyRelationshipAttributeValue(a2, "oneB", null);
+
+ verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a3)));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+ verifyRelationshipAttributeValue(a1, "b", null);
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
new file mode 100644
index 0000000..33ef8c0
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreSoftDeleteV1Test.java
@@ -0,0 +1,55 @@
+/**
+ * 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.v1;
+
+import com.google.common.collect.ImmutableList;
+import org.apache.atlas.TestModules;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.testng.annotations.Guice;
+
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+
+
+/**
+ * Inverse reference update test with {@link SoftDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.SoftDeleteModule.class)
+public class AtlasRelationshipStoreSoftDeleteV1Test extends AtlasRelationshipStoreV1Test {
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+ // Max is still in the subordinates list, as the edge still exists with state DELETED
+ verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John"), employeeNameIdMap.get("Max")));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
+ AtlasEntity a3, AtlasEntity b) {
+
+ verifyRelationshipAttributeValue(a1, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeValue(a2, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2), getAtlasObjectId(a3)));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+ verifyRelationshipAttributeValue(a1, "b", b.getGuid());
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/02e4e86b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
index 6770223..31efe86 100644
--- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/AtlasRelationshipStoreV1Test.java
@@ -17,18 +17,25 @@
*/
package org.apache.atlas.repository.store.graph.v1;
+import com.google.common.collect.ImmutableList;
import org.apache.atlas.RequestContextV1;
import org.apache.atlas.TestModules;
-import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
-import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.AtlasRelationshipStore;
import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.collections.CollectionUtils;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeTest;
@@ -36,11 +43,25 @@ import org.testng.annotations.Guice;
import org.testng.annotations.Test;
import javax.inject.Inject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import static org.apache.atlas.TestRelationshipUtilsV2.EMPLOYEE_TYPE;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeInstances;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeTypes;
+import static org.apache.atlas.TestRelationshipUtilsV2.getInverseReferenceTestTypes;
+import static org.apache.atlas.TestUtils.NAME;
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
@Guice(modules = TestModules.TestOnlyModule.class)
-public class AtlasRelationshipStoreV1Test {
+public abstract class AtlasRelationshipStoreV1Test {
@Inject
AtlasTypeRegistry typeRegistry;
@@ -56,32 +77,28 @@ public class AtlasRelationshipStoreV1Test {
AtlasEntityStore entityStore;
AtlasRelationshipStore relationshipStore;
- AtlasEntityWithExtInfo dbEntity;
- AtlasEntityWithExtInfo tblEntity;
AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
+ protected Map<String, AtlasObjectId> employeeNameIdMap = new HashMap<>();
+
@BeforeClass
public void setUp() throws Exception {
new GraphBackedSearchIndexer(typeRegistry);
- AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
- TestUtilsV2.defineHiveTypes() };
+ // create employee relationship types
+ AtlasTypesDef employeeTypes = getDepartmentEmployeeTypes();
+ typeDefStore.createTypesDef(employeeTypes);
- for (AtlasTypesDef typesDef : testTypesDefs) {
- AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+ AtlasEntitiesWithExtInfo employeeInstances = getDepartmentEmployeeInstances();
+ EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(employeeInstances), false);
- if (!typesToCreate.isEmpty()) {
- typeDefStore.createTypesDef(typesToCreate);
- }
+ for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
+ employeeNameIdMap.put((String) entityHeader.getAttribute(NAME), getAtlasObjectId(entityHeader));
}
- dbEntity = TestUtilsV2.createDBEntityV2();
- tblEntity = TestUtilsV2.createTableEntityV2(dbEntity.getEntity());
- }
-
- @AfterClass
- public void clear() {
- AtlasGraphProvider.cleanup();
+ init();
+ AtlasTypesDef testTypes = getInverseReferenceTestTypes();
+ typeDefStore.createTypesDef(testTypes);
}
@BeforeTest
@@ -92,8 +109,384 @@ public class AtlasRelationshipStoreV1Test {
RequestContextV1.clear();
}
+ @AfterClass
+ public void clear() {
+ AtlasGraphProvider.cleanup();
+ }
+
+ @Test
+ public void testDepartmentEmployeeEntitiesUsingRelationship() throws Exception {
+ AtlasObjectId hrId = employeeNameIdMap.get("hr");
+ AtlasObjectId maxId = employeeNameIdMap.get("Max");
+ AtlasObjectId johnId = employeeNameIdMap.get("John");
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId janeId = employeeNameIdMap.get("Jane");
+
+ AtlasEntity hrDept = getEntityFromStore(hrId.getGuid());
+ AtlasEntity max = getEntityFromStore(maxId.getGuid());
+ AtlasEntity john = getEntityFromStore(johnId.getGuid());
+ AtlasEntity julius = getEntityFromStore(juliusId.getGuid());
+ AtlasEntity jane = getEntityFromStore(janeId.getGuid());
+
+ // Department relationship attributes
+ List<AtlasObjectId> deptEmployees = toAtlasObjectIds(hrDept.getRelationshipAttribute("employees"));
+ assertNotNull(deptEmployees);
+ assertEquals(deptEmployees.size(), 4);
+ assertObjectIdsContains(deptEmployees, maxId);
+ assertObjectIdsContains(deptEmployees, johnId);
+ assertObjectIdsContains(deptEmployees, juliusId);
+ assertObjectIdsContains(deptEmployees, janeId);
+
+ // Max employee validation
+ AtlasObjectId maxDepartmentId = toAtlasObjectId(max.getRelationshipAttribute("department"));
+ assertNotNull(maxDepartmentId);
+ assertObjectIdEquals(maxDepartmentId, hrId);
+
+ AtlasObjectId maxManagerId = toAtlasObjectId(max.getRelationshipAttribute("manager"));
+ assertNotNull(maxManagerId);
+ assertObjectIdEquals(maxManagerId, janeId);
+
+ AtlasObjectId maxMentorId = toAtlasObjectId(max.getRelationshipAttribute("mentor"));
+ assertNotNull(maxMentorId);
+ assertObjectIdEquals(maxMentorId, juliusId);
+
+ List<AtlasObjectId> maxMenteesId = toAtlasObjectIds(max.getRelationshipAttribute("mentees"));
+ assertNotNull(maxMenteesId);
+ assertEquals(maxMenteesId.size(), 1);
+ assertObjectIdEquals(maxMenteesId.get(0), johnId);
+
+ // John Employee validation
+ AtlasObjectId johnDepartmentId = toAtlasObjectId(john.getRelationshipAttribute("department"));
+ assertNotNull(johnDepartmentId);
+ assertObjectIdEquals(johnDepartmentId, hrId);
+
+ AtlasObjectId johnManagerId = toAtlasObjectId(john.getRelationshipAttribute("manager"));
+ assertNotNull(johnManagerId);
+ assertObjectIdEquals(johnManagerId, janeId);
+
+ AtlasObjectId johnMentorId = toAtlasObjectId(john.getRelationshipAttribute("mentor"));
+ assertNotNull(johnMentorId);
+ assertObjectIdEquals(johnMentorId, maxId);
+
+ List<AtlasObjectId> johnMenteesId = toAtlasObjectIds(john.getRelationshipAttribute("mentees"));
+ assertNull(johnMenteesId);
+
+ // Jane Manager validation
+ AtlasObjectId janeDepartmentId = toAtlasObjectId(jane.getRelationshipAttribute("department"));
+ assertNotNull(janeDepartmentId);
+ assertObjectIdEquals(janeDepartmentId, hrId);
+
+ AtlasObjectId janeManagerId = toAtlasObjectId(jane.getRelationshipAttribute("manager"));
+ assertNull(janeManagerId);
+
+ AtlasObjectId janeMentorId = toAtlasObjectId(jane.getRelationshipAttribute("mentor"));
+ assertNull(janeMentorId);
+
+ List<AtlasObjectId> janeMenteesId = toAtlasObjectIds(jane.getRelationshipAttribute("mentees"));
+ assertNull(janeMenteesId);
+
+ List<AtlasObjectId> janeSubordinateIds = toAtlasObjectIds(jane.getRelationshipAttribute("subordinates"));
+ assertNotNull(janeSubordinateIds);
+ assertEquals(janeSubordinateIds.size(), 2);
+ assertObjectIdsContains(janeSubordinateIds, maxId);
+ assertObjectIdsContains(janeSubordinateIds, johnId);
+
+ // Julius Manager validation
+ AtlasObjectId juliusDepartmentId = toAtlasObjectId(julius.getRelationshipAttribute("department"));
+ assertNotNull(juliusDepartmentId);
+ assertObjectIdEquals(juliusDepartmentId, hrId);
+
+ AtlasObjectId juliusManagerId = toAtlasObjectId(julius.getRelationshipAttribute("manager"));
+ assertNull(juliusManagerId);
+
+ AtlasObjectId juliusMentorId = toAtlasObjectId(julius.getRelationshipAttribute("mentor"));
+ assertNull(juliusMentorId);
+
+ List<AtlasObjectId> juliusMenteesId = toAtlasObjectIds(julius.getRelationshipAttribute("mentees"));
+ assertNotNull(juliusMenteesId);
+ assertEquals(juliusMenteesId.size(), 1);
+ assertObjectIdsContains(juliusMenteesId, maxId);
+
+ List<AtlasObjectId> juliusSubordinateIds = toAtlasObjectIds(julius.getRelationshipAttribute("subordinates"));
+ assertNull(juliusSubordinateIds);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_OneToMany() throws Exception {
+ AtlasObjectId maxId = employeeNameIdMap.get("Max");
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId janeId = employeeNameIdMap.get("Jane");
+
+ // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
+ // This should also update Julius to add Max to the inverse Manager.subordinates reference.
+ AtlasEntity maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+ maxEntityForUpdate.setRelationshipAttribute("manager", juliusId);
+
+ AtlasEntityType employeeType = typeRegistry.getEntityTypeByName(EMPLOYEE_TYPE);
+ Map<String, Object> uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
+ EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+ List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+ assertEquals(partialUpdatedEntities.size(), 3);
+ // 3 entities should have been updated:
+ // * Max to change the Employee.manager reference
+ // * Julius to add Max to Manager.subordinates
+ // * Jane to remove Max from Manager.subordinates
+
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeId.getGuid()));
+
+ // Max's manager updated as Julius
+ AtlasEntity maxEntity = updatedEntities.getEntity(maxId.getGuid());
+ verifyRelationshipAttributeValue(maxEntity, "manager", juliusId.getGuid());
+
+ // Max added to the subordinate list of Julius
+ AtlasEntity juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+ verifyRelationshipAttributeList(juliusEntity, "subordinates", ImmutableList.of(maxId));
+
+ // Max removed from the subordinate list of Julius
+ AtlasEntity janeEntity = updatedEntities.getEntity(janeId.getGuid());
+
+ // Jane's subordinates list includes John and Max for soft delete
+ // Jane's subordinates list includes only John for hard delete
+ verifyRelationshipAttributeUpdate_NonComposite_OneToMany(janeEntity);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_ManyToOne() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, "a3_name");
+
+ AtlasEntity b = new AtlasEntity("B");
+ b.setAttribute(NAME, "b_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(a3);
+ entitiesWithExtInfo.addEntity(b);
+ entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity bPartialUpdate = new AtlasEntity("B");
+ bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ init();
+ EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(bPartialUpdate));
+ // Verify 3 entities were updated:
+ // * set b.manyA reference to a1 and a2
+ // * set inverse a1.oneB reference to b
+ // * set inverse a2.oneB reference to b
+ assertEquals(response.getPartialUpdatedEntities().size(), 3);
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+ AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeValue(a1Entity, "oneB", b.getGuid());
+
+ AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeValue(a2Entity, "oneB", b.getGuid());
+
+ AtlasEntity bEntity = updatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeList(bEntity, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+
+ bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a3)));
+ init();
+ response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(bPartialUpdate));
+ // Verify 4 entities were updated:
+ // * set b.manyA reference to a3
+ // * set inverse a3.oneB reference to b
+ // * disconnect inverse a1.oneB reference to b
+ // * disconnect inverse a2.oneB reference to b
+ assertEquals(response.getPartialUpdatedEntities().size(), 4);
+ init();
+
+ updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
+ a1Entity = updatedEntities.getEntity(a1.getGuid());
+ a2Entity = updatedEntities.getEntity(a2.getGuid());
+ bEntity = updatedEntities.getEntity(b.getGuid());
+
+ AtlasEntity a3Entity = updatedEntities.getEntity(a3.getGuid());
+ verifyRelationshipAttributeValue(a3Entity, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(a1Entity, a2Entity, a3Entity, bEntity);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_OneToOne() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity b = new AtlasEntity("B");
+ b.setAttribute(NAME, "b_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(b);
+
+ EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity partialUpdateB = new AtlasEntity("B");
+ partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a1));
+
+ init();
+ AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+
+ response = entityStore.updateByUniqueAttributes(bType, Collections.singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+ List<AtlasEntityHeader> partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+ // Verify 2 entities were updated:
+ // * set b.a reference to a1
+ // * set inverse a1.b reference to b
+ assertEquals(partialUpdatedEntitiesHeader.size(), 2);
+ AtlasEntitiesWithExtInfo partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
+
+ AtlasEntity a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeValue(a1Entity, "b", b.getGuid());
+
+ AtlasEntity bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeValue(bEntity, "a", a1.getGuid());
+
+ init();
+
+ // Update b.a to reference a2.
+ partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a2));
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+ partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+ // Verify 3 entities were updated:
+ // * set b.a reference to a2
+ // * set a2.b reference to b
+ // * disconnect a1.b reference
+ assertEquals(partialUpdatedEntitiesHeader.size(), 3);
+ partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+ bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeValue(bEntity, "a", a2.getGuid());
+
+ AtlasEntity a2Entity = partialUpdatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeValue(a2Entity, "b", b.getGuid());
+
+ a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeUpdate_NonComposite_OneToOne(a1Entity, bEntity);
+ }
+
@Test
- public void testDbTableRelationship() throws Exception {
- // Add tests - in progress
+ public void testRelationshipAttributeUpdate_NonComposite_ManyToMany() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, "a3_name");
+
+ AtlasEntity b1 = new AtlasEntity("B");
+ b1.setAttribute(NAME, "b1_name");
+
+ AtlasEntity b2 = new AtlasEntity("B");
+ b2.setAttribute(NAME, "b2_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(a3);
+ entitiesWithExtInfo.addEntity(b1);
+ entitiesWithExtInfo.addEntity(b2);
+ entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity b1PartialUpdate = new AtlasEntity("B");
+ b1PartialUpdate.setRelationshipAttribute("manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ init();
+ EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b1.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(b1PartialUpdate));
+
+ List<AtlasEntityHeader> updatedEntityHeaders = response.getPartialUpdatedEntities();
+ assertEquals(updatedEntityHeaders.size(), 3);
+
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
+
+ AtlasEntity b1Entity = updatedEntities.getEntity(b1.getGuid());
+ verifyRelationshipAttributeList(b1Entity, "manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeList(a1Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+
+ AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeList(a2Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+ }
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity entity) throws Exception;
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
+
+ private static void assertObjectIdsContains(List<AtlasObjectId> objectIds, AtlasObjectId objectId) {
+ assertTrue(CollectionUtils.isNotEmpty(objectIds));
+ assertTrue(objectIds.contains(objectId));
+ }
+
+ private static void assertObjectIdEquals(AtlasObjectId objId1, AtlasObjectId objId2) {
+ assertTrue(objId1.equals(objId2));
+ }
+
+ private static List<AtlasObjectId> toAtlasObjectIds(Object objectIds) {
+ if (objectIds instanceof List) {
+ return (List<AtlasObjectId>) objectIds;
+ }
+
+ return null;
+ }
+
+ private static AtlasObjectId toAtlasObjectId(Object objectId) {
+ if (objectId instanceof AtlasObjectId) {
+ return (AtlasObjectId) objectId;
+ }
+
+ return null;
+ }
+
+ private AtlasEntity getEntityFromStore(String guid) throws AtlasBaseException {
+ AtlasEntityWithExtInfo entity = guid != null ? entityStore.getById(guid) : null;
+
+ return entity != null ? entity.getEntity() : null;
+ }
+
+ protected static void verifyRelationshipAttributeList(AtlasEntity entity, String relationshipAttrName, List<AtlasObjectId> expectedValues) {
+ Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+ assertTrue(refValue instanceof List);
+
+ List<AtlasObjectId> refList = (List<AtlasObjectId>) refValue;
+ assertEquals(refList.size(), expectedValues.size());
+
+ if (expectedValues.size() > 0) {
+ assertTrue(refList.containsAll(expectedValues));
+ }
+ }
+
+ protected static void verifyRelationshipAttributeValue(AtlasEntity entity, String relationshipAttrName, String expectedGuid) {
+ Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+ if (expectedGuid == null) {
+ assertNull(refValue);
+ }
+ else {
+ assertTrue(refValue instanceof AtlasObjectId);
+ AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
+ assertEquals(referencedObjectId.getGuid(), expectedGuid);
+ }
}
-}
+}
\ No newline at end of file