Commit ce20d6f5 by Madhan Neethiraj

ATLAS-1544: implementation of REST endpoints for entity create/update/bulk-get

parent 414b7bbc
...@@ -64,6 +64,7 @@ public enum AtlasErrorCode { ...@@ -64,6 +64,7 @@ public enum AtlasErrorCode {
UNRESOLVED_REFERENCES_FOUND(400, "ATLAS40033E", "Unresolved references: byId={0}; byUniqueAttributes={1}"), UNRESOLVED_REFERENCES_FOUND(400, "ATLAS40033E", "Unresolved references: byId={0}; byUniqueAttributes={1}"),
UNKNOWN_ATTRIBUTE(400, "ATLAS40034E", "Attribute {0} not found for type {1}"), UNKNOWN_ATTRIBUTE(400, "ATLAS40034E", "Attribute {0} not found for type {1}"),
SYSTEM_TYPE(400, "ATLAS40035E", "{0} is a System-type"), SYSTEM_TYPE(400, "ATLAS40035E", "{0} is a System-type"),
INVALID_STRUCT_VALUE(400, "ATLAS40036E", "not a valid struct value {0}"),
// All Not found enums go here // All Not found enums go here
TYPE_NAME_NOT_FOUND(404, "ATLAS4041E", "Given typename {0} was invalid"), TYPE_NAME_NOT_FOUND(404, "ATLAS4041E", "Given typename {0} was invalid"),
...@@ -74,8 +75,8 @@ public enum AtlasErrorCode { ...@@ -74,8 +75,8 @@ public enum AtlasErrorCode {
INSTANCE_LINEAGE_QUERY_FAILED(404, "ATLAS4047E", "Instance lineage query failed {0}"), INSTANCE_LINEAGE_QUERY_FAILED(404, "ATLAS4047E", "Instance lineage query failed {0}"),
DISCOVERY_QUERY_FAILED(404, "ATLAS4048E", "Discovery query failed {0}"), DISCOVERY_QUERY_FAILED(404, "ATLAS4048E", "Discovery query failed {0}"),
INSTANCE_CRUD_INVALID_PARAMS(404, "ATLAS4049E", "Invalid instance creation/updation parameters passed : {0}"), INSTANCE_CRUD_INVALID_PARAMS(404, "ATLAS4049E", "Invalid instance creation/updation parameters passed : {0}"),
INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(404, "ATLAS40410E", "Instance {0} with unique attribute {1}={2} does not exist"), INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(404, "ATLAS40410E", "Instance {0} with unique attribute {1} does not exist"),
REFERENCED_ENTITY_NOT_FOUND(404, "ATLAS40411E", "Referenced entity {0} is not found"),
// All data conflict errors go here // All data conflict errors go here
TYPE_ALREADY_EXISTS(409, "ATLAS4091E", "Given type {0} already exists"), TYPE_ALREADY_EXISTS(409, "ATLAS4091E", "Given type {0} already exists"),
......
...@@ -34,6 +34,7 @@ import javax.xml.bind.annotation.XmlRootElement; ...@@ -34,6 +34,7 @@ import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.bind.annotation.XmlSeeAlso;
import java.io.Serializable; import java.io.Serializable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
...@@ -87,16 +88,16 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -87,16 +88,16 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
this(entityDef != null ? entityDef.getName() : null, null); this(entityDef != null ? entityDef.getName() : null, null);
} }
public AtlasEntity(String typeName, String attrName, Object attrValue) {
super(typeName, attrName, attrValue);
init();
}
public AtlasEntity(String typeName, Map<String, Object> attributes) { public AtlasEntity(String typeName, Map<String, Object> attributes) {
super(typeName, attributes); super(typeName, attributes);
setGuid(nextInternalId()); init();
setStatus(null);
setCreatedBy(null);
setUpdatedBy(null);
setCreateTime(null);
setUpdateTime(null);
setClassifications(null);
} }
public AtlasEntity(AtlasEntity other) { public AtlasEntity(AtlasEntity other) {
...@@ -186,13 +187,15 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -186,13 +187,15 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
@JsonIgnore @JsonIgnore
public static boolean isAssigned(String guid) { public static boolean isAssigned(String guid) {
try { if (guid != null) {
UUID.fromString(guid); try {
} catch (IllegalArgumentException e) { UUID.fromString(guid);
return false; return true;
} catch (IllegalArgumentException e) {
// ignore
}
} }
return false;
return true;
} }
@JsonIgnore @JsonIgnore
...@@ -200,13 +203,23 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -200,13 +203,23 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
return guid != null && guid.length() > 0 && guid.charAt(0) == '-'; return guid != null && guid.length() > 0 && guid.charAt(0) == '-';
} }
private void init() {
setGuid(nextInternalId());
setStatus(null);
setCreatedBy(null);
setUpdatedBy(null);
setCreateTime(null);
setUpdateTime(null);
setClassifications(null);
}
private static String nextInternalId() { private static String nextInternalId() {
return "-" + Long.toString(s_nextId.getAndIncrement()); return "-" + Long.toString(s_nextId.getAndIncrement());
} }
@JsonIgnore @JsonIgnore
public AtlasObjectId getAtlasObjectId() { public AtlasObjectId getAtlasObjectId() {
return new AtlasObjectId(getTypeName(), getGuid()); return new AtlasObjectId(getGuid(), getTypeName());
} }
@Override @Override
...@@ -279,6 +292,10 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -279,6 +292,10 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
setReferredEntities(null); setReferredEntities(null);
} }
public AtlasEntityExtInfo(AtlasEntity referredEntity) {
addReferredEntity(referredEntity);
}
public AtlasEntityExtInfo(Map<String, AtlasEntity> referredEntities) { public AtlasEntityExtInfo(Map<String, AtlasEntity> referredEntities) {
setReferredEntities(referredEntities); setReferredEntities(referredEntities);
} }
...@@ -294,6 +311,11 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -294,6 +311,11 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
public void setReferredEntities(Map<String, AtlasEntity> referredEntities) { this.referredEntities = referredEntities; } public void setReferredEntities(Map<String, AtlasEntity> referredEntities) { this.referredEntities = referredEntities; }
@JsonIgnore @JsonIgnore
public final void addReferredEntity(AtlasEntity entity) {
addReferredEntity(entity.getGuid(), entity);
}
@JsonIgnore
public final void addReferredEntity(String guid, AtlasEntity entity) { public final void addReferredEntity(String guid, AtlasEntity entity) {
Map<String, AtlasEntity> r = this.referredEntities; Map<String, AtlasEntity> r = this.referredEntities;
...@@ -494,10 +516,17 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -494,10 +516,17 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
this(null, null); this(null, null);
} }
public AtlasEntitiesWithExtInfo(AtlasEntity entity) { this(Arrays.asList(entity), null);
}
public AtlasEntitiesWithExtInfo(List<AtlasEntity> entities) { public AtlasEntitiesWithExtInfo(List<AtlasEntity> entities) {
this(entities, null); this(entities, null);
} }
public AtlasEntitiesWithExtInfo(AtlasEntityWithExtInfo entity) {
this(Arrays.asList(entity.getEntity()), entity);
}
public AtlasEntitiesWithExtInfo(List<AtlasEntity> entities, AtlasEntityExtInfo extInfo) { public AtlasEntitiesWithExtInfo(List<AtlasEntity> entities, AtlasEntityExtInfo extInfo) {
super(extInfo); super(extInfo);
......
...@@ -20,6 +20,7 @@ package org.apache.atlas.model.instance; ...@@ -20,6 +20,7 @@ package org.apache.atlas.model.instance;
import java.io.Serializable; import java.io.Serializable;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.HashMap;
import java.util.Objects; import java.util.Objects;
import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessType;
...@@ -51,88 +52,83 @@ import org.codehaus.jackson.map.annotate.JsonSerialize; ...@@ -51,88 +52,83 @@ import org.codehaus.jackson.map.annotate.JsonSerialize;
public class AtlasObjectId implements Serializable { public class AtlasObjectId implements Serializable {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final String KEY_TYPENAME = "typeName";
public static final String KEY_GUID = "guid"; public static final String KEY_GUID = "guid";
public static final String KEY_TYPENAME = "typeName";
public static final String KEY_UNIQUE_ATTRIBUTES = "uniqueAttributes"; public static final String KEY_UNIQUE_ATTRIBUTES = "uniqueAttributes";
private String typeName;
private String guid; private String guid;
private String typeName;
private Map<String, Object> uniqueAttributes; private Map<String, Object> uniqueAttributes;
@JsonIgnore
private boolean isAssignedGuid = false;
@JsonIgnore
private boolean isUnAssignedGuid = false;
public AtlasObjectId() { public AtlasObjectId() {
this(null, null, null); this(null, null, (Map<String, Object>)null);
} }
public AtlasObjectId(String typeName) { public AtlasObjectId(String guid) {
this(typeName, null, null); this(guid, null, (Map<String, Object>)null);
} }
public AtlasObjectId(String typeName, String guid) { public AtlasObjectId(String guid, String typeName) {
this(typeName, guid, null); this(guid, typeName, (Map<String, Object>)null);
} }
public AtlasObjectId(String typeName, Map<String, Object> uniqueAttributes) { public AtlasObjectId(String typeName, Map<String, Object> uniqueAttributes) {
this(typeName, null, uniqueAttributes); this(null, typeName, uniqueAttributes);
} }
public AtlasObjectId(String typeName, String guid, Map<String, Object> uniqueAttributes) { public AtlasObjectId(String typeName, final String attrName, final Object attrValue) {
setTypeName(typeName); this(null, typeName, new HashMap<String, Object>() {{ put(attrName, attrValue); }});
}
public AtlasObjectId(String guid, String typeName, Map<String, Object> uniqueAttributes) {
setGuid(guid); setGuid(guid);
setTypeName(typeName);
setUniqueAttributes(uniqueAttributes); setUniqueAttributes(uniqueAttributes);
} }
public AtlasObjectId(AtlasObjectId other) { public AtlasObjectId(AtlasObjectId other) {
if (other != null) { if (other != null) {
setTypeName(other.getTypeName());
setGuid(other.getGuid()); setGuid(other.getGuid());
setTypeName(other.getTypeName());
setUniqueAttributes(other.getUniqueAttributes()); setUniqueAttributes(other.getUniqueAttributes());
} }
} }
public AtlasObjectId(Map objIdMap) { public AtlasObjectId(Map objIdMap) {
if (objIdMap != null) { if (objIdMap != null) {
Object t = objIdMap.get(KEY_TYPENAME);
Object g = objIdMap.get(KEY_GUID); Object g = objIdMap.get(KEY_GUID);
Object t = objIdMap.get(KEY_TYPENAME);
Object u = objIdMap.get(KEY_UNIQUE_ATTRIBUTES); Object u = objIdMap.get(KEY_UNIQUE_ATTRIBUTES);
if (t != null) {
setTypeName(t.toString());
}
if (g != null) { if (g != null) {
setGuid(g.toString()); setGuid(g.toString());
} }
if (t != null) {
setTypeName(t.toString());
}
if (u != null && u instanceof Map) { if (u != null && u instanceof Map) {
setUniqueAttributes((Map)u); setUniqueAttributes((Map)u);
} }
} }
} }
public String getTypeName() {
return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
}
public String getGuid() { public String getGuid() {
return guid; return guid;
} }
public void setGuid(String guid) { public void setGuid(String guid) {
this.guid = guid; this.guid = guid;
if ( guid != null) { }
this.isAssignedGuid = AtlasEntity.isAssigned(guid);
this.isUnAssignedGuid = AtlasEntity.isUnAssigned(guid); public String getTypeName() {
} return typeName;
}
public void setTypeName(String typeName) {
this.typeName = typeName;
} }
public Map<String, Object> getUniqueAttributes() { public Map<String, Object> getUniqueAttributes() {
...@@ -144,28 +140,29 @@ public class AtlasObjectId implements Serializable { ...@@ -144,28 +140,29 @@ public class AtlasObjectId implements Serializable {
} }
@JsonIgnore @JsonIgnore
public boolean isValidGuid() {
return isAssignedGuid() || isUnAssignedGuid();
}
@JsonIgnore
public boolean isAssignedGuid() { public boolean isAssignedGuid() {
return isAssignedGuid; return AtlasEntity.isAssigned(guid);
} }
@JsonIgnore @JsonIgnore
public boolean isUnAssignedGuid() { public boolean isUnAssignedGuid() {
return isUnAssignedGuid; return AtlasEntity.isUnAssigned(guid);
} }
@JsonIgnore @JsonIgnore
public boolean isValid() { public boolean isValid() {
if (StringUtils.isEmpty(typeName)) { if (isAssignedGuid() || isUnAssignedGuid()) {
return false; return true;
} else if (StringUtils.isNotEmpty(guid)) { } else if (StringUtils.isNotEmpty(typeName) && MapUtils.isNotEmpty(uniqueAttributes)) {
if (!isAssignedGuid && !isUnAssignedGuid) { return true;
return false;
}
} else if (MapUtils.isEmpty(uniqueAttributes)) {
return false;
} }
return true; return false;
} }
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
...@@ -174,8 +171,8 @@ public class AtlasObjectId implements Serializable { ...@@ -174,8 +171,8 @@ public class AtlasObjectId implements Serializable {
} }
sb.append("AtlasObjectId{"); sb.append("AtlasObjectId{");
sb.append("typeName='").append(typeName).append('\''); sb.append("guid='").append(guid).append('\'');
sb.append(", guid='").append(guid).append('\''); sb.append(", typeName='").append(typeName).append('\'');
sb.append(", uniqueAttributes={"); sb.append(", uniqueAttributes={");
AtlasBaseTypeDef.dumpObjects(uniqueAttributes, sb); AtlasBaseTypeDef.dumpObjects(uniqueAttributes, sb);
sb.append('}'); sb.append('}');
...@@ -186,17 +183,27 @@ public class AtlasObjectId implements Serializable { ...@@ -186,17 +183,27 @@ public class AtlasObjectId implements Serializable {
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) {
if (o == null || getClass() != o.getClass()) return false; return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
AtlasObjectId that = (AtlasObjectId) o; AtlasObjectId that = (AtlasObjectId) o;
if (isValidGuid() && Objects.equals(guid, that.guid)) {
return true;
}
return Objects.equals(typeName, that.typeName) && return Objects.equals(typeName, that.typeName) &&
Objects.equals(guid, that.guid) && Objects.equals(uniqueAttributes, that.uniqueAttributes);
Objects.equals(uniqueAttributes, that.uniqueAttributes);
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(typeName, guid, uniqueAttributes); return isValidGuid() ? Objects.hash(guid) : Objects.hash(typeName, uniqueAttributes);
} }
@Override @Override
......
...@@ -81,7 +81,7 @@ public class AtlasStruct implements Serializable { ...@@ -81,7 +81,7 @@ public class AtlasStruct implements Serializable {
public AtlasStruct(AtlasStruct other) { public AtlasStruct(AtlasStruct other) {
if (other != null) { if (other != null) {
setTypeName(other.getTypeName()); setTypeName(other.getTypeName());
setAttributes(other.getAttributes()); setAttributes(new HashMap<>(other.getAttributes()));
} }
} }
......
...@@ -233,7 +233,7 @@ public class AtlasArrayType extends AtlasType { ...@@ -233,7 +233,7 @@ public class AtlasArrayType extends AtlasType {
ret = false; ret = false;
messages.add(objName + ": incorrect number of values. found=" + objList.size() messages.add(objName + ": incorrect number of values. found=" + objList.size()
+ "; expected: minCount=" + minCount + ", maxCount=" + maxCount); + "; expected: minCount=" + minCount + ", maxCount=" + maxCount);
} }
int idx = 0; int idx = 0;
...@@ -248,7 +248,7 @@ public class AtlasArrayType extends AtlasType { ...@@ -248,7 +248,7 @@ public class AtlasArrayType extends AtlasType {
ret = false; ret = false;
messages.add(objName + ": incorrect number of values. found=" + arrayLen messages.add(objName + ": incorrect number of values. found=" + arrayLen
+ "; expected: minCount=" + minCount + ", maxCount=" + maxCount); + "; expected: minCount=" + minCount + ", maxCount=" + maxCount);
} }
for (int i = 0; i < arrayLen; i++) { for (int i = 0; i < arrayLen; i++) {
......
...@@ -519,7 +519,7 @@ public class AtlasBuiltInTypes { ...@@ -519,7 +519,7 @@ public class AtlasBuiltInTypes {
@Override @Override
public AtlasObjectId createDefaultValue() { public AtlasObjectId createDefaultValue() {
return new AtlasObjectId(AtlasBaseTypeDef.ATLAS_TYPE_ASSET, "test"); return new AtlasObjectId("-1", AtlasBaseTypeDef.ATLAS_TYPE_ASSET);
} }
@Override @Override
...@@ -551,13 +551,16 @@ public class AtlasBuiltInTypes { ...@@ -551,13 +551,16 @@ public class AtlasBuiltInTypes {
} }
private boolean isValidMap(Map map) { private boolean isValidMap(Map map) {
if (map.containsKey(AtlasObjectId.KEY_TYPENAME)) { Object guid = map.get(AtlasObjectId.KEY_GUID);
if (map.containsKey(AtlasObjectId.KEY_GUID)) {
return true; if (guid != null && StringUtils.isNotEmpty(guid.toString())) {
} else { return true;
} else {
Object typeName = map.get(AtlasObjectId.KEY_TYPENAME);
if (typeName != null && StringUtils.isNotEmpty(typeName.toString())) {
Object uniqueAttributes = map.get(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES); Object uniqueAttributes = map.get(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES);
if (uniqueAttributes instanceof Map && MapUtils.isNotEmpty((Map)uniqueAttributes)) { if (uniqueAttributes instanceof Map && MapUtils.isNotEmpty((Map) uniqueAttributes)) {
return true; return true;
} }
} }
......
...@@ -190,6 +190,9 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -190,6 +190,9 @@ public class AtlasEntityType extends AtlasStructType {
if (obj instanceof AtlasObjectId) { if (obj instanceof AtlasObjectId) {
AtlasObjectId objId = (AtlasObjectId ) obj; AtlasObjectId objId = (AtlasObjectId ) obj;
return isAssignableFrom(objId); return isAssignableFrom(objId);
} else if (obj instanceof Map) {
AtlasObjectId objId = new AtlasObjectId((Map)obj);
return isAssignableFrom(objId);
} }
for (AtlasEntityType superType : superTypes) { for (AtlasEntityType superType : superTypes) {
......
...@@ -254,7 +254,7 @@ public class AtlasStructType extends AtlasType { ...@@ -254,7 +254,7 @@ public class AtlasStructType extends AtlasType {
} }
} }
} else if (obj instanceof Map) { } else if (obj instanceof Map) {
Map map = (Map) obj; Map attributes = AtlasTypeUtil.toStructAttributes((Map)obj);
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) { for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
String attrName = attributeDef.getName(); String attrName = attributeDef.getName();
...@@ -262,7 +262,7 @@ public class AtlasStructType extends AtlasType { ...@@ -262,7 +262,7 @@ public class AtlasStructType extends AtlasType {
if (attribute != null) { if (attribute != null) {
AtlasType dataType = attribute.getAttributeType(); AtlasType dataType = attribute.getAttributeType();
Object value = map.get(attrName); Object value = attributes.get(attrName);
String fieldName = objName + "." + attrName; String fieldName = objName + "." + attrName;
if (value != null) { if (value != null) {
...@@ -408,14 +408,16 @@ public class AtlasStructType extends AtlasType { ...@@ -408,14 +408,16 @@ public class AtlasStructType extends AtlasType {
private final AtlasType attributeType; private final AtlasType attributeType;
private final AtlasAttributeDef attributeDef; private final AtlasAttributeDef attributeDef;
private final String qualifiedName; private final String qualifiedName;
private final String vertexPropertyName;
private final boolean isOwnedRef; private final boolean isOwnedRef;
private final String inverseRefAttribute; private final String inverseRefAttribute;
public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType) { public AtlasAttribute(AtlasStructType definedInType, AtlasAttributeDef attrDef, AtlasType attributeType) {
this.definedInType = definedInType; this.definedInType = definedInType;
this.attributeDef = attrDef; this.attributeDef = attrDef;
this.attributeType = attributeType; this.attributeType = attributeType;
this.qualifiedName = getQualifiedAttributeName(definedInType.getStructDef(), attributeDef.getName()); this.qualifiedName = getQualifiedAttributeName(definedInType.getStructDef(), attributeDef.getName());
this.vertexPropertyName = encodePropertyKey(this.qualifiedName);
boolean isOwnedRef = false; boolean isOwnedRef = false;
String inverseRefAttribute = null; String inverseRefAttribute = null;
...@@ -458,17 +460,47 @@ public class AtlasStructType extends AtlasType { ...@@ -458,17 +460,47 @@ public class AtlasStructType extends AtlasType {
public String getQualifiedName() { return qualifiedName; } public String getQualifiedName() { return qualifiedName; }
public String getQualifiedAttributeName() { public String getVertexPropertyName() { return vertexPropertyName; }
return qualifiedName;
}
public boolean isOwnedRef() { return isOwnedRef; } public boolean isOwnedRef() { return isOwnedRef; }
public String getInverseRefAttribute() { return inverseRefAttribute; } public String getInverseRefAttribute() { return inverseRefAttribute; }
public static String getQualifiedAttributeName(AtlasStructDef structDef, String attrName) { private static String getQualifiedAttributeName(AtlasStructDef structDef, String attrName) {
final String typeName = structDef.getName(); final String typeName = structDef.getName();
return attrName.contains(".") ? attrName : String.format("%s.%s", typeName, attrName); return attrName.contains(".") ? attrName : String.format("%s.%s", typeName, attrName);
} }
private static String encodePropertyKey(String key) {
if (StringUtils.isBlank(key)) {
return key;
}
for (String[] strMap : RESERVED_CHAR_ENCODE_MAP) {
key = key.replace(strMap[0], strMap[1]);
}
return key;
}
private static String decodePropertyKey(String key) {
if (StringUtils.isBlank(key)) {
return key;
}
for (String[] strMap : RESERVED_CHAR_ENCODE_MAP) {
key = key.replace(strMap[1], strMap[0]);
}
return key;
}
private static String[][] RESERVED_CHAR_ENCODE_MAP = new String[][] {
new String[] { "{", "_o" },
new String[] { "}", "_c" },
new String[] { "\"", "_q" },
new String[] { "$", "_d" },
new String[] { "%", "_p" },
};
} }
} }
...@@ -21,6 +21,8 @@ import com.google.common.collect.ImmutableSet; ...@@ -21,6 +21,8 @@ import com.google.common.collect.ImmutableSet;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.typedef.AtlasClassificationDef; import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef; import org.apache.atlas.model.typedef.AtlasEntityDef;
...@@ -35,14 +37,16 @@ import org.apache.atlas.model.typedef.AtlasTypesDef; ...@@ -35,14 +37,16 @@ import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.commons.collections.CollectionUtils; import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.Arrays;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
...@@ -298,4 +302,26 @@ public class AtlasTypeUtil { ...@@ -298,4 +302,26 @@ public class AtlasTypeUtil {
return headerList; return headerList;
} }
public static Collection<AtlasObjectId> toObjectIds(Collection<AtlasEntity> entities) {
List<AtlasObjectId> ret = new ArrayList<>();
if (CollectionUtils.isNotEmpty(entities)) {
for (AtlasEntity entity : entities) {
if (entity != null) {
ret.add(entity.getAtlasObjectId());
}
}
}
return ret;
}
public static Map toStructAttributes(Map map) {
if (map != null && map.containsKey("typeName") && map.containsKey("attributes") && map.get("attributes") instanceof Map) {
return (Map)map.get("attributes");
}
return map;
}
} }
\ No newline at end of file
...@@ -45,37 +45,41 @@ public class TestAtlasObjectIdType { ...@@ -45,37 +45,41 @@ public class TestAtlasObjectIdType {
Map<Object, Object> invalidObj2 = new HashMap<>(); Map<Object, Object> invalidObj2 = new HashMap<>();
Map<Object, Object> invalidObj3 = new HashMap<>(); Map<Object, Object> invalidObj3 = new HashMap<>();
Map<Object, Object> invalidObj4 = new HashMap<>(); Map<Object, Object> invalidObj4 = new HashMap<>();
Map<Object, Object> invalidObj5 = new HashMap<>();
validObj1.put(AtlasObjectId.KEY_TYPENAME, "testType");
validObj1.put(AtlasObjectId.KEY_GUID, "guid-1234");
validObj2.put(AtlasObjectId.KEY_TYPENAME, "testType");
validObj2.put(AtlasObjectId.KEY_GUID, 1234);
Map<String, Object> uniqAttribs = new HashMap<String, Object>(); Map<String, Object> uniqAttribs = new HashMap<String, Object>();
uniqAttribs.put("name", "testTypeInstance-1"); uniqAttribs.put("name", "testTypeInstance-1");
// guid
validObj1.put(AtlasObjectId.KEY_GUID, "guid-1234");
// typeName & unique-attributes
validObj2.put(AtlasObjectId.KEY_TYPENAME, "testType");
validObj2.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, uniqAttribs);
// guid, typeName & unique-attributes
validObj3.put(AtlasObjectId.KEY_GUID, "guid-1234");
validObj3.put(AtlasObjectId.KEY_TYPENAME, "testType"); validObj3.put(AtlasObjectId.KEY_TYPENAME, "testType");
validObj3.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, uniqAttribs); validObj3.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, uniqAttribs);
invalidObj1.put(AtlasObjectId.KEY_TYPENAME, "testType"); // no guid // no guid or typeName/unique-attributes
invalidObj1.put(AtlasObjectId.KEY_GUID + "-invalid", "guid-1234"); // no guid or typename or uniqueAttribute
invalidObj2.put(AtlasObjectId.KEY_GUID, "guid-1234"); // no typeName or uniqueAttribute
invalidObj2.put(AtlasObjectId.KEY_TYPENAME + "-invalid", "testType");
invalidObj3.put(AtlasObjectId.KEY_GUID + "-invalid", "guid-1234"); // no guid or typename or uniqueAttribute // no unique-attributes
invalidObj2.put(AtlasObjectId.KEY_TYPENAME, "testType"); // no guid
invalidObj4.put(AtlasObjectId.KEY_TYPENAME, "testType"); // empty uniqueAttribute // empty uniqueAttribute
invalidObj4.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, new HashMap<String, Object>()); invalidObj3.put(AtlasObjectId.KEY_TYPENAME, "testType");
invalidObj3.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, new HashMap<String, Object>());
invalidObj5.put(AtlasObjectId.KEY_TYPENAME, "testType"); // non-map uniqueAttribute // non-map uniqueAttribute
invalidObj5.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, new ArrayList<String>()); invalidObj4.put(AtlasObjectId.KEY_TYPENAME, "testType");
invalidObj4.put(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES, new ArrayList<String>());
validValues = new Object[] { validValues = new Object[] {
null, validObj1, validObj2, validObj3, new AtlasObjectId(), new AtlasObjectId("testType", "guid-1234"), }; null, validObj1, validObj2, validObj3, new AtlasObjectId(), new AtlasObjectId("guid-1234", "testType"), };
invalidValues = new Object[] { invalidValues = new Object[] {
invalidObj1, invalidObj2, invalidObj3, invalidObj4, invalidObj5, invalidObj1, invalidObj2, invalidObj3, invalidObj4,
Byte.valueOf((byte)1), Short.valueOf((short)1), Integer.valueOf(1), Byte.valueOf((byte)1), Short.valueOf((short)1), Integer.valueOf(1),
Long.valueOf(1L), Float.valueOf(1), Double.valueOf(1), BigInteger.valueOf(1), BigDecimal.valueOf(1), "1", Long.valueOf(1L), Float.valueOf(1), Double.valueOf(1), BigInteger.valueOf(1), BigDecimal.valueOf(1), "1",
"", "12ab", "abcd", "-12ab", "", "12ab", "abcd", "-12ab",
...@@ -116,12 +120,12 @@ public class TestAtlasObjectIdType { ...@@ -116,12 +120,12 @@ public class TestAtlasObjectIdType {
if (value instanceof AtlasObjectId) { if (value instanceof AtlasObjectId) {
assertEquals(normalizedValue, value, "value=" + value); assertEquals(normalizedValue, value, "value=" + value);
} else if (value instanceof Map) { } else if (value instanceof Map) {
assertEquals(normalizedValue.getTypeName(), ((Map)value).get(AtlasObjectId.KEY_TYPENAME).toString(), assertEquals(normalizedValue.getTypeName(), ((Map)value).get(AtlasObjectId.KEY_TYPENAME),
"value=" + value); "value=" + value);
if (((Map)value).get(AtlasObjectId.KEY_GUID) == null) { if (((Map)value).get(AtlasObjectId.KEY_GUID) == null) {
assertEquals(normalizedValue.getGuid(), ((Map)value).get(AtlasObjectId.KEY_GUID), "value=" + value); assertEquals(normalizedValue.getGuid(), ((Map)value).get(AtlasObjectId.KEY_GUID), "value=" + value);
} else { } else {
assertEquals(normalizedValue.getGuid().toString(), ((Map) value).get(AtlasObjectId.KEY_GUID).toString(), "value=" + value); assertEquals(normalizedValue.getGuid(), ((Map) value).get(AtlasObjectId.KEY_GUID), "value=" + value);
} }
assertEquals(normalizedValue.getUniqueAttributes(), ((Map)value).get(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES), assertEquals(normalizedValue.getUniqueAttributes(), ((Map)value).get(AtlasObjectId.KEY_UNIQUE_ATTRIBUTES),
......
...@@ -42,17 +42,10 @@ import org.apache.atlas.repository.graph.DeleteHandler; ...@@ -42,17 +42,10 @@ import org.apache.atlas.repository.graph.DeleteHandler;
import org.apache.atlas.repository.graph.GraphBackedMetadataRepository; import org.apache.atlas.repository.graph.GraphBackedMetadataRepository;
import org.apache.atlas.repository.graph.GraphBackedSearchIndexer; import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.EntityGraphDiscovery;
import org.apache.atlas.repository.store.graph.EntityResolver;
import org.apache.atlas.repository.store.graph.v1.ArrayVertexMapper;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityGraphDiscoveryV1;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1; import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1;
import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1; import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1;
import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper; import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper;
import org.apache.atlas.repository.store.graph.v1.IDBasedEntityResolver;
import org.apache.atlas.repository.store.graph.v1.MapVertexMapper;
import org.apache.atlas.repository.store.graph.v1.UniqAttrBasedEntityResolver;
import org.apache.atlas.repository.typestore.GraphBackedTypeStore; import org.apache.atlas.repository.typestore.GraphBackedTypeStore;
import org.apache.atlas.repository.typestore.ITypeStore; import org.apache.atlas.repository.typestore.ITypeStore;
import org.apache.atlas.service.Service; import org.apache.atlas.service.Service;
...@@ -121,15 +114,6 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule { ...@@ -121,15 +114,6 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
bind(EntityGraphMapper.class); bind(EntityGraphMapper.class);
bind(MapVertexMapper.class).asEagerSingleton();
bind(ArrayVertexMapper.class).asEagerSingleton();
Multibinder<EntityResolver> entityRefResolver =
Multibinder.newSetBinder(binder(), EntityResolver.class);
entityRefResolver.addBinding().to(IDBasedEntityResolver.class);
entityRefResolver.addBinding().to(UniqAttrBasedEntityResolver.class);
//Add EntityAuditListener as EntityChangeListener //Add EntityAuditListener as EntityChangeListener
Multibinder<EntityChangeListener> entityChangeListenerBinder = Multibinder<EntityChangeListener> entityChangeListenerBinder =
Multibinder.newSetBinder(binder(), EntityChangeListener.class); Multibinder.newSetBinder(binder(), EntityChangeListener.class);
...@@ -138,8 +122,6 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule { ...@@ -138,8 +122,6 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
MethodInterceptor interceptor = new GraphTransactionInterceptor(); MethodInterceptor interceptor = new GraphTransactionInterceptor();
requestInjection(interceptor); requestInjection(interceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), interceptor); bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), interceptor);
bind(EntityGraphDiscovery.class).to(AtlasEntityGraphDiscoveryV1.class);
} }
protected Configuration getConfiguration() { protected Configuration getConfiguration() {
......
...@@ -244,7 +244,7 @@ public final class GraphHelper { ...@@ -244,7 +244,7 @@ public final class GraphHelper {
/** /**
Iterable<AtlasEdge> edges = outVertex.getEdges(Direction.OUT, edgeLabel); Iterable<AtlasEdge> edges = outVertex.getEdges(Direction.OUT, edgeLabel);
for (AtlasEdge edge : edges) { for (AtlasEdge edge : edges) {
if (edge.getId().toString().equals(edgeId)) { if (edge.getObjectId().toString().equals(edgeId)) {
return edge; return edge;
} }
} }
......
...@@ -86,39 +86,7 @@ public class AtlasTypeDefStoreInitializer { ...@@ -86,39 +86,7 @@ public class AtlasTypeDefStoreInitializer {
continue; continue;
} }
AtlasTypesDef typesToCreate = new AtlasTypesDef(); AtlasTypesDef typesToCreate = getTypesToCreate(typesDef, typeRegistry);
if (CollectionUtils.isNotEmpty(typesDef.getEnumDefs())) {
for (AtlasEnumDef enumDef : typesDef.getEnumDefs()) {
if (!typeRegistry.isRegisteredType(enumDef.getName())) {
typesToCreate.getEnumDefs().add(enumDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getStructDefs())) {
for (AtlasStructDef structDef : typesDef.getStructDefs()) {
if (!typeRegistry.isRegisteredType(structDef.getName())) {
typesToCreate.getStructDefs().add(structDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getClassificationDefs())) {
for (AtlasClassificationDef classificationDef : typesDef.getClassificationDefs()) {
if (!typeRegistry.isRegisteredType(classificationDef.getName())) {
typesToCreate.getClassificationDefs().add(classificationDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getEntityDefs())) {
for (AtlasEntityDef entityDef : typesDef.getEntityDefs()) {
if (!typeRegistry.isRegisteredType(entityDef.getName())) {
typesToCreate.getEntityDefs().add(entityDef);
}
}
}
if (typesToCreate.isEmpty()) { if (typesToCreate.isEmpty()) {
LOG.info("No new type in file {}", typeDefFile.getAbsolutePath()); LOG.info("No new type in file {}", typeDefFile.getAbsolutePath());
...@@ -137,6 +105,44 @@ public class AtlasTypeDefStoreInitializer { ...@@ -137,6 +105,44 @@ public class AtlasTypeDefStoreInitializer {
applyTypePatches(typeDefStore, typeRegistry, typesDirName); applyTypePatches(typeDefStore, typeRegistry, typesDirName);
} }
public static AtlasTypesDef getTypesToCreate(AtlasTypesDef typesDef, AtlasTypeRegistry typeRegistry) {
AtlasTypesDef typesToCreate = new AtlasTypesDef();
if (CollectionUtils.isNotEmpty(typesDef.getEnumDefs())) {
for (AtlasEnumDef enumDef : typesDef.getEnumDefs()) {
if (!typeRegistry.isRegisteredType(enumDef.getName())) {
typesToCreate.getEnumDefs().add(enumDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getStructDefs())) {
for (AtlasStructDef structDef : typesDef.getStructDefs()) {
if (!typeRegistry.isRegisteredType(structDef.getName())) {
typesToCreate.getStructDefs().add(structDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getClassificationDefs())) {
for (AtlasClassificationDef classificationDef : typesDef.getClassificationDefs()) {
if (!typeRegistry.isRegisteredType(classificationDef.getName())) {
typesToCreate.getClassificationDefs().add(classificationDef);
}
}
}
if (CollectionUtils.isNotEmpty(typesDef.getEntityDefs())) {
for (AtlasEntityDef entityDef : typesDef.getEntityDefs()) {
if (!typeRegistry.isRegisteredType(entityDef.getName())) {
typesToCreate.getEntityDefs().add(entityDef);
}
}
}
return typesToCreate;
}
private void applyTypePatches(AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry, String typesDirName) { private void applyTypePatches(AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry, String typesDirName) {
String typePatchesDirName = typesDirName + File.separator + "patches"; String typePatchesDirName = typesDirName + File.separator + "patches";
File typePatchesDir = new File(typePatchesDirName); File typePatchesDir = new File(typePatchesDirName);
......
...@@ -24,8 +24,8 @@ import org.apache.atlas.model.instance.AtlasEntity; ...@@ -24,8 +24,8 @@ import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.repository.store.graph.v1.EntityStream;
import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -34,13 +34,6 @@ import java.util.Map; ...@@ -34,13 +34,6 @@ import java.util.Map;
* Persistence/Retrieval API for AtlasEntity * Persistence/Retrieval API for AtlasEntity
*/ */
public interface AtlasEntityStore { public interface AtlasEntityStore {
/**
* Initialization
*/
void init(AtlasTypeRegistry typeRegistry) throws AtlasBaseException;
/** /**
* *
* Get entity definition by its guid * Get entity definition by its guid
...@@ -50,22 +43,6 @@ public interface AtlasEntityStore { ...@@ -50,22 +43,6 @@ public interface AtlasEntityStore {
AtlasEntityWithExtInfo getById(String guid) throws AtlasBaseException; AtlasEntityWithExtInfo getById(String guid) throws AtlasBaseException;
/** /**
* Delete an entity by its guid
* @param guid
* @return
*/
EntityMutationResponse deleteById(String guid);
/**
* Create or update entities
* @param entities Map of the entity Id(guid or transient Id) to AtlasEntity objects that need to be created
* @return EntityMutationResponse Entity mutations operations with the correspomding set of entities on which these operations were performed
* @throws AtlasBaseException
*/
EntityMutationResponse createOrUpdate(Map<String, AtlasEntity> entities) throws AtlasBaseException;
/**
* Batch GET to retrieve entities by their ID * Batch GET to retrieve entities by their ID
* @param guid * @param guid
* @return * @return
...@@ -73,43 +50,57 @@ public interface AtlasEntityStore { ...@@ -73,43 +50,57 @@ public interface AtlasEntityStore {
*/ */
AtlasEntitiesWithExtInfo getByIds(List<String> guid) throws AtlasBaseException; AtlasEntitiesWithExtInfo getByIds(List<String> guid) throws AtlasBaseException;
/*
* Return list of deleted entity guids
*/
EntityMutationResponse deleteByIds(List<String> guid) throws AtlasBaseException;
/** /**
* *
* Get an eneity by its unique attribute * Get an eneity by its unique attribute
* @param entityType * @param entityType type of the entity
* @param uniqAttributes * @param uniqAttributes Attributes that uniquely identify the entity
* @return AtlasEntity * @return EntityMutationResponse details of the updates performed by this call
*/ */
AtlasEntityWithExtInfo getByUniqueAttribute(AtlasEntityType entityType, Map<String, Object> uniqAttributes) AtlasEntityWithExtInfo getByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes)
throws AtlasBaseException; throws AtlasBaseException;
/**
* Create or update entities in the stream
* @param entityStream AtlasEntityStream
* @return EntityMutationResponse Entity mutations operations with the corresponding set of entities on which these operations were performed
* @throws AtlasBaseException
*/
EntityMutationResponse createOrUpdate(EntityStream entityStream) throws AtlasBaseException;
/** /**
* @deprecated * @deprecated
* Create or update a single entity * Update a single entity
* @param typeName The entity's type * @param entityType type of the entity
* @param attributeName Attribute that uniquely identifies the entity * @param uniqAttributes Attributes that uniquely identify the entity
* @param attributeValue The unqiue attribute's value * @return EntityMutationResponse details of the updates performed by this call
* @return EntityMutationResponse Entity mutations operations with the correspomding set of entities on which these operations were performed
* @throws AtlasBaseException * @throws AtlasBaseException
* *
*/ */
EntityMutationResponse updateByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes,
AtlasEntity entity) throws AtlasBaseException;
EntityMutationResponse updateByUniqueAttribute(String typeName, String attributeName, String attributeValue, AtlasEntity entity) throws AtlasBaseException; /**
* Delete an entity by its guid
* @param guid
* @return
*/
EntityMutationResponse deleteById(String guid) throws AtlasBaseException;
/** /**
* @deprecated * @deprecated
* @param typeName * @param entityType type of the entity
* @param attributeName * @param uniqAttributes Attributes that uniquely identify the entity
* @param attributeValue * @return EntityMutationResponse details of the updates performed by this call
* @return
* @throws AtlasBaseException * @throws AtlasBaseException
*/ */
EntityMutationResponse deleteByUniqueAttribute(String typeName, String attributeName, String attributeValue) throws AtlasBaseException; EntityMutationResponse deleteByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes)
throws AtlasBaseException;
/*
* Return list of deleted entity guids
*/
EntityMutationResponse deleteByIds(List<String> guid) throws AtlasBaseException;
/** /**
* Add classification(s) * Add classification(s)
......
...@@ -20,8 +20,10 @@ package org.apache.atlas.repository.store.graph; ...@@ -20,8 +20,10 @@ package org.apache.atlas.repository.store.graph;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
import java.util.List; import java.util.List;
import java.util.Map;
public interface EntityGraphDiscovery { public interface EntityGraphDiscovery {
...@@ -33,7 +35,7 @@ public interface EntityGraphDiscovery { ...@@ -33,7 +35,7 @@ public interface EntityGraphDiscovery {
* Resolved references already exist in the ATLAS repository and have an assigned unique GUID * Resolved references already exist in the ATLAS repository and have an assigned unique GUID
* Unresolved attribute references result in an error if they are not composite (managed by a parent entity) * Unresolved attribute references result in an error if they are not composite (managed by a parent entity)
*/ */
EntityGraphDiscoveryContext discoverEntities(List<AtlasEntity> entities) throws AtlasBaseException; EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException;
void cleanUp() throws AtlasBaseException; void cleanUp() throws AtlasBaseException;
} }
...@@ -17,179 +17,117 @@ ...@@ -17,179 +17,117 @@
*/ */
package org.apache.atlas.repository.store.graph; package org.apache.atlas.repository.store.graph;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.v1.EntityStream;
import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap;
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;
public final class EntityGraphDiscoveryContext { public final class EntityGraphDiscoveryContext {
private static final Logger LOG = LoggerFactory.getLogger(EntityGraphDiscoveryContext.class); private static final Logger LOG = LoggerFactory.getLogger(EntityGraphDiscoveryContext.class);
private final AtlasTypeRegistry typeRegistry; private final AtlasTypeRegistry typeRegistry;
private List<AtlasEntity> rootEntities = new ArrayList<>(); private final EntityStream entityStream;
private Map<AtlasObjectId, AtlasVertex> resolvedIds = new LinkedHashMap<>(); private final List<String> referencedGuids = new ArrayList<>();
private Set<AtlasObjectId> unresolvedIds = new HashSet<>(); private final Set<AtlasObjectId> referencedByUniqAttribs = new HashSet<>();
private List<AtlasObjectId> unresolvedIdsByUniqAttribs = new ArrayList<>(); private final Map<String, AtlasVertex> resolvedGuids = new HashMap<>();
private final Map<AtlasObjectId, AtlasVertex> resolvedIdsByUniqAttribs = new HashMap<>();
private final Set<String> localGuids = new HashSet<>();
public EntityGraphDiscoveryContext(AtlasTypeRegistry typeRegistry) { public EntityGraphDiscoveryContext(AtlasTypeRegistry typeRegistry, EntityStream entityStream) {
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
this.entityStream = entityStream;
} }
public EntityStream getEntityStream() {
public Collection<AtlasEntity> getRootEntities() { return entityStream;
return rootEntities;
} }
public Map<AtlasObjectId, AtlasVertex> getResolvedIds() { public List<String> getReferencedGuids() { return referencedGuids; }
return resolvedIds;
}
public Set<AtlasObjectId> getUnresolvedIds() { public Set<AtlasObjectId> getReferencedByUniqAttribs() { return referencedByUniqAttribs; }
return unresolvedIds;
}
public List<AtlasObjectId> getUnresolvedIdsByUniqAttribs() { public Map<String, AtlasVertex> getResolvedGuids() {
return unresolvedIdsByUniqAttribs; return resolvedGuids;
} }
public Map<AtlasObjectId, AtlasVertex> getResolvedIdsByUniqAttribs() {
public void addRootEntity(AtlasEntity rootEntity) { return resolvedIdsByUniqAttribs;
this.rootEntities.add(rootEntity);
} }
public Set<String> getLocalGuids() { return localGuids; }
public void addResolvedId(AtlasObjectId objId, AtlasVertex vertex) {
if (LOG.isDebugEnabled()) {
LOG.debug("addResolvedId({})", objId);
}
resolvedIds.put(objId, vertex);
}
public boolean removeUnResolvedId(AtlasObjectId objId) { public void addReferencedGuid(String guid) {
if (LOG.isDebugEnabled()) { if (! referencedGuids.contains(guid)) {
LOG.debug("removeUnResolvedId({})", objId); referencedGuids.add(guid);
} }
return unresolvedIds.remove(objId);
} }
public void addReferencedByUniqAttribs(AtlasObjectId objId) { referencedByUniqAttribs.add(objId); }
public void addUnResolvedId(AtlasObjectId objId) {
if (LOG.isDebugEnabled()) {
LOG.debug("addUnResolvedId({})", objId);
}
this.unresolvedIds.add(objId); public void addResolvedGuid(String guid, AtlasVertex vertex) { resolvedGuids.put(guid, vertex); }
}
public boolean removeUnResolvedIds(List<AtlasObjectId> objIds) { public void addResolvedIdByUniqAttribs(AtlasObjectId objId, AtlasVertex vertex) { resolvedIdsByUniqAttribs.put(objId, vertex); }
if (LOG.isDebugEnabled()) {
LOG.debug("removeUnResolvedIds({})", objIds);
}
return unresolvedIds.removeAll(objIds); public void addLocalGuidReference(String guid) { localGuids.add(guid); }
}
public boolean isResolvedGuid(String guid) { return resolvedGuids.containsKey(guid); }
public void addUnresolvedIdByUniqAttribs(AtlasObjectId objId) { public boolean isResolvedIdByUniqAttrib(AtlasObjectId objId) { return resolvedIdsByUniqAttribs.containsKey(objId); }
if (LOG.isDebugEnabled()) {
LOG.debug("addUnresolvedIdByUniqAttribs({})", objId);
}
this.unresolvedIdsByUniqAttribs.add(objId);
}
public boolean removeUnresolvedIdsByUniqAttribs(List<AtlasObjectId> objIds) { public AtlasVertex getResolvedEntityVertex(String guid) throws AtlasBaseException {
if (LOG.isDebugEnabled()) { AtlasVertex ret = resolvedGuids.get(guid);
LOG.debug("removeUnresolvedIdsByUniqAttribs({})", objIds);
}
return unresolvedIdsByUniqAttribs.removeAll(objIds); return ret;
} }
public boolean hasUnresolvedReferences() { public AtlasVertex getResolvedEntityVertex(AtlasObjectId objId) {
return unresolvedIdsByUniqAttribs.size() > 0 || unresolvedIds.size() > 0; AtlasVertex vertex = resolvedIdsByUniqAttribs.get(objId);
}
public boolean isResolvedId(AtlasObjectId id) {
return resolvedIds.containsKey(id);
}
public AtlasVertex getResolvedEntityVertex(AtlasObjectId ref) throws AtlasBaseException {
AtlasVertex vertex = resolvedIds.get(ref);
// check also for sub-types; ref={typeName=Asset; guid=abcd} should match {typeName=hive_table; guid=abcd} // check also for sub-types; ref={typeName=Asset; guid=abcd} should match {typeName=hive_table; guid=abcd}
if (vertex == null) { if (vertex == null) {
final AtlasEntityType entityType = typeRegistry.getEntityTypeByName(ref.getTypeName()); final AtlasEntityType entityType = typeRegistry.getEntityTypeByName(objId.getTypeName());
final Set<String> allSubTypes = entityType.getAllSubTypes(); final Set<String> allSubTypes = entityType.getAllSubTypes();
for (String subType : allSubTypes) { for (String subType : allSubTypes) {
AtlasObjectId subTypeObjId = new AtlasObjectId(subType, ref.getGuid(), ref.getUniqueAttributes()); AtlasObjectId subTypeObjId = new AtlasObjectId(objId.getGuid(), subType, objId.getUniqueAttributes());
vertex = resolvedIds.get(subTypeObjId); vertex = resolvedIdsByUniqAttribs.get(subTypeObjId);
if (vertex != null) { if (vertex != null) {
resolvedIds.put(ref, vertex); resolvedIdsByUniqAttribs.put(objId, vertex);
break; break;
} }
} }
} }
if (vertex == null) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS,
" : Could not find an entity with " + ref.toString());
}
return vertex; return vertex;
} }
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (obj == this) {
return true;
} else if (obj.getClass() != getClass()) {
return false;
} else {
EntityGraphDiscoveryContext ctx = (EntityGraphDiscoveryContext) obj;
return Objects.equals(rootEntities, ctx.getRootEntities()) &&
Objects.equals(resolvedIds, ctx.getResolvedIds()) &&
Objects.equals(unresolvedIdsByUniqAttribs, ctx.getUnresolvedIdsByUniqAttribs()) &&
Objects.equals(unresolvedIds, ctx.getUnresolvedIds());
}
}
@Override
public int hashCode() {
return Objects.hash(rootEntities, resolvedIds, unresolvedIdsByUniqAttribs, unresolvedIds);
}
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
sb = new StringBuilder(); sb = new StringBuilder();
} }
sb.append("EntityGraphDiscoveryCtx{"); sb.append("EntityGraphDiscoveryCtx{");
sb.append("rootEntities='").append(rootEntities).append('\''); sb.append("referencedGuids=").append(referencedGuids);
sb.append(", resolvedIds=").append(resolvedIds); sb.append(", referencedByUniqAttribs=").append(referencedByUniqAttribs);
sb.append(", unresolvedIdsByUniqAttribs='").append(unresolvedIdsByUniqAttribs).append('\''); sb.append(", resolvedGuids='").append(resolvedGuids);
sb.append(", unresolvedIds='").append(unresolvedIds).append('\''); sb.append(", resolvedIdsByUniqAttribs='").append(resolvedIdsByUniqAttribs);
sb.append(", localGuids='").append(localGuids);
sb.append('}'); sb.append('}');
return sb; return sb;
...@@ -201,9 +139,10 @@ public final class EntityGraphDiscoveryContext { ...@@ -201,9 +139,10 @@ public final class EntityGraphDiscoveryContext {
} }
public void cleanUp() { public void cleanUp() {
rootEntities.clear(); referencedGuids.clear();
unresolvedIdsByUniqAttribs.clear(); referencedByUniqAttribs.clear();
resolvedIds.clear(); resolvedGuids.clear();
unresolvedIds.clear(); resolvedIdsByUniqAttribs.clear();
localGuids.clear();
} }
} }
...@@ -21,10 +21,5 @@ import org.apache.atlas.exception.AtlasBaseException; ...@@ -21,10 +21,5 @@ import org.apache.atlas.exception.AtlasBaseException;
public interface EntityResolver { public interface EntityResolver {
EntityGraphDiscoveryContext resolveEntityReferences(EntityGraphDiscoveryContext entities) throws AtlasBaseException;
void init(EntityGraphDiscoveryContext entities) throws AtlasBaseException;
EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException;
void cleanUp() throws AtlasBaseException;
} }
/**
* 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.base.Optional;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
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.type.AtlasArrayType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.apache.atlas.repository.graph.GraphHelper.string;
@Singleton
public class ArrayVertexMapper implements InstanceGraphMapper<List> {
private static final Logger LOG = LoggerFactory.getLogger(ArrayVertexMapper.class);
protected final DeleteHandlerV1 deleteHandler;
protected StructVertexMapper structVertexMapper;
@Inject
public ArrayVertexMapper(DeleteHandlerV1 deleteHandler) {
this.deleteHandler = deleteHandler;
}
void init(StructVertexMapper structVertexMapper) {
this.structVertexMapper = structVertexMapper;
}
@Override
public List toGraph(GraphMutationContext ctx) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("Mapping instance to vertex {} for array attribute {}", string(ctx.getReferringVertex()), ctx.getAttrType().getTypeName());
}
List newElements = (List) ctx.getValue();
boolean newAttributeEmpty = (newElements == null || newElements.isEmpty());
AtlasArrayType arrType = (AtlasArrayType) ctx.getAttrType();
AtlasType elementType = arrType.getElementType();
List<Object> currentElements = getArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexPropertyKey());
List<Object> newElementsCreated = new ArrayList<>();
if (!newAttributeEmpty) {
for (int index = 0; index < newElements.size(); index++) {
LOG.debug("Adding/updating element at position {}, current element {}, new element {}", index,
(currentElements != null && index < currentElements.size()) ? currentElements.get(index) : null, newElements.get(index));
Optional<AtlasEdge> existingEdge = getEdgeAt(currentElements, index, arrType.getElementType());
GraphMutationContext arrCtx = new GraphMutationContext.Builder(ctx.getOp(), ctx.getAttribute(),
arrType.getElementType(), newElements.get(index))
.referringVertex(ctx.getReferringVertex())
.edge(existingEdge)
.vertexProperty(ctx.getVertexPropertyKey()).build();
Object newEntry = structVertexMapper.mapCollectionElementsToVertex(arrCtx);
newElementsCreated.add(newEntry);
}
}
if (AtlasGraphUtilsV1.isReference(elementType)) {
List<AtlasEdge> additionalEdges = removeUnusedArrayEntries(ctx.getParentType(), ctx.getAttributeDef(), (List) currentElements, (List) newElementsCreated, elementType);
newElementsCreated.addAll(additionalEdges);
}
// for dereference on way out
setArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexPropertyKey(), newElementsCreated);
return newElementsCreated;
}
@Override
public void cleanUp() throws AtlasBaseException {
}
//Removes unused edges from the old collection, compared to the new collection
private List<AtlasEdge> removeUnusedArrayEntries(
AtlasStructType entityType,
AtlasAttributeDef attributeDef,
List<AtlasEdge> currentEntries,
List<AtlasEdge> newEntries,
AtlasType entryType) throws AtlasBaseException {
if (currentEntries != null && !currentEntries.isEmpty()) {
LOG.debug("Removing unused entries from the old collection");
if (AtlasGraphUtilsV1.isReference(entryType)) {
Collection<AtlasEdge> edgesToRemove = CollectionUtils.subtract(currentEntries, newEntries);
LOG.debug("Removing unused entries from the old collection - {}", edgesToRemove);
if (!edgesToRemove.isEmpty()) {
//Remove the edges for (current edges - new edges)
List<AtlasEdge> additionalElements = new ArrayList<>();
for (AtlasEdge edge : edgesToRemove) {
boolean deleteChildReferences = StructVertexMapper.shouldManageChildReferences(entityType, attributeDef.getName());
boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(),
deleteChildReferences, true);
if (!deleted) {
additionalElements.add(edge);
}
}
return additionalElements;
}
}
}
return Collections.emptyList();
}
public static List<Object> getArrayElementsProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName) {
String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
if (AtlasGraphUtilsV1.isReference(elementType)) {
return (List)instanceVertex.getListProperty(actualPropertyName, AtlasEdge.class);
}
else {
return (List)instanceVertex.getListProperty(actualPropertyName);
}
}
private Optional<AtlasEdge> getEdgeAt(List<Object> currentElements, int index, AtlasType elemType) {
Optional<AtlasEdge> existingEdge = Optional.absent();
if ( AtlasGraphUtilsV1.isReference(elemType) ) {
Object currentElement = (currentElements != null && index < currentElements.size()) ?
currentElements.get(index) : null;
if ( currentElement != null) {
existingEdge = Optional.of((AtlasEdge) currentElement);
}
}
return existingEdge;
}
private void setArrayElementsProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName, List<Object> values) {
String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
if (AtlasGraphUtilsV1.isReference(elementType)) {
GraphHelper.setListPropertyFromElementIds(instanceVertex, actualPropertyName, (List) values);
}
else {
GraphHelper.setProperty(instanceVertex, actualPropertyName, values);
}
}
}
/**
* 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
* <p>
* http://www.apache.org/licenses/LICENSE-2.0
* <p>
* 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 org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import java.util.Iterator;
public class AtlasEntityStream implements EntityStream {
private AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
private Iterator<AtlasEntity> iterator;
public AtlasEntityStream() {
}
public AtlasEntityStream(AtlasEntity entity) {
this(new AtlasEntitiesWithExtInfo(entity));
}
public AtlasEntityStream(AtlasEntityWithExtInfo entityWithExtInfo) {
this(new AtlasEntitiesWithExtInfo(entityWithExtInfo));
}
public AtlasEntityStream(AtlasEntitiesWithExtInfo entitiesWithExtInfo) {
this.entitiesWithExtInfo = entitiesWithExtInfo;
this.iterator = this.entitiesWithExtInfo.getEntities().iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public AtlasEntity next() {
return iterator.hasNext() ? iterator.next() : null;
}
@Override
public void reset() {
this.iterator = entitiesWithExtInfo.getEntities().iterator();
}
@Override
public AtlasEntity getByGuid(String guid) {
return entitiesWithExtInfo.getEntity(guid);
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer("AtlasEntityStream{");
sb.append("entitiesWithExtInfo=").append(entitiesWithExtInfo);
sb.append(", iterator=").append(iterator);
sb.append('}');
return sb.toString();
}
}
...@@ -217,7 +217,7 @@ public class AtlasGraphUtilsV1 { ...@@ -217,7 +217,7 @@ public class AtlasGraphUtilsV1 {
if (entityVertex == null) { if (entityVertex == null) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND, entityType.getTypeName(), throw new AtlasBaseException(AtlasErrorCode.INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND, entityType.getTypeName(),
uniqAttributes.keySet().toString(), uniqAttributes.values().toString()); uniqAttributes.toString());
} }
return entityVertex; return entityVertex;
......
...@@ -18,26 +18,25 @@ ...@@ -18,26 +18,25 @@
package org.apache.atlas.repository.store.graph.v1; package org.apache.atlas.repository.store.graph.v1;
import com.google.common.base.Optional; import org.apache.atlas.model.instance.EntityMutations.EntityOperation;
import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.typedef.AtlasStructDef; import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef; import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasStructType.AtlasAttribute;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import java.util.Objects;
public class GraphMutationContext {
import java.util.Objects;
private EntityMutations.EntityOperation op; public class AttributeMutationContext {
private EntityOperation op;
/** /**
* Atlas Attribute * Atlas Attribute
*/ */
private AtlasStructType.AtlasAttribute attribute; private AtlasAttribute attribute;
/** /**
* Overriding type for which elements are being mapped * Overriding type for which elements are being mapped
...@@ -49,6 +48,8 @@ public class GraphMutationContext { ...@@ -49,6 +48,8 @@ public class GraphMutationContext {
*/ */
private Object value; private Object value;
private String vertexProperty;
/** /**
* *
* The vertex which corresponds to the entity/struct for which we are mapping a complex attributes like struct, traits * The vertex which corresponds to the entity/struct for which we are mapping a complex attributes like struct, traits
...@@ -56,34 +57,28 @@ public class GraphMutationContext { ...@@ -56,34 +57,28 @@ public class GraphMutationContext {
AtlasVertex referringVertex; AtlasVertex referringVertex;
/** /**
* the vertex property that we are updating
*/
String vertexPropertyKey;
/**
* The current edge(in case of updates) from the parent entity/struct to the complex attribute like struct, trait * The current edge(in case of updates) from the parent entity/struct to the complex attribute like struct, trait
*/ */
Optional<AtlasEdge> existingEdge; AtlasEdge existingEdge;
private GraphMutationContext(final Builder builder) { public AttributeMutationContext(EntityOperation op, AtlasVertex referringVertex, AtlasAttribute attribute, Object value) {
this.op = builder.op; this(op, referringVertex, attribute, value, attribute.getVertexPropertyName(), null, null);
this.attribute = builder.attribute;
this.currentElementType = builder.elementType;
this.existingEdge = builder.currentEdge;
this.value = builder.currentValue;
this.referringVertex = builder.referringVertex;
this.vertexPropertyKey = builder.vertexPropertyKey;
} }
public String getVertexPropertyKey() { public AttributeMutationContext(EntityOperation op, AtlasVertex referringVertex, AtlasAttribute attribute, Object value,
return vertexPropertyKey; String vertexProperty, AtlasType currentElementType, AtlasEdge currentEdge) {
this.op = op;
this.referringVertex = referringVertex;
this.attribute = attribute;
this.value = value;
this.vertexProperty = vertexProperty;
this.currentElementType = currentElementType;
this.existingEdge = currentEdge;
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(op, attribute, value, referringVertex, vertexPropertyKey, existingEdge); return Objects.hash(op, referringVertex, attribute, value, vertexProperty, currentElementType, existingEdge);
} }
@Override @Override
...@@ -95,70 +90,18 @@ public class GraphMutationContext { ...@@ -95,70 +90,18 @@ public class GraphMutationContext {
} else if (obj.getClass() != getClass()) { } else if (obj.getClass() != getClass()) {
return false; return false;
} else { } else {
GraphMutationContext rhs = (GraphMutationContext) obj; AttributeMutationContext rhs = (AttributeMutationContext) obj;
return Objects.equals(attribute, rhs.getAttribute()) return Objects.equals(op, rhs.op)
&& Objects.equals(value, rhs.getValue()) && Objects.equals(referringVertex, rhs.referringVertex)
&& Objects.equals(referringVertex, rhs.getReferringVertex()) && Objects.equals(attribute, rhs.attribute)
&& Objects.equals(vertexPropertyKey, rhs.getReferringVertex()) && Objects.equals(value, rhs.value)
&& Objects.equals(existingEdge, rhs.getCurrentEdge()) && Objects.equals(vertexProperty, rhs.vertexProperty)
&& Objects.equals(op, rhs.getOp()); && Objects.equals(currentElementType, rhs.currentElementType)
&& Objects.equals(existingEdge, rhs.existingEdge);
} }
} }
public static final class Builder {
private final EntityMutations.EntityOperation op;
private final AtlasStructType.AtlasAttribute attribute;
private final AtlasType elementType;
private final Object currentValue;
private AtlasVertex referringVertex;
private Optional<AtlasEdge> currentEdge = Optional.absent();
private String vertexPropertyKey;
public Builder(EntityMutations.EntityOperation op, AtlasStructType.AtlasAttribute attribute, AtlasType currentElementType, Object currentValue) {
this.op = op;
this.attribute = attribute;
this.elementType = currentElementType;
this.currentValue = currentValue;
}
public Builder(EntityMutations.EntityOperation op, AtlasStructType.AtlasAttribute attribute, Object currentValue) {
this(op, attribute, null, currentValue);
}
Builder referringVertex(AtlasVertex referringVertex) {
this.referringVertex = referringVertex;
return this;
}
Builder edge(AtlasEdge edge) {
this.currentEdge = Optional.of(edge);
return this;
}
Builder edge(Optional<AtlasEdge> edge) {
this.currentEdge = edge;
return this;
}
Builder vertexProperty(String propertyKey) {
this.vertexPropertyKey = propertyKey;
return this;
}
GraphMutationContext build() {
return new GraphMutationContext(this);
}
}
public AtlasStructType getParentType() { public AtlasStructType getParentType() {
return attribute.getDefinedInType(); return attribute.getDefinedInType();
} }
...@@ -183,11 +126,11 @@ public class GraphMutationContext { ...@@ -183,11 +126,11 @@ public class GraphMutationContext {
return value; return value;
} }
public AtlasVertex getReferringVertex() { public String getVertexProperty() { return vertexProperty; }
return referringVertex;
}
public Optional<AtlasEdge> getCurrentEdge() { public AtlasVertex getReferringVertex() { return referringVertex; }
public AtlasEdge getCurrentEdge() {
return existingEdge; return existingEdge;
} }
...@@ -195,15 +138,13 @@ public class GraphMutationContext { ...@@ -195,15 +138,13 @@ public class GraphMutationContext {
this.currentElementType = attrType; this.currentElementType = attrType;
} }
public AtlasStructType.AtlasAttribute getAttribute() { public AtlasAttribute getAttribute() {
return attribute; return attribute;
} }
public EntityMutations.EntityOperation getOp() { public EntityOperation getOp() {
return op; return op;
} }
public void setExistingEdge(final Optional<AtlasEdge> existingEdge) { public void setExistingEdge(AtlasEdge existingEdge) { this.existingEdge = existingEdge; }
this.existingEdge = existingEdge;
}
} }
...@@ -98,7 +98,7 @@ public abstract class DeleteHandlerV1 { ...@@ -98,7 +98,7 @@ public abstract class DeleteHandlerV1 {
// Record all deletion candidate GUIDs in RequestContext // Record all deletion candidate GUIDs in RequestContext
// and gather deletion candidate vertices. // and gather deletion candidate vertices.
for (GraphHelper.VertexInfo vertexInfo : compositeVertices) { for (GraphHelper.VertexInfo vertexInfo : compositeVertices) {
requestContext.recordEntityDelete(new AtlasObjectId(vertexInfo.getTypeName(), vertexInfo.getGuid())); requestContext.recordEntityDelete(new AtlasObjectId(vertexInfo.getGuid(), vertexInfo.getTypeName()));
deletionCandidateVertices.add(vertexInfo.getVertex()); deletionCandidateVertices.add(vertexInfo.getVertex());
} }
} }
...@@ -324,7 +324,7 @@ public abstract class DeleteHandlerV1 { ...@@ -324,7 +324,7 @@ public abstract class DeleteHandlerV1 {
String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(structType, attributeInfo.getName()); String propertyName = AtlasGraphUtilsV1.getQualifiedAttributePropertyKey(structType, attributeInfo.getName());
if (AtlasGraphUtilsV1.isReference(valueTypeCategory)) { if (AtlasGraphUtilsV1.isReference(valueTypeCategory)) {
List<Object> keys = ArrayVertexMapper.getArrayElementsProperty(keyType, instanceVertex, propertyName); List<Object> keys = EntityGraphMapper.getArrayElementsProperty(keyType, instanceVertex, propertyName);
if (keys != null) { if (keys != null) {
for (Object key : keys) { for (Object key : keys) {
String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, (String) key); String mapEdgeLabel = GraphHelper.getQualifiedNameForMapKey(edgeLabel, (String) key);
...@@ -513,7 +513,7 @@ public abstract class DeleteHandlerV1 { ...@@ -513,7 +513,7 @@ public abstract class DeleteHandlerV1 {
GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY, GraphHelper.setProperty(outVertex, Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY,
requestContext.getRequestTime()); requestContext.getRequestTime());
GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser()); GraphHelper.setProperty(outVertex, Constants.MODIFIED_BY_KEY, requestContext.getUser());
requestContext.recordEntityUpdate(new AtlasObjectId(typeName, outId)); requestContext.recordEntityUpdate(new AtlasObjectId(outId, typeName));
} }
} }
......
...@@ -22,6 +22,7 @@ import org.apache.atlas.AtlasException; ...@@ -22,6 +22,7 @@ import org.apache.atlas.AtlasException;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityExtInfo;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
...@@ -100,6 +101,22 @@ public final class EntityGraphRetriever { ...@@ -100,6 +101,22 @@ public final class EntityGraphRetriever {
return ret; return ret;
} }
public AtlasEntitiesWithExtInfo toAtlasEntitiesWithExtInfo(List<String> guids) throws AtlasBaseException {
AtlasEntitiesWithExtInfo ret = new AtlasEntitiesWithExtInfo();
for (String guid : guids) {
AtlasVertex vertex = getEntityVertex(guid);
AtlasEntity entity = mapVertexToAtlasEntity(vertex, ret);
ret.addEntity(entity);
}
ret.compact();
return ret;
}
private AtlasVertex getEntityVertex(String guid) throws AtlasBaseException { private AtlasVertex getEntityVertex(String guid) throws AtlasBaseException {
try { try {
return graphHelper.getVertexForGUID(guid); return graphHelper.getVertexForGUID(guid);
...@@ -405,7 +422,7 @@ public final class EntityGraphRetriever { ...@@ -405,7 +422,7 @@ public final class EntityGraphRetriever {
ret = entity.getAtlasObjectId(); ret = entity.getAtlasObjectId();
} }
} else { } else {
ret = new AtlasObjectId(GraphHelper.getTypeName(referenceVertex), GraphHelper.getGuid(referenceVertex)); ret = new AtlasObjectId(GraphHelper.getGuid(referenceVertex), GraphHelper.getTypeName(referenceVertex));
} }
} }
} }
......
...@@ -24,32 +24,37 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; ...@@ -24,32 +24,37 @@ import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext; import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.commons.lang.StringUtils;
import java.util.*; import java.util.*;
public class EntityMutationContext { public class EntityMutationContext {
private final EntityGraphDiscoveryContext context; private final EntityGraphDiscoveryContext context;
private final List<AtlasEntity> entitiesCreated = new ArrayList<>(); private final List<AtlasEntity> entitiesCreated = new ArrayList<>();
private final List<AtlasEntity> entitiesUpdated = new ArrayList<>(); private final List<AtlasEntity> entitiesUpdated = new ArrayList<>();
private final Map<AtlasObjectId, AtlasEntityType> entityVsType = new HashMap<>(); private final Map<String, AtlasEntityType> entityVsType = new HashMap<>();
private final Map<AtlasObjectId, AtlasVertex> entityVsVertex = new HashMap<>(); private final Map<String, AtlasVertex> entityVsVertex = new HashMap<>();
private final Map<String, String> guidAssignments = new HashMap<>();
public EntityMutationContext(final EntityGraphDiscoveryContext context) { public EntityMutationContext(final EntityGraphDiscoveryContext context) {
this.context = context; this.context = context;
} }
public void addCreated(AtlasEntity entity, AtlasEntityType type, AtlasVertex atlasVertex) { public void addCreated(String internalGuid, AtlasEntity entity, AtlasEntityType type, AtlasVertex atlasVertex) {
AtlasObjectId objId = entity.getAtlasObjectId();
entitiesCreated.add(entity); entitiesCreated.add(entity);
entityVsType.put(objId, type); entityVsType.put(entity.getGuid(), type);
entityVsVertex.put(objId, atlasVertex); entityVsVertex.put(entity.getGuid(), atlasVertex);
if (!StringUtils.equals(internalGuid, entity.getGuid())) {
guidAssignments.put(internalGuid, entity.getGuid());
entityVsVertex.put(internalGuid, atlasVertex);
}
} }
public void addUpdated(AtlasEntity entity, AtlasEntityType type, AtlasVertex atlasVertex) { public void addUpdated(AtlasEntity entity, AtlasEntityType type, AtlasVertex atlasVertex) {
AtlasObjectId objId = entity.getAtlasObjectId();
entitiesUpdated.add(entity); entitiesUpdated.add(entity);
entityVsType.put(objId, type); entityVsType.put(entity.getGuid(), type);
entityVsVertex.put(objId, atlasVertex); entityVsVertex.put(entity.getGuid(), atlasVertex);
} }
public EntityGraphDiscoveryContext getDiscoveryContext() { public EntityGraphDiscoveryContext getDiscoveryContext() {
...@@ -64,21 +69,15 @@ public class EntityMutationContext { ...@@ -64,21 +69,15 @@ public class EntityMutationContext {
return entitiesUpdated; return entitiesUpdated;
} }
public AtlasEntityType getType(AtlasEntity entity) { public Map<String, String> getGuidAssignments() {
return entityVsType.get(entity.getAtlasObjectId()); return guidAssignments;
}
public AtlasType getType(AtlasObjectId entityId) {
return entityVsType.get(entityId);
} }
public AtlasVertex getVertex(AtlasEntity entity) { public AtlasEntityType getType(String guid) {
return entityVsVertex.get(entity.getAtlasObjectId()); return entityVsType.get(guid);
} }
public AtlasVertex getVertex(AtlasObjectId entityId) { public AtlasVertex getVertex(String guid) { return entityVsVertex.get(guid); }
return entityVsVertex.get(entityId);
}
@Override @Override
......
...@@ -28,5 +28,5 @@ public interface EntityStream { ...@@ -28,5 +28,5 @@ public interface EntityStream {
void reset(); void reset();
AtlasEntity getById(AtlasObjectId id); AtlasEntity getByGuid(String guid);
} }
...@@ -17,11 +17,9 @@ ...@@ -17,11 +17,9 @@
*/ */
package org.apache.atlas.repository.store.graph.v1; package org.apache.atlas.repository.store.graph.v1;
import com.google.common.base.Optional;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.repository.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graph.GraphHelper; import org.apache.atlas.repository.graph.GraphHelper;
import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
...@@ -29,93 +27,53 @@ import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext; ...@@ -29,93 +27,53 @@ import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
import org.apache.atlas.repository.store.graph.EntityResolver; import org.apache.atlas.repository.store.graph.EntityResolver;
import org.apache.atlas.typesystem.exception.EntityNotFoundException; import org.apache.atlas.typesystem.exception.EntityNotFoundException;
import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.persistence.Id;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class IDBasedEntityResolver implements EntityResolver { public class IDBasedEntityResolver implements EntityResolver {
private static final Logger LOG = LoggerFactory.getLogger(IDBasedEntityResolver.class);
private final GraphHelper graphHelper = GraphHelper.getInstance();
private final Map<String, AtlasEntity> idToEntityMap = new HashMap<>();
private EntityGraphDiscoveryContext context;
@Override private final GraphHelper graphHelper = GraphHelper.getInstance();
public void init(EntityGraphDiscoveryContext context) throws AtlasBaseException {
this.context = context;
for (AtlasEntity entity : context.getRootEntities()) {
idToEntityMap.put(entity.getGuid(), entity);
}
}
public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException { public EntityGraphDiscoveryContext resolveEntityReferences(EntityGraphDiscoveryContext context) throws AtlasBaseException {
if (context == null) { if (context == null) {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Entity resolver not initialized"); throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "IDBasedEntityResolver.resolveEntityReferences(): context is null");
} }
List<AtlasObjectId> resolvedReferences = new ArrayList<>(); EntityStream entityStream = context.getEntityStream();
for (AtlasObjectId objId : context.getUnresolvedIds()) { for (String guid : context.getReferencedGuids()) {
if (objId.isAssignedGuid()) { if (AtlasEntity.isAssigned(guid)) { // validate in graph repo that given guid exists
//validate in graph repo that given guid, typename exists AtlasVertex vertex = resolveGuid(guid);
Optional<AtlasVertex> vertex = resolveGuid(objId);
if (vertex.isPresent()) { context.addResolvedGuid(guid, vertex);
context.addResolvedId(objId, vertex.get()); } else if (entityStream.getByGuid(guid) != null) { //check if entity stream have this reference id
resolvedReferences.add(objId); context.addLocalGuidReference(guid);
}
} else { } else {
//check if root references have this temporary id throw new AtlasBaseException(AtlasErrorCode.REFERENCED_ENTITY_NOT_FOUND, guid);
if (!idToEntityMap.containsKey(objId.getGuid()) ) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, objId.toString());
}
resolvedReferences.add(objId);
}
}
context.removeUnResolvedIds(resolvedReferences);
//Resolve root references
for (AtlasEntity entity : context.getRootEntities()) {
AtlasObjectId objId = entity.getAtlasObjectId();
if (!context.isResolvedId(objId) && AtlasEntity.isAssigned(entity.getGuid())) {
Optional<AtlasVertex> vertex = resolveGuid(objId);
if (vertex.isPresent()) {
context.addResolvedId(objId, vertex.get());
context.removeUnResolvedId(objId);
}
} }
} }
return context; return context;
} }
private Optional<AtlasVertex> resolveGuid(AtlasObjectId objId) throws AtlasBaseException { private AtlasVertex resolveGuid(String guid) throws AtlasBaseException {
//validate in graph repo that given guid, typename exists //validate in graph repo that given guid, typename exists
AtlasVertex vertex = null; AtlasVertex vertex = null;
try { try {
vertex = graphHelper.findVertex(Constants.GUID_PROPERTY_KEY, objId.getGuid(), vertex = graphHelper.findVertex(Constants.GUID_PROPERTY_KEY, guid,
Constants.TYPE_NAME_PROPERTY_KEY, objId.getTypeName(), Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name());
Constants.STATE_PROPERTY_KEY, Id.EntityState.ACTIVE.name());
} catch (EntityNotFoundException e) { } catch (EntityNotFoundException e) {
//Ignore //Ignore
} }
if ( vertex != null ) {
return Optional.of(vertex); if (vertex != null) {
return vertex;
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, objId.getGuid()); throw new AtlasBaseException(AtlasErrorCode.REFERENCED_ENTITY_NOT_FOUND, guid);
} }
} }
@Override
public void cleanUp() throws AtlasBaseException {
idToEntityMap.clear();
this.context = null;
}
} }
...@@ -27,14 +27,11 @@ import java.util.Map; ...@@ -27,14 +27,11 @@ import java.util.Map;
public class InMemoryMapEntityStream implements EntityStream { public class InMemoryMapEntityStream implements EntityStream {
private final Map<AtlasObjectId, AtlasEntity> entities = new HashMap<>(); private final Map<String, AtlasEntity> entities;
private Iterator<Map.Entry<AtlasObjectId, AtlasEntity>> iterator; private Iterator<Map.Entry<String, AtlasEntity>> iterator;
public InMemoryMapEntityStream(Map<String, AtlasEntity> entityMap) {
for (AtlasEntity entity : entityMap.values()) {
entities.put(entity.getAtlasObjectId(), entity);
}
public InMemoryMapEntityStream(Map<String, AtlasEntity> entities) {
this.entities = entities;
this.iterator = entities.entrySet().iterator(); this.iterator = entities.entrySet().iterator();
} }
...@@ -54,7 +51,7 @@ public class InMemoryMapEntityStream implements EntityStream { ...@@ -54,7 +51,7 @@ public class InMemoryMapEntityStream implements EntityStream {
} }
@Override @Override
public AtlasEntity getById(final AtlasObjectId id) { public AtlasEntity getByGuid(final String guid) {
return entities.get(id); return entities.get(guid);
} }
} }
...@@ -18,9 +18,6 @@ ...@@ -18,9 +18,6 @@
package org.apache.atlas.repository.store.graph.v1; package org.apache.atlas.repository.store.graph.v1;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.type.AtlasEntityType;
public interface InstanceGraphMapper<T> { public interface InstanceGraphMapper<T> {
...@@ -31,9 +28,5 @@ public interface InstanceGraphMapper<T> { ...@@ -31,9 +28,5 @@ public interface InstanceGraphMapper<T> {
* @return the value that was mapped to the vertex * @return the value that was mapped to the vertex
* @throws AtlasBaseException * @throws AtlasBaseException
*/ */
T toGraph(GraphMutationContext ctx) throws AtlasBaseException; T toGraph(AttributeMutationContext ctx, EntityMutationContext context) throws AtlasBaseException;
void cleanUp() throws AtlasBaseException;
} }
/**
* 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.base.Optional;
import com.google.inject.Inject;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.AtlasException;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
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.type.AtlasMapType;
import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static org.apache.atlas.repository.graph.GraphHelper.string;
public class MapVertexMapper implements InstanceGraphMapper<Map> {
private DeleteHandlerV1 deleteHandler;
private static final Logger LOG = LoggerFactory.getLogger(MapVertexMapper.class);
private StructVertexMapper structVertexMapper;
@Inject
public MapVertexMapper(DeleteHandlerV1 deleteHandler) {
this.deleteHandler = deleteHandler;
}
void init(StructVertexMapper structVertexMapper) {
this.structVertexMapper = structVertexMapper;
}
@Override
public Map<String, Object> toGraph(GraphMutationContext ctx) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("Mapping instance to vertex {} for map type {}", string(ctx.getReferringVertex()), ctx.getAttrType().getTypeName());
}
@SuppressWarnings("unchecked") Map<Object, Object> newVal =
(Map<Object, Object>) ctx.getValue();
boolean newAttributeEmpty = MapUtils.isEmpty(newVal);
Map<String, Object> currentMap = new HashMap<>();
Map<String, Object> newMap = new HashMap<>();
AtlasMapType mapType = (AtlasMapType) ctx.getAttrType();
try {
List<String> currentKeys = GraphHelper.getListProperty(ctx.getReferringVertex(), ctx.getVertexPropertyKey());
if (currentKeys != null && !currentKeys.isEmpty()) {
for (String key : currentKeys) {
String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(ctx.getVertexPropertyKey(), key);
Object propertyValueForKey = getMapValueProperty(mapType.getValueType(), ctx.getReferringVertex(), propertyNameForKey);
currentMap.put(key, propertyValueForKey);
}
}
if (!newAttributeEmpty) {
for (Map.Entry<Object, Object> entry : newVal.entrySet()) {
String keyStr = entry.getKey().toString();
String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(ctx.getVertexPropertyKey(), keyStr);
Optional<AtlasEdge> existingEdge = getEdgeIfExists(mapType, currentMap, keyStr);
GraphMutationContext mapCtx = new GraphMutationContext.Builder(ctx.getOp(), ctx.getAttribute(), mapType.getValueType(), entry.getValue())
.referringVertex(ctx.getReferringVertex())
.edge(existingEdge)
.vertexProperty(propertyNameForKey).build();
//Add/Update/Remove property value
Object newEntry = structVertexMapper.mapCollectionElementsToVertex(mapCtx);
MapVertexMapper.setMapValueProperty(mapType.getValueType(), ctx.getReferringVertex(), propertyNameForKey, newEntry);
newMap.put(keyStr, newEntry);
}
}
Map<String, Object> finalMap =
removeUnusedMapEntries(ctx.getParentType(), mapType, ctx.getAttributeDef(), ctx.getReferringVertex(), ctx.getVertexPropertyKey(), currentMap, newMap);
Set<String> newKeys = new HashSet<>(newMap.keySet());
newKeys.addAll(finalMap.keySet());
// for dereference on way out
GraphHelper.setListProperty(ctx.getReferringVertex(), ctx.getVertexPropertyKey(), new ArrayList<>(newKeys));
} catch (AtlasException e) {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, e);
}
if (LOG.isDebugEnabled()) {
LOG.debug("Map values set in vertex {} {}", mapType.getTypeName(), newMap);
}
return newMap;
}
@Override
public void cleanUp() throws AtlasBaseException {
}
public static Object getMapValueProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName) {
String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
if (AtlasGraphUtilsV1.isReference(elementType)) {
return instanceVertex.getProperty(actualPropertyName, AtlasEdge.class);
}
else {
return instanceVertex.getProperty(actualPropertyName, String.class).toString();
}
}
public static void setMapValueProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName, Object value) {
String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
if (AtlasGraphUtilsV1.isReference(elementType)) {
instanceVertex.setPropertyFromElementId(actualPropertyName, (AtlasEdge)value);
}
else {
instanceVertex.setProperty(actualPropertyName, value);
}
}
//Remove unused entries from map
private Map<String, Object> removeUnusedMapEntries(
AtlasStructType entityType,
AtlasMapType mapType, AtlasAttributeDef attributeDef,
AtlasVertex instanceVertex, String propertyName,
Map<String, Object> currentMap,
Map<String, Object> newMap)
throws AtlasException, AtlasBaseException {
Map<String, Object> additionalMap = new HashMap<>();
for (String currentKey : currentMap.keySet()) {
boolean shouldDeleteKey = !newMap.containsKey(currentKey);
if (AtlasGraphUtilsV1.isReference(mapType.getValueType())) {
//Delete the edge reference if its not part of new edges created/updated
AtlasEdge currentEdge = (AtlasEdge)currentMap.get(currentKey);
if (!newMap.values().contains(currentEdge)) {
boolean deleteChildReferences = StructVertexMapper.shouldManageChildReferences(entityType, attributeDef.getName());
boolean deleted =
deleteHandler.deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), deleteChildReferences, true);
if (!deleted) {
additionalMap.put(currentKey, currentEdge);
shouldDeleteKey = false;
}
}
}
if (shouldDeleteKey) {
String propertyNameForKey = GraphHelper.getQualifiedNameForMapKey(propertyName, currentKey);
GraphHelper.setProperty(instanceVertex, propertyNameForKey, null);
}
}
return additionalMap;
}
private Optional<AtlasEdge> getEdgeIfExists(AtlasMapType mapType, Map<String, Object> currentMap, String keyStr) {
Optional<AtlasEdge> existingEdge = Optional.absent();
if ( AtlasGraphUtilsV1.isReference(mapType.getValueType()) ) {
if ( currentMap.get(keyStr) != null) {
existingEdge = Optional.of((AtlasEdge) currentMap.get(keyStr));
}
}
return existingEdge;
}
}
...@@ -765,7 +765,7 @@ public class DefaultMetadataServiceTest { ...@@ -765,7 +765,7 @@ public class DefaultMetadataServiceTest {
Referenceable dbDef = InstanceSerialization.fromJsonReferenceable(dbDefJson, true); Referenceable dbDef = InstanceSerialization.fromJsonReferenceable(dbDefJson, true);
Assert.assertNotEquals(dbId, (((Id) tableDefinitionActual.get("database"))._getId())); Assert.assertNotEquals(dbId, (((Id) tableDefinitionActual.get("database"))._getId()));
Assert.assertEquals(dbDef.getId()._getId(), (((Id) tableDefinitionActual.get("database"))._getId())); */ Assert.assertEquals(dbDef.getObjectId()._getId(), (((Id) tableDefinitionActual.get("database"))._getId())); */
} }
......
...@@ -341,7 +341,7 @@ public class QuickStartV2 { ...@@ -341,7 +341,7 @@ public class QuickStartV2 {
private AtlasEntity createInstance(AtlasEntity entity, String[] traitNames) throws Exception { private AtlasEntity createInstance(AtlasEntity entity, String[] traitNames) throws Exception {
AtlasEntity ret = null; AtlasEntity ret = null;
EntityMutationResponse response = entitiesClient.createEntity(entity); EntityMutationResponse response = entitiesClient.createEntity(new AtlasEntityWithExtInfo(entity));
List<AtlasEntityHeader> entities = response.getEntitiesByOperation(EntityOperation.CREATE); List<AtlasEntityHeader> entities = response.getEntitiesByOperation(EntityOperation.CREATE);
if (CollectionUtils.isNotEmpty(entities)) { if (CollectionUtils.isNotEmpty(entities)) {
...@@ -422,7 +422,7 @@ public class QuickStartV2 { ...@@ -422,7 +422,7 @@ public class QuickStartV2 {
entity.setAttribute("retention", System.currentTimeMillis()); entity.setAttribute("retention", System.currentTimeMillis());
entity.setAttribute("db", db.getAtlasObjectId()); entity.setAttribute("db", db.getAtlasObjectId());
entity.setAttribute("sd", sd.getAtlasObjectId()); entity.setAttribute("sd", sd.getAtlasObjectId());
entity.setAttribute("columns", getObjectIds(columns)); entity.setAttribute("columns", AtlasTypeUtil.toObjectIds(columns));
return createInstance(entity, traitNames); return createInstance(entity, traitNames);
} }
...@@ -563,18 +563,4 @@ public class QuickStartV2 { ...@@ -563,18 +563,4 @@ public class QuickStartV2 {
AtlasEntity tableEntity = entitiesClient.getEntityByAttribute(TABLE_TYPE, attributes).getEntity(); AtlasEntity tableEntity = entitiesClient.getEntityByAttribute(TABLE_TYPE, attributes).getEntity();
return tableEntity.getGuid(); return tableEntity.getGuid();
} }
private Collection<AtlasObjectId> getObjectIds(Collection<AtlasEntity> entities) {
List<AtlasObjectId> ret = new ArrayList<>();
if (CollectionUtils.isNotEmpty(entities)) {
for (AtlasEntity entity : entities) {
if (entity != null) {
ret.add(entity.getAtlasObjectId());
}
}
}
return ret;
}
} }
...@@ -60,11 +60,11 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -60,11 +60,11 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
if (v1Obj instanceof Id) { if (v1Obj instanceof Id) {
Id id = (Id) v1Obj; Id id = (Id) v1Obj;
ret = new AtlasObjectId(id.getTypeName(), id._getId()); ret = new AtlasObjectId(id._getId(), id.getTypeName());
} else if (v1Obj instanceof IReferenceableInstance) { } else if (v1Obj instanceof IReferenceableInstance) {
IReferenceableInstance entRef = (IReferenceableInstance) v1Obj; IReferenceableInstance entRef = (IReferenceableInstance) v1Obj;
ret = new AtlasObjectId(entRef.getTypeName(), entRef.getId()._getId()); ret = new AtlasObjectId(entRef.getId()._getId(), entRef.getTypeName());
if (!context.entityExists(ret.getGuid())) { if (!context.entityExists(ret.getGuid())) {
Map<String, Object> v1Attribs = null; Map<String, Object> v1Attribs = null;
......
...@@ -51,10 +51,10 @@ AtlasObjectIdConverter extends AtlasAbstractFormatConverter { ...@@ -51,10 +51,10 @@ AtlasObjectIdConverter extends AtlasAbstractFormatConverter {
if (v1Obj != null) { if (v1Obj != null) {
if (v1Obj instanceof Id) { if (v1Obj instanceof Id) {
Id id = (Id) v1Obj; Id id = (Id) v1Obj;
ret = new AtlasObjectId(id.getTypeName(), id._getId()); ret = new AtlasObjectId(id._getId(), id.getTypeName());
} else if (v1Obj instanceof IReferenceableInstance) { } else if (v1Obj instanceof IReferenceableInstance) {
IReferenceableInstance entity = (IReferenceableInstance) v1Obj; IReferenceableInstance entity = (IReferenceableInstance) v1Obj;
ret = new AtlasObjectId(entity.getTypeName(), entity.getId()._getId()); ret = new AtlasObjectId(entity.getId()._getId(), entity.getTypeName());
} }
} }
return ret; return ret;
......
...@@ -20,15 +20,16 @@ package org.apache.atlas.web.rest; ...@@ -20,15 +20,16 @@ package org.apache.atlas.web.rest;
import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasClient;
import org.apache.atlas.AtlasErrorCode; import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.AtlasException; import org.apache.atlas.AtlasException;
import org.apache.atlas.CreateUpdateEntitiesResult;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.ClassificationAssociateRequest; import org.apache.atlas.model.instance.ClassificationAssociateRequest;
import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.AtlasEntityStore;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStream;
import org.apache.atlas.repository.store.graph.v1.EntityStream;
import org.apache.atlas.services.MetadataService; import org.apache.atlas.services.MetadataService;
import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.web.adapters.AtlasInstanceRestAdapters; import org.apache.atlas.web.adapters.AtlasInstanceRestAdapters;
import org.apache.atlas.web.util.Servlets; import org.apache.atlas.web.util.Servlets;
...@@ -50,13 +51,9 @@ import javax.ws.rs.Produces; ...@@ -50,13 +51,9 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.apache.atlas.web.adapters.AtlasInstanceRestAdapters.toAtlasBaseException; import static org.apache.atlas.web.adapters.AtlasInstanceRestAdapters.toAtlasBaseException;
import static org.apache.atlas.web.adapters.AtlasInstanceRestAdapters.toEntityMutationResponse;
@Path("v2/entities") @Path("v2/entities")
...@@ -81,101 +78,6 @@ public class EntitiesREST { ...@@ -81,101 +78,6 @@ public class EntitiesREST {
this.restAdapters = restAdapters; this.restAdapters = restAdapters;
} }
/*******
* Entity Creation/Updation if it already exists in ATLAS
* An existing entity is matched by its guid if supplied or by its unique attribute eg: qualifiedName
* Any associations like Classifications, Business Terms will have to be handled through the respective APIs
*******/
@POST
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse createOrUpdate(Map<String, AtlasEntity> entities) throws AtlasBaseException {
EntityMutationResponse response = null;
ITypedReferenceableInstance[] entitiesInOldFormat = restAdapters.getITypedReferenceables(entities.values());
try {
final CreateUpdateEntitiesResult result = metadataService.updateEntities(entitiesInOldFormat);
response = toEntityMutationResponse(result);
} catch (AtlasException e) {
LOG.error("Exception while getting a typed reference for the entity ", e);
throw AtlasInstanceRestAdapters.toAtlasBaseException(e);
}
return response;
}
/*******
* Entity Updation - Allows full update of the specified entities.
* Any associations like Classifications, Business Terms will have to be handled through the respective APIs
* Null updates are supported i.e Set an attribute value to Null if its an optional attribute
*******/
@PUT
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse update(Map<String, AtlasEntity> entities) throws AtlasBaseException {
return createOrUpdate(entities);
}
@GET
@Path("/guids")
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasEntity.AtlasEntities getById(@QueryParam("guid") List<String> guids) throws AtlasBaseException {
if (CollectionUtils.isEmpty(guids)) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guids);
}
AtlasEntity.AtlasEntities entities = new AtlasEntity.AtlasEntities();
List<AtlasEntity> entityList = new ArrayList<>();
for (String guid : guids) {
try {
ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid);
Map<String, AtlasEntity> entityRet = restAdapters.getAtlasEntity(ref);
addToEntityList(entityList, entityRet.values());
} catch (AtlasException e) {
throw toAtlasBaseException(e);
}
}
entities.setList(entityList);
return entities;
}
private void addToEntityList(final List<AtlasEntity> entityList, final Collection<AtlasEntity> values) {
for (AtlasEntity val : values) {
if ( !entityList.contains(val)) {
entityList.add(val);
}
}
}
/*******
* Entity Delete
*******/
@DELETE
@Path("/guids")
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse deleteById(@QueryParam("guid") final List<String> guids) throws AtlasBaseException {
if (CollectionUtils.isEmpty(guids)) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, guids);
}
try {
AtlasClient.EntityResult result = metadataService.deleteEntities(guids);
return toEntityMutationResponse(result);
} catch (AtlasException e) {
throw toAtlasBaseException(e);
}
}
/** /**
* Bulk API to associate a tag to multiple entities * Bulk API to associate a tag to multiple entities
* *
......
...@@ -25,6 +25,7 @@ import org.apache.atlas.RequestContext; ...@@ -25,6 +25,7 @@ import org.apache.atlas.RequestContext;
import org.apache.atlas.TestUtilsV2; import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct; import org.apache.atlas.model.instance.AtlasStruct;
...@@ -33,7 +34,9 @@ import org.apache.atlas.model.instance.EntityMutationResponse; ...@@ -33,7 +34,9 @@ import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.instance.EntityMutations; import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer;
import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.web.rest.EntitiesREST; import org.apache.atlas.web.rest.EntitiesREST;
import org.apache.atlas.web.rest.EntityREST; import org.apache.atlas.web.rest.EntityREST;
...@@ -49,16 +52,21 @@ import org.testng.annotations.Test; ...@@ -49,16 +52,21 @@ import org.testng.annotations.Test;
import javax.inject.Inject; import javax.inject.Inject;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@Guice(modules = {RepositoryMetadataModule.class}) @Guice(modules = {RepositoryMetadataModule.class})
public class TestEntitiesREST { public class TestEntitiesREST {
private static final Logger LOG = LoggerFactory.getLogger(TestEntitiesREST.class); private static final Logger LOG = LoggerFactory.getLogger(TestEntitiesREST.class);
@Inject @Inject
AtlasTypeRegistry typeRegistry;
@Inject
private AtlasTypeDefStore typeStore; private AtlasTypeDefStore typeStore;
@Inject @Inject
...@@ -69,10 +77,6 @@ public class TestEntitiesREST { ...@@ -69,10 +77,6 @@ public class TestEntitiesREST {
private List<String> createdGuids = new ArrayList<>(); private List<String> createdGuids = new ArrayList<>();
private Map<String, AtlasEntity> dbEntityMap;
private Map<String, AtlasEntity> tableEntityMap;
private AtlasEntity dbEntity; private AtlasEntity dbEntity;
private AtlasEntity tableEntity; private AtlasEntity tableEntity;
...@@ -81,17 +85,22 @@ public class TestEntitiesREST { ...@@ -81,17 +85,22 @@ public class TestEntitiesREST {
@BeforeClass @BeforeClass
public void setUp() throws Exception { public void setUp() throws Exception {
AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes(); AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineHiveTypes() };
typeStore.createTypesDef(typesDef);
dbEntityMap = TestUtilsV2.createDBEntity();
dbEntity = dbEntityMap.values().iterator().next();
tableEntityMap = TestUtilsV2.createTableEntity(dbEntity.getGuid()); for (AtlasTypesDef typesDef : testTypesDefs) {
tableEntity = tableEntityMap.values().iterator().next(); AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); if (!typesToCreate.isEmpty()) {
typeStore.createTypesDef(typesToCreate);
}
}
dbEntity = TestUtilsV2.createDBEntity();
tableEntity = TestUtilsV2.createTableEntity(dbEntity);
final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity);
columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }}; columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }};
tableEntity.setAttribute("columns", columns); tableEntity.setAttribute("columns", getObjIdList(columns));
} }
@AfterMethod @AfterMethod
...@@ -106,11 +115,15 @@ public class TestEntitiesREST { ...@@ -106,11 +115,15 @@ public class TestEntitiesREST {
@Test @Test
public void testCreateOrUpdateEntities() throws Exception { public void testCreateOrUpdateEntities() throws Exception {
Map<String, AtlasEntity> entities = new HashMap<>(); AtlasEntitiesWithExtInfo entities = new AtlasEntitiesWithExtInfo();
entities.put(dbEntity.getGuid(), dbEntity);
entities.put(tableEntity.getGuid(), tableEntity);
EntityMutationResponse response = entitiesREST.createOrUpdate(entities); entities.addEntity(dbEntity);
entities.addEntity(tableEntity);
for (AtlasEntity column : columns) {
entities.addReferredEntity(column);
}
EntityMutationResponse response = entityREST.createOrUpdate(entities);
List<AtlasEntityHeader> guids = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); List<AtlasEntityHeader> guids = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
Assert.assertNotNull(guids); Assert.assertNotNull(guids);
...@@ -137,23 +150,24 @@ public class TestEntitiesREST { ...@@ -137,23 +150,24 @@ public class TestEntitiesREST {
public void testUpdateWithSerializedEntities() throws Exception { public void testUpdateWithSerializedEntities() throws Exception {
//Check with serialization and deserialization of entity attributes for the case //Check with serialization and deserialization of entity attributes for the case
// where attributes which are de-serialized into a map // where attributes which are de-serialized into a map
Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity(); AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
AtlasEntity dbEntity = dbEntityMap.values().iterator().next(); AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
Map<String, AtlasEntity> tableEntityMap = TestUtilsV2.createTableEntity(dbEntity.getGuid());
AtlasEntity tableEntity = tableEntityMap.values().iterator().next();
final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity);
List<AtlasEntity> columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }}; List<AtlasEntity> columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }};
tableEntity.setAttribute("columns", columns); tableEntity.setAttribute("columns", getObjIdList(columns));
AtlasEntity newDBEntity = serDeserEntity(dbEntity); AtlasEntity newDBEntity = serDeserEntity(dbEntity);
AtlasEntity newTableEntity = serDeserEntity(tableEntity); AtlasEntity newTableEntity = serDeserEntity(tableEntity);
Map<String, AtlasEntity> newEntities = new HashMap<>(); AtlasEntitiesWithExtInfo newEntities = new AtlasEntitiesWithExtInfo();
newEntities.put(newDBEntity.getGuid(), newDBEntity); newEntities.addEntity(newDBEntity);
newEntities.put(newTableEntity.getGuid(), newTableEntity); newEntities.addEntity(newTableEntity);
EntityMutationResponse response2 = entitiesREST.createOrUpdate(newEntities); for (AtlasEntity column : columns) {
newEntities.addReferredEntity(serDeserEntity(column));
}
EntityMutationResponse response2 = entityREST.createOrUpdate(newEntities);
List<AtlasEntityHeader> newGuids = response2.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); List<AtlasEntityHeader> newGuids = response2.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
Assert.assertNotNull(newGuids); Assert.assertNotNull(newGuids);
...@@ -163,8 +177,8 @@ public class TestEntitiesREST { ...@@ -163,8 +177,8 @@ public class TestEntitiesREST {
@Test(dependsOnMethods = "testCreateOrUpdateEntities") @Test(dependsOnMethods = "testCreateOrUpdateEntities")
public void testGetEntities() throws Exception { public void testGetEntities() throws Exception {
final AtlasEntity.AtlasEntities response = entitiesREST.getById(createdGuids); final AtlasEntitiesWithExtInfo response = entityREST.getByGuids(createdGuids);
final List<AtlasEntity> entities = response.getList(); final List<AtlasEntity> entities = response.getEntities();
Assert.assertNotNull(entities); Assert.assertNotNull(entities);
Assert.assertEquals(entities.size(), 3); Assert.assertEquals(entities.size(), 3);
...@@ -174,7 +188,7 @@ public class TestEntitiesREST { ...@@ -174,7 +188,7 @@ public class TestEntitiesREST {
@Test(dependsOnMethods = "testGetEntities") @Test(dependsOnMethods = "testGetEntities")
public void testDeleteEntities() throws Exception { public void testDeleteEntities() throws Exception {
final EntityMutationResponse response = entitiesREST.deleteById(createdGuids); final EntityMutationResponse response = entityREST.deleteByGuids(createdGuids);
final List<AtlasEntityHeader> entities = response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE); final List<AtlasEntityHeader> entities = response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE);
Assert.assertNotNull(entities); Assert.assertNotNull(entities);
...@@ -247,4 +261,14 @@ public class TestEntitiesREST { ...@@ -247,4 +261,14 @@ public class TestEntitiesREST {
AtlasEntity newEntity = mapper.readValue(entityJson, AtlasEntity.class); AtlasEntity newEntity = mapper.readValue(entityJson, AtlasEntity.class);
return newEntity; return newEntity;
} }
private List<AtlasObjectId> getObjIdList(Collection<AtlasEntity> entities) {
List<AtlasObjectId> ret = new ArrayList<>();
for (AtlasEntity entity : entities) {
ret.add(entity.getAtlasObjectId());
}
return ret;
}
} }
...@@ -22,6 +22,7 @@ import org.apache.atlas.RequestContext; ...@@ -22,6 +22,7 @@ import org.apache.atlas.RequestContext;
import org.apache.atlas.TestUtilsV2; import org.apache.atlas.TestUtilsV2;
import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasClassification;
import org.apache.atlas.model.instance.AtlasEntity; 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.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.instance.EntityMutationResponse;
...@@ -29,8 +30,8 @@ import org.apache.atlas.model.instance.EntityMutations; ...@@ -29,8 +30,8 @@ import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.model.typedef.AtlasTypesDef;
import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.graph.AtlasGraphProvider;
import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.store.AtlasTypeDefStore;
import org.apache.atlas.web.rest.EntitiesREST;
import org.apache.atlas.web.rest.EntityREST; import org.apache.atlas.web.rest.EntityREST;
import org.mockito.Mockito;
import org.testng.Assert; import org.testng.Assert;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeClass;
...@@ -39,6 +40,7 @@ import org.testng.annotations.Guice; ...@@ -39,6 +40,7 @@ import org.testng.annotations.Guice;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import javax.inject.Inject; import javax.inject.Inject;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
...@@ -53,9 +55,6 @@ public class TestEntityREST { ...@@ -53,9 +55,6 @@ public class TestEntityREST {
@Inject @Inject
private EntityREST entityREST; private EntityREST entityREST;
@Inject
private EntitiesREST entitiesREST;
private AtlasEntity dbEntity; private AtlasEntity dbEntity;
private AtlasClassification testClassification; private AtlasClassification testClassification;
...@@ -77,12 +76,9 @@ public class TestEntityREST { ...@@ -77,12 +76,9 @@ public class TestEntityREST {
} }
private void createTestEntity() throws Exception { private void createTestEntity() throws Exception {
Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity(); AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
AtlasEntity dbEntity = dbEntityMap.values().iterator().next();
dbEntityMap.put(dbEntity.getGuid(), dbEntity); final EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity));
final EntityMutationResponse response = entitiesREST.createOrUpdate(dbEntityMap);
Assert.assertNotNull(response); Assert.assertNotNull(response);
List<AtlasEntityHeader> entitiesMutated = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); List<AtlasEntityHeader> entitiesMutated = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
...@@ -158,10 +154,9 @@ public class TestEntityREST { ...@@ -158,10 +154,9 @@ public class TestEntityREST {
@Test @Test
public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception { public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception {
Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity(); AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
AtlasEntity dbEntity = dbEntityMap.values().iterator().next(); EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity));
EntityMutationResponse response = entitiesREST.createOrUpdate(dbEntityMap); String dbGuid = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0).getGuid();
String dbGuid = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0).getGuid();
Assert.assertTrue(AtlasEntity.isAssigned(dbGuid)); Assert.assertTrue(AtlasEntity.isAssigned(dbGuid));
...@@ -170,21 +165,35 @@ public class TestEntityREST { ...@@ -170,21 +165,35 @@ public class TestEntityREST {
dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName); dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName);
response = entityREST.partialUpdateByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, TestUtilsV2.NAME, prevDBName, dbEntity); response = entityREST.partialUpdateByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).get(0).getGuid(), dbGuid); Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).get(0).getGuid(), dbGuid);
//Get By unique attribute //Get By unique attribute
List<AtlasEntity> entities = entityREST.getByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, TestUtilsV2.NAME, updatedDBName); AtlasEntityWithExtInfo entity = entityREST.getByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, updatedDBName));
Assert.assertNotNull(entities); Assert.assertNotNull(entity);
Assert.assertNotNull(entities.get(0).getGuid()); Assert.assertNotNull(entity.getEntity().getGuid());
Assert.assertEquals(entities.get(0).getGuid(), dbGuid); Assert.assertEquals(entity.getEntity().getGuid(), dbGuid);
TestEntitiesREST.verifyAttributes(entities.get(0).getAttributes(), dbEntity.getAttributes()); TestEntitiesREST.verifyAttributes(entity.getEntity().getAttributes(), dbEntity.getAttributes());
final EntityMutationResponse deleteResponse = entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, TestUtilsV2.NAME, (String) dbEntity.getAttribute(TestUtilsV2.NAME)); final EntityMutationResponse deleteResponse = entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, (String) dbEntity.getAttribute(TestUtilsV2.NAME)));
Assert.assertNotNull(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE)); Assert.assertNotNull(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE));
Assert.assertEquals(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 1); Assert.assertEquals(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 1);
Assert.assertEquals(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).get(0).getGuid(), dbGuid); Assert.assertEquals(deleteResponse.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).get(0).getGuid(), dbGuid);
} }
private HttpServletRequest toHttpServletRequest(String attrName, String attrValue) {
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Map<String, String[]> paramsMap = toParametersMap(EntityREST.PREFIX_ATTR + attrName, attrValue);
Mockito.when(request.getParameterMap()).thenReturn(paramsMap);
return request;
}
private Map<String, String[]> toParametersMap(final String name, final String value) {
return new HashMap<String, String[]>() {{
put(name, new String[] { value });
}};
}
} }
...@@ -43,6 +43,7 @@ import org.apache.atlas.model.instance.AtlasEntityHeader; ...@@ -43,6 +43,7 @@ import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasStruct; import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.model.instance.EntityMutations; import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
import org.apache.atlas.model.typedef.AtlasClassificationDef; import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef; import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasEnumDef; import org.apache.atlas.model.typedef.AtlasEnumDef;
...@@ -74,6 +75,7 @@ import org.apache.atlas.typesystem.types.TypeUtils; ...@@ -74,6 +75,7 @@ import org.apache.atlas.typesystem.types.TypeUtils;
import org.apache.atlas.typesystem.types.utils.TypesUtil; import org.apache.atlas.typesystem.types.utils.TypesUtil;
import org.apache.atlas.utils.AuthenticationUtil; import org.apache.atlas.utils.AuthenticationUtil;
import org.apache.atlas.utils.ParamChecker; import org.apache.atlas.utils.ParamChecker;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.configuration.Configuration; import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.RandomStringUtils; import org.apache.commons.lang.RandomStringUtils;
import org.codehaus.jettison.json.JSONArray; import org.codehaus.jettison.json.JSONArray;
...@@ -286,13 +288,13 @@ public abstract class BaseResourceIT { ...@@ -286,13 +288,13 @@ public abstract class BaseResourceIT {
EntityMutationResponse entity = null; EntityMutationResponse entity = null;
try { try {
if (!update) { if (!update) {
entity = entitiesClientV2.createEntity(atlasEntity); entity = entitiesClientV2.createEntity(new AtlasEntityWithExtInfo(atlasEntity));
assertNotNull(entity); assertNotNull(entity);
assertNotNull(entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE)); assertNotNull(entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE));
assertTrue(entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).size() > 0); assertTrue(entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).size() > 0);
return entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0); return entity.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0);
} else { } else {
entity = entitiesClientV2.updateEntity(atlasEntity); entity = entitiesClientV2.updateEntity(new AtlasEntityWithExtInfo(atlasEntity));
assertNotNull(entity); assertNotNull(entity);
assertNotNull(entity.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE)); assertNotNull(entity.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE));
assertTrue(entity.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).size() > 0); assertTrue(entity.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).size() > 0);
......
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