Commit 2341d58a by Madhan Neethiraj

ATLAS-3035: updated entity-get/delete to retrieve/delete soft-ref entities

parent 4985b9f2
...@@ -19,24 +19,30 @@ package org.apache.atlas.utils; ...@@ -19,24 +19,30 @@ package org.apache.atlas.utils;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.type.AtlasArrayType; import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasMapType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collection; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
public class AtlasEntityUtil { public class AtlasEntityUtil {
private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityUtil.class); private static final Logger LOG = LoggerFactory.getLogger(AtlasEntityUtil.class);
private static final String SOFT_REFERENCE_FORMAT_SEPERATOR = ":";
private static final String SOFT_REF_FORMAT = "%s" + SOFT_REFERENCE_FORMAT_SEPERATOR + "%s";
private static final int SOFT_REFERENCE_FORMAT_INDEX_TYPE_NAME = 0;
private static final int SOFT_REFERENCE_FORMAT_INDEX_GUID = 1;
public static boolean hasAnyAttributeUpdate(AtlasEntityType entityType, AtlasEntity currEntity, AtlasEntity newEntity) { public static boolean hasAnyAttributeUpdate(AtlasEntityType entityType, AtlasEntity currEntity, AtlasEntity newEntity) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("==> hasAnyAttributeUpdate(guid={}, typeName={})", currEntity.getGuid(), currEntity.getTypeName()); LOG.debug("==> hasAnyAttributeUpdate(guid={}, typeName={})", currEntity.getGuid(), currEntity.getTypeName());
...@@ -68,4 +74,85 @@ public class AtlasEntityUtil { ...@@ -68,4 +74,85 @@ public class AtlasEntityUtil {
return ret; return ret;
} }
public static String formatSoftRefValue(String typeName, String guid) {
return String.format(SOFT_REF_FORMAT, typeName, guid);
}
public static String formatSoftRefValue(AtlasObjectId objectId) {
return formatSoftRefValue(objectId.getTypeName(), objectId.getGuid());
}
public static List<String> formatSoftRefValue(List<AtlasObjectId> objIds) {
List<String> ret = new ArrayList<>();
for (AtlasObjectId objId : objIds) {
ret.add(formatSoftRefValue(objId));
}
return ret;
}
public static Map<String, String> formatSoftRefValue(Map<String, AtlasObjectId> objIdMap) {
Map<String, String> ret = new HashMap<>();
for (Map.Entry<String, AtlasObjectId> entry : objIdMap.entrySet()) {
ret.put(entry.getKey(), formatSoftRefValue(entry.getValue()));
}
return ret;
}
public static AtlasObjectId parseSoftRefValue(String softRefValue) {
AtlasObjectId ret = null;
if (StringUtils.isNotEmpty(softRefValue)) {
String[] objectIdParts = StringUtils.split(softRefValue, SOFT_REFERENCE_FORMAT_SEPERATOR);
if(objectIdParts.length >= 2) {
ret = new AtlasObjectId(objectIdParts[SOFT_REFERENCE_FORMAT_INDEX_GUID], objectIdParts[SOFT_REFERENCE_FORMAT_INDEX_TYPE_NAME]);
} else {
LOG.warn("Invalid soft-ref value: {}", softRefValue);
}
}
return ret;
}
public static List<AtlasObjectId> parseSoftRefValue(List<String> softRefValue) {
List<AtlasObjectId> ret = null;
if (CollectionUtils.isNotEmpty(softRefValue)) {
ret = new ArrayList<>();
for (String elemValue : softRefValue) {
AtlasObjectId objId = parseSoftRefValue(elemValue);
if (objId != null) {
ret.add(objId);
}
}
}
return ret;
}
public static Map<String, AtlasObjectId> parseSoftRefValue(Map<String, String> softRefValue) {
Map<String, AtlasObjectId> ret = null;
if (MapUtils.isNotEmpty(softRefValue)) {
ret = new HashMap<>();
for (Map.Entry<String, String> entry : softRefValue.entrySet()) {
AtlasObjectId objId = parseSoftRefValue(entry.getValue());
if (objId != null) {
ret.put(entry.getKey(), objId);
}
}
}
return ret;
}
} }
...@@ -45,6 +45,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute; ...@@ -45,6 +45,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection; import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdgeDirection;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.utils.AtlasEntityUtil;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
...@@ -210,14 +211,23 @@ public abstract class DeleteHandlerV1 { ...@@ -210,14 +211,23 @@ public abstract class DeleteHandlerV1 {
TypeCategory typeCategory = attrType.getTypeCategory(); TypeCategory typeCategory = attrType.getTypeCategory();
if (typeCategory == OBJECT_ID_TYPE) { if (typeCategory == OBJECT_ID_TYPE) {
AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel); if (attributeInfo.getAttributeDef().isSoftReferenced()) {
String softRefVal = vertex.getProperty(attributeInfo.getVertexPropertyName(), String.class);
AtlasObjectId refObjId = AtlasEntityUtil.parseSoftRefValue(softRefVal);
AtlasVertex refVertex = refObjId != null ? AtlasGraphUtilsV2.findByGuid(refObjId.getGuid()) : null;
if (edge == null || getState(edge) == DELETED) { if (refVertex != null) {
continue; vertices.push(refVertex);
} }
} else {
AtlasEdge edge = graphHelper.getEdgeForLabel(vertex, edgeLabel);
vertices.push(edge.getInVertex()); if (edge == null || getState(edge) == DELETED) {
continue;
}
vertices.push(edge.getInVertex());
}
} else if (typeCategory == ARRAY || typeCategory == MAP) { } else if (typeCategory == ARRAY || typeCategory == MAP) {
TypeCategory elementType = null; TypeCategory elementType = null;
...@@ -231,15 +241,46 @@ public abstract class DeleteHandlerV1 { ...@@ -231,15 +241,46 @@ public abstract class DeleteHandlerV1 {
continue; continue;
} }
List<AtlasEdge> edges = getCollectionElementsUsingRelationship(vertex, attributeInfo); if (attributeInfo.getAttributeDef().isSoftReferenced()) {
if (typeCategory == ARRAY) {
List softRefVal = vertex.getListProperty(attributeInfo.getVertexPropertyName(), List.class);
List<AtlasObjectId> refObjIds = AtlasEntityUtil.parseSoftRefValue(softRefVal);
if (CollectionUtils.isNotEmpty(refObjIds)) {
for (AtlasObjectId refObjId : refObjIds) {
AtlasVertex refVertex = AtlasGraphUtilsV2.findByGuid(refObjId.getGuid());
if (refVertex != null) {
vertices.push(refVertex);
}
}
}
} else if (typeCategory == MAP) {
Map softRefVal = vertex.getProperty(attributeInfo.getVertexPropertyName(), Map.class);
Map<String, AtlasObjectId> refObjIds = AtlasEntityUtil.parseSoftRefValue(softRefVal);
if (MapUtils.isNotEmpty(refObjIds)) {
for (AtlasObjectId refObjId : refObjIds.values()) {
AtlasVertex refVertex = AtlasGraphUtilsV2.findByGuid(refObjId.getGuid());
if (CollectionUtils.isNotEmpty(edges)) { if (refVertex != null) {
for (AtlasEdge edge : edges) { vertices.push(refVertex);
if (edge == null || getState(edge) == DELETED) { }
continue; }
} }
}
} else {
List<AtlasEdge> edges = getCollectionElementsUsingRelationship(vertex, attributeInfo);
vertices.push(edge.getInVertex()); if (CollectionUtils.isNotEmpty(edges)) {
for (AtlasEdge edge : edges) {
if (edge == null || getState(edge) == DELETED) {
continue;
}
vertices.push(edge.getInVertex());
}
} }
} }
} }
......
...@@ -54,6 +54,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdg ...@@ -54,6 +54,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute.AtlasRelationshipEdg
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.type.AtlasTypeUtil;
import org.apache.atlas.utils.AtlasEntityUtil;
import org.apache.atlas.utils.AtlasJson; import org.apache.atlas.utils.AtlasJson;
import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder; import org.apache.atlas.utils.AtlasPerfMetrics.MetricRecorder;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
...@@ -496,28 +497,27 @@ public class EntityGraphMapper { ...@@ -496,28 +497,27 @@ public class EntityGraphMapper {
} }
} }
private Object mapSoftRefValue(AttributeMutationContext ctx, EntityMutationContext context) { private String mapSoftRefValue(AttributeMutationContext ctx, EntityMutationContext context) {
if(ctx.getValue() != null && !(ctx.getValue() instanceof AtlasObjectId)) { String ret = null;
LOG.warn("mapSoftRefValue: Was expecting AtlasObjectId, but found: {}", ctx.getValue().getClass());
return null;
}
String softRefValue = null; if (ctx.getValue() instanceof AtlasObjectId) {
if(ctx.getValue() != null) {
AtlasObjectId objectId = (AtlasObjectId) ctx.getValue(); AtlasObjectId objectId = (AtlasObjectId) ctx.getValue();
String resolvedGuid = AtlasTypeUtil.isUnAssignedGuid(objectId.getGuid()) String typeName = objectId.getTypeName();
? context.getGuidAssignments().get(objectId.getGuid()) String guid = AtlasTypeUtil.isUnAssignedGuid(objectId.getGuid()) ? context.getGuidAssignments().get(objectId.getGuid()) : objectId.getGuid();
: objectId.getGuid();
softRefValue = String.format(SOFT_REF_FORMAT, objectId.getTypeName(), resolvedGuid); ret = AtlasEntityUtil.formatSoftRefValue(typeName, guid);
} else {
if (ctx.getValue() != null) {
LOG.warn("mapSoftRefValue: Was expecting AtlasObjectId, but found: {}", ctx.getValue().getClass());
}
} }
return softRefValue; return ret;
} }
private Object mapSoftRefValueWithUpdate(AttributeMutationContext ctx, EntityMutationContext context) { private Object mapSoftRefValueWithUpdate(AttributeMutationContext ctx, EntityMutationContext context) {
String softRefValue = mapSoftRefValue(ctx, context);
String softRefValue = (String) mapSoftRefValue(ctx, context);
AtlasGraphUtilsV2.setProperty(ctx.getReferringVertex(), ctx.getVertexProperty(), softRefValue); AtlasGraphUtilsV2.setProperty(ctx.getReferringVertex(), ctx.getVertexProperty(), softRefValue);
return softRefValue; return softRefValue;
......
...@@ -52,6 +52,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute; ...@@ -52,6 +52,7 @@ import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.type.AtlasTypeUtil; import org.apache.atlas.type.AtlasTypeUtil;
import org.apache.atlas.utils.AtlasEntityUtil;
import org.apache.atlas.utils.AtlasJson; import org.apache.atlas.utils.AtlasJson;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils; import org.apache.commons.collections.MapUtils;
...@@ -71,6 +72,7 @@ import java.util.HashSet; ...@@ -71,6 +72,7 @@ import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -106,9 +108,6 @@ public class EntityGraphRetriever { ...@@ -106,9 +108,6 @@ public class EntityGraphRetriever {
public static final String DESCRIPTION = "description"; public static final String DESCRIPTION = "description";
public static final String OWNER = "owner"; public static final String OWNER = "owner";
public static final String CREATE_TIME = "createTime"; public static final String CREATE_TIME = "createTime";
private static final String SOFT_REFERENCE_FORMAT_SEPERATOR = ":";
private static final int SOFT_REFERENCE_FORMAT_INDEX_TYPE_NAME = 0;
private static final int SOFT_REFERENCE_FORMAT_INDEX_GUID = 1;
public static final String QUALIFIED_NAME = "qualifiedName"; public static final String QUALIFIED_NAME = "qualifiedName";
private static final TypeReference<List<TimeBoundary>> TIME_BOUNDARIES_LIST_TYPE = new TypeReference<List<TimeBoundary>>() {}; private static final TypeReference<List<TimeBoundary>> TIME_BOUNDARIES_LIST_TYPE = new TypeReference<List<TimeBoundary>>() {};
...@@ -704,21 +703,21 @@ public class EntityGraphRetriever { ...@@ -704,21 +703,21 @@ public class EntityGraphRetriever {
break; break;
case OBJECT_ID_TYPE: case OBJECT_ID_TYPE:
if(attribute.getAttributeDef().isSoftReferenced()) { if(attribute.getAttributeDef().isSoftReferenced()) {
ret = mapVertexToObjectIdForSoftRef(entityVertex, attribute.getVertexPropertyName()); ret = mapVertexToObjectIdForSoftRef(entityVertex, attribute, entityExtInfo, isMinExtInfo);
} else { } else {
ret = mapVertexToObjectId(entityVertex, edgeLabel, null, entityExtInfo, isOwnedAttribute, edgeDirection, isMinExtInfo); ret = mapVertexToObjectId(entityVertex, edgeLabel, null, entityExtInfo, isOwnedAttribute, edgeDirection, isMinExtInfo);
} }
break; break;
case ARRAY: case ARRAY:
if(attribute.getAttributeDef().isSoftReferenced()) { if(attribute.getAttributeDef().isSoftReferenced()) {
ret = mapVertexToArrayForSoftRef(entityVertex, attribute.getVertexPropertyName()); ret = mapVertexToArrayForSoftRef(entityVertex, attribute, entityExtInfo, isMinExtInfo);
} else { } else {
ret = mapVertexToArray(entityVertex, entityExtInfo, isOwnedAttribute, attribute, isMinExtInfo); ret = mapVertexToArray(entityVertex, entityExtInfo, isOwnedAttribute, attribute, isMinExtInfo);
} }
break; break;
case MAP: case MAP:
if(attribute.getAttributeDef().isSoftReferenced()) { if(attribute.getAttributeDef().isSoftReferenced()) {
ret = mapVertexToMapForSoftRef(entityVertex, attribute.getVertexPropertyName()); ret = mapVertexToMapForSoftRef(entityVertex, attribute, entityExtInfo, isMinExtInfo);
} else { } else {
ret = mapVertexToMap(entityVertex, entityExtInfo, isOwnedAttribute, attribute, isMinExtInfo); ret = mapVertexToMap(entityVertex, entityExtInfo, isOwnedAttribute, attribute, isMinExtInfo);
} }
...@@ -731,74 +730,78 @@ public class EntityGraphRetriever { ...@@ -731,74 +730,78 @@ public class EntityGraphRetriever {
return ret; return ret;
} }
private Map<String, AtlasObjectId> mapVertexToMapForSoftRef(AtlasVertex entityVertex, String propertyName) { private Map<String, AtlasObjectId> mapVertexToMapForSoftRef(AtlasVertex entityVertex, AtlasAttribute attribute, AtlasEntityExtInfo entityExtInfo, final boolean isMinExtInfo) {
Map map = entityVertex.getProperty(propertyName, Map.class); Map<String, AtlasObjectId> ret = null;
if (MapUtils.isEmpty(map)) { Map softRefVal = entityVertex.getProperty(attribute.getVertexPropertyName(), Map.class);
return null;
}
if (LOG.isDebugEnabled()) { if (MapUtils.isNotEmpty(softRefVal)) {
LOG.debug("Mapping map attribute {} for vertex {}", propertyName, entityVertex); ret = new HashMap<>();
}
Map ret = new HashMap(); for (Object mapKey : softRefVal.keySet()) {
for (Object mapKey : map.keySet()) { AtlasObjectId objectId = getAtlasObjectIdFromSoftRefFormat(Objects.toString(softRefVal.get(mapKey)), attribute, entityExtInfo, isMinExtInfo);
String softRefRaw = (String) map.get(mapKey);
AtlasObjectId mapValue = getAtlasObjectIdFromSoftRefFormat(softRefRaw); if (objectId != null) {
if (mapValue != null) { ret.put(Objects.toString(mapKey), objectId);
ret.put(mapKey, mapValue); }
} }
} }
return ret; return ret;
} }
private List<AtlasObjectId> mapVertexToArrayForSoftRef(AtlasVertex entityVertex, String propertyName) { private List<AtlasObjectId> mapVertexToArrayForSoftRef(AtlasVertex entityVertex, AtlasAttribute attribute, AtlasEntityExtInfo entityExtInfo, final boolean isMinExtInfo) {
List rawValue = entityVertex.getListProperty(propertyName, List.class); List<AtlasObjectId> ret = null;
if (CollectionUtils.isEmpty(rawValue)) { List softRefVal = entityVertex.getListProperty(attribute.getVertexPropertyName(), List.class);
return null;
}
List list = (List) rawValue; if (CollectionUtils.isNotEmpty(softRefVal)) {
List<AtlasObjectId> objectIds = new ArrayList<>(); ret = new ArrayList<>();
for (Object o : list) {
if (!(o instanceof String)) {
continue;
}
AtlasObjectId objectId = getAtlasObjectIdFromSoftRefFormat((String) o); for (Object o : softRefVal) {
if(objectId == null) { AtlasObjectId objectId = getAtlasObjectIdFromSoftRefFormat(Objects.toString(o), attribute, entityExtInfo, isMinExtInfo);
continue;
}
objectIds.add(objectId); if(objectId != null) {
ret.add(objectId);
}
}
} }
return objectIds; return ret;
} }
private AtlasObjectId mapVertexToObjectIdForSoftRef(AtlasVertex entityVertex, String vertexPropertyName) { private AtlasObjectId mapVertexToObjectIdForSoftRef(AtlasVertex entityVertex, AtlasAttribute attribute, AtlasEntityExtInfo entityExtInfo, final boolean isMinExtInfo) {
String rawValue = AtlasGraphUtilsV2.getEncodedProperty(entityVertex, vertexPropertyName, String.class); String softRefVal = AtlasGraphUtilsV2.getEncodedProperty(entityVertex, attribute.getVertexPropertyName(), String.class);
if(StringUtils.isEmpty(rawValue)) {
return null;
}
return getAtlasObjectIdFromSoftRefFormat(rawValue); return StringUtils.isNotEmpty(softRefVal) ? getAtlasObjectIdFromSoftRefFormat(softRefVal, attribute, entityExtInfo, isMinExtInfo) : null;
} }
private AtlasObjectId getAtlasObjectIdFromSoftRefFormat(String rawValue) { private AtlasObjectId getAtlasObjectIdFromSoftRefFormat(String softRefVal, AtlasAttribute attribute, AtlasEntityExtInfo entityExtInfo, final boolean isMinExtInfo) {
if(StringUtils.isEmpty(rawValue)) { AtlasObjectId ret = AtlasEntityUtil.parseSoftRefValue(softRefVal);
return null;
}
String[] objectIdParts = StringUtils.split(rawValue, SOFT_REFERENCE_FORMAT_SEPERATOR); if(ret != null) {
if(objectIdParts.length < 2) { if (entityExtInfo != null && attribute.isOwnedRef()) {
LOG.warn("Expecting value to be formatted for softRef. Instead found: {}", rawValue); try {
return null; AtlasVertex referenceVertex = getEntityVertex(ret.getGuid());
if (referenceVertex != null) {
final AtlasEntity entity;
if (isMinExtInfo) {
entity = mapVertexToAtlasEntityMin(referenceVertex, entityExtInfo);
} else {
entity = mapVertexToAtlasEntity(referenceVertex, entityExtInfo);
}
if (entity != null) {
ret = toAtlasObjectId(entity);
}
}
} catch (AtlasBaseException excp) {
LOG.info("failed to retrieve soft-referenced entity(typeName={}, guid={}); errorCode={}. Ignoring", ret.getTypeName(), ret.getGuid(), excp.getAtlasErrorCode());
}
}
} }
return new AtlasObjectId(objectIdParts[SOFT_REFERENCE_FORMAT_INDEX_GUID], return ret;
objectIdParts[SOFT_REFERENCE_FORMAT_INDEX_TYPE_NAME]);
} }
private Map<String, Object> mapVertexToMap(AtlasVertex entityVertex, AtlasEntityExtInfo entityExtInfo, private Map<String, Object> mapVertexToMap(AtlasVertex entityVertex, AtlasEntityExtInfo entityExtInfo,
...@@ -986,7 +989,7 @@ public class EntityGraphRetriever { ...@@ -986,7 +989,7 @@ public class EntityGraphRetriever {
ret = AtlasTypeUtil.getAtlasObjectId(entity); ret = AtlasTypeUtil.getAtlasObjectId(entity);
} }
} else { } else {
ret = new AtlasObjectId(getGuid(referenceVertex), getTypeName(referenceVertex)); ret = toAtlasObjectId(referenceVertex);
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment