Commit d8c2a10e by Suma Shivaprasad Committed by Madhan Neethiraj

ATLAS-1522: V2 entity API changes to accept only AtlasObjectId for child references

parent 02cf8c48
...@@ -32,7 +32,9 @@ import org.apache.hadoop.security.UserGroupInformation; ...@@ -32,7 +32,9 @@ import org.apache.hadoop.security.UserGroupInformation;
import javax.ws.rs.HttpMethod; import javax.ws.rs.HttpMethod;
import javax.ws.rs.core.MultivaluedMap; import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import static org.apache.atlas.model.instance.AtlasEntity.AtlasEntities; import static org.apache.atlas.model.instance.AtlasEntity.AtlasEntities;
...@@ -43,12 +45,11 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient { ...@@ -43,12 +45,11 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient {
private static final APIInfo GET_ENTITY_BY_GUID = new APIInfo(ENTITY_API + "guid/", HttpMethod.GET, Response.Status.OK); private static final APIInfo GET_ENTITY_BY_GUID = new APIInfo(ENTITY_API + "guid/", HttpMethod.GET, Response.Status.OK);
private static final APIInfo GET_ENTITY_WITH_ASSOCIATION_BY_GUID = new APIInfo(ENTITY_API + "guid/%s/associations", HttpMethod.GET, Response.Status.OK); private static final APIInfo GET_ENTITY_WITH_ASSOCIATION_BY_GUID = new APIInfo(ENTITY_API + "guid/%s/associations", HttpMethod.GET, Response.Status.OK);
private static final APIInfo CREATE_ENTITY = new APIInfo(ENTITY_API, HttpMethod.POST, Response.Status.OK); private static final APIInfo CREATE_ENTITY = new APIInfo(ENTITIES_API, HttpMethod.POST, Response.Status.OK);
private static final APIInfo UPDATE_ENTITY = CREATE_ENTITY; private static final APIInfo UPDATE_ENTITY = CREATE_ENTITY;
private static final APIInfo GET_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.GET, Response.Status.OK); private static final APIInfo GET_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.GET, Response.Status.OK);
private static final APIInfo UPDATE_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.PUT, Response.Status.OK); private static final APIInfo UPDATE_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.PUT, Response.Status.OK);
private static final APIInfo DELETE_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.DELETE, Response.Status.OK); private static final APIInfo DELETE_ENTITY_BY_ATTRIBUTE = new APIInfo(ENTITY_API + "uniqueAttribute/type/%s/attribute/%s", HttpMethod.DELETE, Response.Status.OK);
private static final APIInfo UPDATE_ENTITY_BY_GUID = new APIInfo(ENTITY_API + "guid/", HttpMethod.PUT, Response.Status.OK);
private static final APIInfo DELETE_ENTITY_BY_GUID = new APIInfo(ENTITY_API + "guid/", HttpMethod.DELETE, Response.Status.OK); private static final APIInfo DELETE_ENTITY_BY_GUID = new APIInfo(ENTITY_API + "guid/", HttpMethod.DELETE, Response.Status.OK);
private static final APIInfo DELETE_ENTITY_BY_GUIDS = new APIInfo(ENTITIES_API + "guids/", HttpMethod.DELETE, Response.Status.OK); private static final APIInfo DELETE_ENTITY_BY_GUIDS = new APIInfo(ENTITIES_API + "guids/", HttpMethod.DELETE, Response.Status.OK);
private static final APIInfo GET_CLASSIFICATIONS = new APIInfo(ENTITY_API + "guid/%s/classifications", HttpMethod.GET, Response.Status.OK); private static final APIInfo GET_CLASSIFICATIONS = new APIInfo(ENTITY_API + "guid/%s/classifications", HttpMethod.GET, Response.Status.OK);
...@@ -113,16 +114,12 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient { ...@@ -113,16 +114,12 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient {
return callAPI(formatPathForPathParams(DELETE_ENTITY_BY_ATTRIBUTE, type, attribute), null, EntityMutationResponse.class, queryParams); return callAPI(formatPathForPathParams(DELETE_ENTITY_BY_ATTRIBUTE, type, attribute), null, EntityMutationResponse.class, queryParams);
} }
public EntityMutationResponse createEntity(AtlasEntity atlasEntity) throws AtlasServiceException { public EntityMutationResponse createEntity(final AtlasEntity atlasEntity) throws AtlasServiceException {
return callAPI(CREATE_ENTITY, atlasEntity, EntityMutationResponse.class); return callAPI(CREATE_ENTITY, new HashMap<String, AtlasEntity>() {{ put(atlasEntity.getGuid(), atlasEntity); }}, EntityMutationResponse.class);
} }
public EntityMutationResponse updateEntity(AtlasEntity atlasEntity) throws AtlasServiceException { public EntityMutationResponse updateEntity(final AtlasEntity atlasEntity) throws AtlasServiceException {
return callAPI(UPDATE_ENTITY, atlasEntity, EntityMutationResponse.class); return callAPI(UPDATE_ENTITY, new HashMap<String, AtlasEntity>() {{ put(atlasEntity.getGuid(), atlasEntity); }}, EntityMutationResponse.class);
}
public EntityMutationResponse updateEntity(String guid, AtlasEntity atlasEntity) throws AtlasServiceException {
return callAPI(UPDATE_ENTITY_BY_GUID, atlasEntity, EntityMutationResponse.class, guid);
} }
public AtlasEntity deleteEntityByGuid(String guid) throws AtlasServiceException { public AtlasEntity deleteEntityByGuid(String guid) throws AtlasServiceException {
...@@ -159,15 +156,11 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient { ...@@ -159,15 +156,11 @@ public class AtlasEntitiesClientV2 extends AtlasBaseClient {
return null; return null;
} }
public List<AtlasEntity> createEntities(List<AtlasEntity> atlasEntities) throws AtlasServiceException { public List<AtlasEntity> createEntities(Map<String, AtlasEntity> atlasEntities) throws AtlasServiceException {
return (List<AtlasEntity>)callAPI(CREATE_ENTITIES, atlasEntities, List.class); return (List<AtlasEntity>)callAPI(CREATE_ENTITIES, atlasEntities, List.class);
} }
public List<AtlasEntity> updateEntities(List<AtlasEntity> atlasEntities) throws AtlasServiceException { public List<AtlasEntity> updateEntities(Map<String, AtlasEntity> atlasEntities) throws AtlasServiceException {
return (List<AtlasEntity>)callAPI(UPDATE_ENTITIES, atlasEntities, List.class); return (List<AtlasEntity>)callAPI(UPDATE_ENTITIES, atlasEntities, List.class);
} }
public AtlasEntity.AtlasEntities searchEntities(SearchFilter searchFilter) throws AtlasServiceException {
return callAPI(GET_ENTITIES, AtlasEntity.AtlasEntities.class, searchFilter.getParams());
}
} }
...@@ -80,6 +80,8 @@ public enum AtlasErrorCode { ...@@ -80,6 +80,8 @@ public enum AtlasErrorCode {
INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(400, "ATLAS40018E", "Instance {0} with unique attribute {1} does not exist"), INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(400, "ATLAS40018E", "Instance {0} with unique attribute {1} does not exist"),
UNRESOLVED_REFERENCES_FOUND(400, "ATLAS40010E", "Unresolved references: byId={0}; byUniqueAttributes={1}"),
UNKNOWN_ATTRIBUTE(400, "ATLAS40019E", "Attribute {0} not found for type {1}"); UNKNOWN_ATTRIBUTE(400, "ATLAS40019E", "Attribute {0} not found for type {1}");
private String errorCode; private String errorCode;
......
...@@ -161,6 +161,41 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -161,6 +161,41 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
this.version = version; this.version = version;
} }
@JsonIgnore
public boolean isUnassigned() {
return isUnAssigned(guid);
}
@JsonIgnore
public boolean isAssigned() {
return isAssigned(guid);
}
@JsonIgnore
public static boolean isAssigned(String guid) {
try {
UUID.fromString(guid);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
@JsonIgnore
public static boolean isUnAssigned(String guid) {
return guid != null && guid.length() > 0 && guid.charAt(0) == '-';
}
private static String nextInternalId() {
return "-" + Long.toString(s_nextId.getAndIncrement());
}
@JsonIgnore
public AtlasObjectId getAtlasObjectId() {
return new AtlasObjectId(getTypeName(), getGuid());
}
@Override @Override
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
...@@ -233,44 +268,4 @@ public class AtlasEntity extends AtlasStruct implements Serializable { ...@@ -233,44 +268,4 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
super(list, startIndex, pageSize, totalCount, sortType, sortBy); super(list, startIndex, pageSize, totalCount, sortType, sortBy);
} }
} }
@JsonIgnore
public boolean validate(String id) {
try {
long l = Long.parseLong(id);
return l < 0;
} catch (NumberFormatException ne) {
return false;
}
}
@JsonIgnore
public boolean isUnassigned() {
return isUnAssigned(guid);
}
@JsonIgnore
public boolean isAssigned() {
return isAssigned(guid);
}
@JsonIgnore
public static boolean isAssigned(String guid) {
try {
UUID.fromString(guid);
} catch (IllegalArgumentException e) {
return false;
}
return true;
}
@JsonIgnore
public static boolean isUnAssigned(String guid) {
return guid != null && guid.length() > 0 && guid.charAt(0) == '-';
}
private String nextInternalId() {
return "-" + Long.toString(s_nextId.getAndIncrement());
}
} }
...@@ -73,6 +73,10 @@ public class AtlasEntityWithAssociations extends AtlasEntity implements Serializ ...@@ -73,6 +73,10 @@ public class AtlasEntityWithAssociations extends AtlasEntity implements Serializ
setClassifications(other != null ? other.getClassifications() : null); setClassifications(other != null ? other.getClassifications() : null);
} }
public AtlasEntityWithAssociations(AtlasEntity other) {
super(other);
}
@Override @Override
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
......
...@@ -30,10 +30,13 @@ import javax.xml.bind.annotation.XmlSeeAlso; ...@@ -30,10 +30,13 @@ import javax.xml.bind.annotation.XmlSeeAlso;
import org.apache.atlas.model.PList; import org.apache.atlas.model.PList;
import org.apache.atlas.model.SearchFilter.SortType; import org.apache.atlas.model.SearchFilter.SortType;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef; import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.annotate.JsonAutoDetect; import org.codehaus.jackson.annotate.JsonAutoDetect;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY; import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.PUBLIC_ONLY;
import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE; import static org.codehaus.jackson.annotate.JsonAutoDetect.Visibility.NONE;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.annotate.JsonSerialize;
...@@ -56,6 +59,12 @@ public class AtlasObjectId implements Serializable { ...@@ -56,6 +59,12 @@ public class AtlasObjectId implements Serializable {
private String guid; private String guid;
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, null);
} }
...@@ -120,6 +129,10 @@ public class AtlasObjectId implements Serializable { ...@@ -120,6 +129,10 @@ public class AtlasObjectId implements Serializable {
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 Map<String, Object> getUniqueAttributes() { public Map<String, Object> getUniqueAttributes() {
...@@ -130,6 +143,31 @@ public class AtlasObjectId implements Serializable { ...@@ -130,6 +143,31 @@ public class AtlasObjectId implements Serializable {
this.uniqueAttributes = uniqueAttributes; this.uniqueAttributes = uniqueAttributes;
} }
@JsonIgnore
public boolean isAssignedGuid() {
return isAssignedGuid;
}
@JsonIgnore
public boolean isUnAssignedGuid() {
return isUnAssignedGuid;
}
@JsonIgnore
public boolean isValid() {
if (StringUtils.isEmpty(typeName)) {
return false;
} else if (StringUtils.isNotEmpty(guid)) {
if (!isAssignedGuid && !isUnAssignedGuid) {
return false;
}
} else if (MapUtils.isEmpty(uniqueAttributes)) {
return false;
}
return true;
}
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
if (sb == null) { if (sb == null) {
sb = new StringBuilder(); sb = new StringBuilder();
......
...@@ -89,6 +89,34 @@ public class EntityMutationResponse { ...@@ -89,6 +89,34 @@ public class EntityMutationResponse {
return null; return null;
} }
@JsonIgnore
public AtlasEntityHeader getFirstCreatedEntityByTypeName(String typeName) {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
for (AtlasEntityHeader header : entitiesByOperation) {
if ( header.getTypeName().equals(typeName)) {
return header;
}
}
}
return null;
}
@JsonIgnore
public AtlasEntityHeader getFirstUpdatedEntityByTypeName(String typeName) {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
for (AtlasEntityHeader header : entitiesByOperation) {
if ( header.getTypeName().equals(typeName)) {
return header;
}
}
}
return null;
}
public void addEntity(EntityMutations.EntityOperation op, AtlasEntityHeader header) { public void addEntity(EntityMutations.EntityOperation op, AtlasEntityHeader header) {
if (entitiesMutated == null) { if (entitiesMutated == null) {
entitiesMutated = new HashMap<>(); entitiesMutated = new HashMap<>();
......
...@@ -193,7 +193,7 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -193,7 +193,7 @@ public class AtlasEntityType extends AtlasStructType {
if (obj != null) { if (obj != null) {
if (obj instanceof AtlasObjectId) { if (obj instanceof AtlasObjectId) {
AtlasObjectId objId = (AtlasObjectId ) obj; AtlasObjectId objId = (AtlasObjectId ) obj;
return validateAtlasObjectId(objId); return isAssignableFrom(objId);
} else { } else {
for (AtlasEntityType superType : superTypes) { for (AtlasEntityType superType : superTypes) {
if (!superType.isValidValue(obj)) { if (!superType.isValidValue(obj)) {
...@@ -240,7 +240,7 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -240,7 +240,7 @@ public class AtlasEntityType extends AtlasStructType {
if (obj != null) { if (obj != null) {
if (obj instanceof AtlasObjectId) { if (obj instanceof AtlasObjectId) {
AtlasObjectId objId = (AtlasObjectId ) obj; AtlasObjectId objId = (AtlasObjectId ) obj;
return validateAtlasObjectId(objId); return isAssignableFrom(objId);
} }
for (AtlasEntityType superType : superTypes) { for (AtlasEntityType superType : superTypes) {
...@@ -406,16 +406,10 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -406,16 +406,10 @@ public class AtlasEntityType extends AtlasStructType {
return ret == null ? Collections.<String, AtlasAttribute>emptyMap() : ret; return ret == null ? Collections.<String, AtlasAttribute>emptyMap() : ret;
} }
private boolean validateAtlasObjectId(AtlasObjectId objId) { boolean isAssignableFrom(AtlasObjectId objId) {
if (StringUtils.isEmpty(objId.getTypeName()) || StringUtils.isEmpty(objId.getGuid())) { boolean ret = objId.isValid() && (StringUtils.equals(objId.getTypeName(), getTypeName()) || isSuperTypeOf(objId.getTypeName()));
return false;
} else { return ret;
String typeName = objId.getTypeName();
if (!typeName.equals(getTypeName()) && !isSuperTypeOf(typeName)) {
return false;
}
}
return AtlasEntity.isAssigned(objId.getGuid()) || AtlasEntity.isUnAssigned((objId.getGuid()));
} }
public static class ForeignKeyReference { public static class ForeignKeyReference {
......
...@@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory; ...@@ -34,7 +34,6 @@ import org.slf4j.LoggerFactory;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
...@@ -481,6 +480,22 @@ public class AtlasStructType extends AtlasType { ...@@ -481,6 +480,22 @@ public class AtlasStructType extends AtlasType {
return qualifiedName; return qualifiedName;
} }
/*
* "isContainedAttribute" can not be computed and cached in the constructor - as structType is not fully
* populated at the time AtlasAttribute object is constructed.
*/
public boolean isContainedAttribute() {
if ( structType.isForeignKeyOnDeleteActionUpdate(attributeDef.getName()) ) {
return true;
}
if ( structType instanceof AtlasEntityType) {
return ((AtlasEntityType) structType).isMappedFromRefAttribute(attributeDef.getName());
}
return false;
}
public static String getQualifiedAttributeName(AtlasStructDef structDef, String attrName) { public 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);
......
...@@ -284,7 +284,9 @@ public final class TestUtilsV2 { ...@@ -284,7 +284,9 @@ public final class TestUtilsV2 {
public static final String PERSON_TYPE = "Person"; public static final String PERSON_TYPE = "Person";
public static final String EMPLOYEE_TYPE = "Employee"; public static final String EMPLOYEE_TYPE = "Employee";
public static AtlasEntity createDeptEg1() { public static Map<String, AtlasEntity> createDeptEg1() {
Map<String, AtlasEntity> deptEmpEntities = new HashMap<>();
AtlasEntity hrDept = new AtlasEntity(DEPARTMENT_TYPE); AtlasEntity hrDept = new AtlasEntity(DEPARTMENT_TYPE);
AtlasEntity john = new AtlasEntity(EMPLOYEE_TYPE); AtlasEntity john = new AtlasEntity(EMPLOYEE_TYPE);
...@@ -329,7 +331,8 @@ public final class TestUtilsV2 { ...@@ -329,7 +331,8 @@ public final class TestUtilsV2 {
julius.setAttribute("address", juliusAddr); julius.setAttribute("address", juliusAddr);
julius.setAttribute("subordinates", ImmutableList.of()); julius.setAttribute("subordinates", ImmutableList.of());
AtlasObjectId janeId = new AtlasObjectId(jane.getTypeName(), jane.getGuid()); AtlasObjectId janeId = jane.getAtlasObjectId();
AtlasObjectId johnId = john.getAtlasObjectId();
//TODO - Change to MANAGER_TYPE for JULIUS //TODO - Change to MANAGER_TYPE for JULIUS
AtlasObjectId maxId = new AtlasObjectId(EMPLOYEE_TYPE, max.getGuid()); AtlasObjectId maxId = new AtlasObjectId(EMPLOYEE_TYPE, max.getGuid());
...@@ -355,15 +358,20 @@ public final class TestUtilsV2 { ...@@ -355,15 +358,20 @@ public final class TestUtilsV2 {
john.setAttribute("manager", janeId); john.setAttribute("manager", janeId);
john.setAttribute("mentor", maxId); john.setAttribute("mentor", maxId);
hrDept.setAttribute("employees", ImmutableList.of(john, jane, julius, max)); hrDept.setAttribute("employees", ImmutableList.of(johnId, janeId, juliusId, maxId));
jane.setAttribute("subordinates", ImmutableList.of(john, max)); jane.setAttribute("subordinates", ImmutableList.of(johnId, maxId));
// Map<String, Integer> secClearanceLevelMap = new HashMap<>(); // Map<String, Integer> secClearanceLevelMap = new HashMap<>();
// secClearanceLevelMap.put("level", 1); // secClearanceLevelMap.put("level", 1);
// jane.setAttribute("SecurityClearance", secClearanceLevelMap); // jane.setAttribute("SecurityClearance", secClearanceLevelMap);
return hrDept; deptEmpEntities.put(jane.getGuid(), jane);
deptEmpEntities.put(john.getGuid(), john);
deptEmpEntities.put(julius.getGuid(), julius);
deptEmpEntities.put(max.getGuid(), max);
deptEmpEntities.put(deptId.getGuid(), hrDept);
return deptEmpEntities;
} }
public static final String DATABASE_TYPE = "hive_database"; public static final String DATABASE_TYPE = "hive_database";
...@@ -661,15 +669,20 @@ public final class TestUtilsV2 { ...@@ -661,15 +669,20 @@ public final class TestUtilsV2 {
return RandomStringUtils.randomAlphanumeric(10); return RandomStringUtils.randomAlphanumeric(10);
} }
public static AtlasEntity createDBEntity() { public static Map<String, AtlasEntity> createDBEntity() {
Map<String, AtlasEntity> ret = new HashMap<>();
AtlasEntity entity = new AtlasEntity(DATABASE_TYPE); AtlasEntity entity = new AtlasEntity(DATABASE_TYPE);
String dbName = RandomStringUtils.randomAlphanumeric(10); String dbName = RandomStringUtils.randomAlphanumeric(10);
entity.setAttribute(NAME, dbName); entity.setAttribute(NAME, dbName);
entity.setAttribute("description", "us db"); entity.setAttribute("description", "us db");
return entity;
ret.put(entity.getGuid(), entity);
return ret;
} }
public static AtlasEntity createTableEntity(String dbId) { public static Map<String, AtlasEntity> createTableEntity(String dbId) {
Map<String, AtlasEntity> ret = new HashMap<>();
AtlasEntity entity = new AtlasEntity(TABLE_TYPE); AtlasEntity entity = new AtlasEntity(TABLE_TYPE);
String tableName = RandomStringUtils.randomAlphanumeric(10); String tableName = RandomStringUtils.randomAlphanumeric(10);
entity.setAttribute(NAME, tableName); entity.setAttribute(NAME, tableName);
...@@ -688,10 +701,13 @@ public final class TestUtilsV2 { ...@@ -688,10 +701,13 @@ public final class TestUtilsV2 {
entity.setAttribute("parametersMap", new java.util.HashMap<String, String>() {{ entity.setAttribute("parametersMap", new java.util.HashMap<String, String>() {{
put("key1", "value1"); put("key1", "value1");
}}); }});
return entity;
ret.put(entity.getGuid(), entity);
return ret;
} }
public static AtlasEntity createColumnEntity(String tableId) { public static AtlasEntity createColumnEntity(String tableId) {
AtlasEntity entity = new AtlasEntity(COLUMN_TYPE); AtlasEntity entity = new AtlasEntity(COLUMN_TYPE);
entity.setAttribute(NAME, RandomStringUtils.randomAlphanumeric(10)); entity.setAttribute(NAME, RandomStringUtils.randomAlphanumeric(10));
entity.setAttribute("type", "VARCHAR(32)"); entity.setAttribute("type", "VARCHAR(32)");
......
...@@ -28,6 +28,7 @@ import org.apache.atlas.model.instance.EntityMutationResponse; ...@@ -28,6 +28,7 @@ import org.apache.atlas.model.instance.EntityMutationResponse;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Persistence/Retrieval API for AtlasEntity * Persistence/Retrieval API for AtlasEntity
...@@ -37,23 +38,8 @@ public interface AtlasEntityStore { ...@@ -37,23 +38,8 @@ public interface AtlasEntityStore {
/** /**
* Initialization * Initialization
*/ */
void init(AtlasTypeRegistry typeRegistry, EntityGraphDiscovery graphDiscovery) throws AtlasBaseException; void init(AtlasTypeRegistry typeRegistry) throws AtlasBaseException;
/**
* Create or update an entity if it already exists.
* @param entity
* @return
*/
EntityMutationResponse createOrUpdate(AtlasEntity entity) throws AtlasBaseException;
/**
* Update entity identified by its guid
* @param guid
* @param entity
* @return
*/
EntityMutationResponse updateById(String guid, AtlasEntity entity);
/** /**
* *
...@@ -70,25 +56,14 @@ public interface AtlasEntityStore { ...@@ -70,25 +56,14 @@ public interface AtlasEntityStore {
*/ */
EntityMutationResponse deleteById(String guid); EntityMutationResponse deleteById(String guid);
/** /**
* Create or update a list of entities * Create or update entities
* @param entities List of AtlasEntity objects that need to be created * @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 * @return EntityMutationResponse Entity mutations operations with the correspomding set of entities on which these operations were performed
* @throws AtlasBaseException * @throws AtlasBaseException
*/ */
EntityMutationResponse createOrUpdate(List<AtlasEntity> entities) throws AtlasBaseException; EntityMutationResponse createOrUpdate(Map<String, AtlasEntity> entities) throws AtlasBaseException;
/**
*
* Provides list of updated entity guids including any child entities
* @param guid
* @param entity
* @return
* @throws AtlasBaseException
*/
EntityMutationResponse updateByIds(String guid, AtlasEntity entity) throws AtlasBaseException;
/** /**
* Batch GET to retrieve entities by their ID * Batch GET to retrieve entities by their ID
...@@ -145,14 +120,6 @@ public interface AtlasEntityStore { ...@@ -145,14 +120,6 @@ public interface AtlasEntityStore {
EntityMutationResponse deleteByUniqueAttribute(String typeName, String attributeName, String attributeValue) throws AtlasBaseException; EntityMutationResponse deleteByUniqueAttribute(String typeName, String attributeName, String attributeValue) throws AtlasBaseException;
/** /**
* Compose any type of mutation op - EntityMutation.EntityOperation - CREATE_OR_UPDATE, PARTIAL_UPDATE, DELETE etc in a single transaction
* @param mutations
* @return
* @throws AtlasBaseException
*/
EntityMutationResponse batchMutate(EntityMutations mutations) throws AtlasBaseException;
/**
* Add classification(s) * Add classification(s)
*/ */
void addClassifications(String guid, List<AtlasClassification> classification) throws AtlasBaseException; void addClassifications(String guid, List<AtlasClassification> classification) throws AtlasBaseException;
...@@ -168,13 +135,4 @@ public interface AtlasEntityStore { ...@@ -168,13 +135,4 @@ public interface AtlasEntityStore {
*/ */
void deleteClassifications(String guid, List<String> classificationNames) throws AtlasBaseException; void deleteClassifications(String guid, List<String> classificationNames) throws AtlasBaseException;
/**
*
* Search by AND filters like typename, pre-defined attribute(s) eg: name, qualifiedName
* @param searchFilter
* @return
* @throws AtlasBaseException
*/
AtlasEntity.AtlasEntities searchEntities(SearchFilter searchFilter) throws AtlasBaseException;
} }
...@@ -17,106 +17,145 @@ ...@@ -17,106 +17,145 @@
*/ */
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.model.instance.AtlasEntity; 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.type.AtlasEntityType; import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; 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 final AtlasTypeRegistry typeRegistry;
* Keeps track of all the entities that need to be created/updated including its child entities * private List<AtlasEntity> rootEntities = new ArrayList<>();
*/ private Map<AtlasObjectId, AtlasVertex> resolvedIds = new LinkedHashMap<>();
private Set<AtlasEntity> rootEntities = new LinkedHashSet<>(); private Set<AtlasObjectId> unresolvedIds = new HashSet<>();
private List<AtlasObjectId> unresolvedIdsByUniqAttribs = new ArrayList<>();
//Key is a transient id/guid public EntityGraphDiscoveryContext(AtlasTypeRegistry typeRegistry) {
/** this.typeRegistry = typeRegistry;
* These references have been resolved using a unique identifier like guid or a qualified name etc in Atlas repository }
*/
private Map<String, AtlasVertex> repositoryResolvedReferences = new LinkedHashMap<>();
/**
* Unresolved entity references
*/
private List<AtlasEntity> unresolvedEntityReferences = new ArrayList<>();
/**
* Unresolved entity id references
*/
private Set<AtlasObjectId> unresolvedIdReferences = new HashSet<>();
public void addRepositoryResolvedReference(AtlasObjectId id, AtlasVertex vertex) { public Collection<AtlasEntity> getRootEntities() {
repositoryResolvedReferences.put(id.getGuid(), vertex); return rootEntities;
} }
public void addUnResolvedEntityReference(AtlasEntity entity) { public Map<AtlasObjectId, AtlasVertex> getResolvedIds() {
this.unresolvedEntityReferences.add(entity); return resolvedIds;
} }
public void addUnResolvedIdReference(AtlasEntityType entityType, String id) { public Set<AtlasObjectId> getUnresolvedIds() {
this.unresolvedIdReferences.add(new AtlasObjectId(entityType.getTypeName(), id)); return unresolvedIds;
} }
public Set<AtlasObjectId> getUnresolvedIdReferences() { public List<AtlasObjectId> getUnresolvedIdsByUniqAttribs() {
return unresolvedIdReferences; return unresolvedIdsByUniqAttribs;
} }
public boolean isResolved(String guid) {
return repositoryResolvedReferences.containsKey(guid);
}
public AtlasVertex getResolvedReference(AtlasObjectId ref) { public void addRootEntity(AtlasEntity rootEntity) {
return repositoryResolvedReferences.get(ref.getGuid()); this.rootEntities.add(rootEntity);
} }
public Map<String, AtlasVertex> getRepositoryResolvedReferences() {
return repositoryResolvedReferences;
}
public AtlasVertex getResolvedReference(String id) { public void addResolvedId(AtlasObjectId objId, AtlasVertex vertex) {
return repositoryResolvedReferences.get(id); if (LOG.isDebugEnabled()) {
LOG.debug("addResolvedId({})", objId);
}
resolvedIds.put(objId, vertex);
} }
public List<AtlasEntity> getUnResolvedEntityReferences() { public boolean removeUnResolvedId(AtlasObjectId objId) {
return unresolvedEntityReferences; if (LOG.isDebugEnabled()) {
LOG.debug("removeUnResolvedId({})", objId);
}
return unresolvedIds.remove(objId);
} }
public void addRootEntity(AtlasEntity rootEntity) {
this.rootEntities.add(rootEntity); public void addUnResolvedId(AtlasObjectId objId) {
if (LOG.isDebugEnabled()) {
LOG.debug("addUnResolvedId({})", objId);
}
this.unresolvedIds.add(objId);
} }
public Collection<AtlasEntity> getRootEntities() { public boolean removeUnResolvedIds(List<AtlasObjectId> objIds) {
return rootEntities; if (LOG.isDebugEnabled()) {
LOG.debug("removeUnResolvedIds({})", objIds);
}
return unresolvedIds.removeAll(objIds);
} }
public boolean removeUnResolvedEntityReference(final AtlasEntity entity) {
return unresolvedEntityReferences.remove(entity); public void addUnresolvedIdByUniqAttribs(AtlasObjectId objId) {
if (LOG.isDebugEnabled()) {
LOG.debug("addUnresolvedIdByUniqAttribs({})", objId);
}
this.unresolvedIdsByUniqAttribs.add(objId);
} }
public boolean removeUnResolvedEntityReferences(final List<AtlasEntity> entities) { public boolean removeUnresolvedIdsByUniqAttribs(List<AtlasObjectId> objIds) {
return unresolvedEntityReferences.removeAll(entities); if (LOG.isDebugEnabled()) {
LOG.debug("removeUnresolvedIdsByUniqAttribs({})", objIds);
}
return unresolvedIdsByUniqAttribs.removeAll(objIds);
} }
public boolean removeUnResolvedIdReferences(final List<AtlasObjectId> entities) { public boolean hasUnresolvedReferences() {
return unresolvedIdReferences.removeAll(entities); return unresolvedIdsByUniqAttribs.size() > 0 || unresolvedIds.size() > 0;
} }
public boolean removeUnResolvedIdReference(final AtlasObjectId entity) { public boolean isResolvedId(AtlasObjectId id) {
return unresolvedIdReferences.remove(entity); return resolvedIds.containsKey(id);
} }
public boolean hasUnresolvedReferences() { public AtlasVertex getResolvedEntityVertex(AtlasObjectId ref) throws AtlasBaseException {
return unresolvedEntityReferences.size() > 0 || unresolvedIdReferences.size() > 0; AtlasVertex vertex = resolvedIds.get(ref);
// check also for sub-types; ref={typeName=Asset; guid=abcd} should match {typeName=hive_table; guid=abcd}
if (vertex == null) {
final AtlasEntityType entityType = typeRegistry.getEntityTypeByName(ref.getTypeName());
final Set<String> allSubTypes = entityType.getAllSubTypes();
for (String subType : allSubTypes) {
AtlasObjectId subTypeObjId = new AtlasObjectId(subType, ref.getGuid(), ref.getUniqueAttributes());
vertex = resolvedIds.get(subTypeObjId);
if (vertex != null) {
resolvedIds.put(ref, vertex);
break;
}
}
}
if (vertex == null) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS,
" : Could not find an entity with " + ref.toString());
}
return vertex;
} }
@Override @Override
...@@ -130,15 +169,15 @@ public final class EntityGraphDiscoveryContext { ...@@ -130,15 +169,15 @@ public final class EntityGraphDiscoveryContext {
} else { } else {
EntityGraphDiscoveryContext ctx = (EntityGraphDiscoveryContext) obj; EntityGraphDiscoveryContext ctx = (EntityGraphDiscoveryContext) obj;
return Objects.equals(rootEntities, ctx.getRootEntities()) && return Objects.equals(rootEntities, ctx.getRootEntities()) &&
Objects.equals(repositoryResolvedReferences, ctx.getRepositoryResolvedReferences()) && Objects.equals(resolvedIds, ctx.getResolvedIds()) &&
Objects.equals(unresolvedEntityReferences, ctx.getUnResolvedEntityReferences()) && Objects.equals(unresolvedIdsByUniqAttribs, ctx.getUnresolvedIdsByUniqAttribs()) &&
Objects.equals(unresolvedIdReferences, ctx.getUnresolvedIdReferences()); Objects.equals(unresolvedIds, ctx.getUnresolvedIds());
} }
} }
@Override @Override
public int hashCode() { public int hashCode() {
return Objects.hash(rootEntities, repositoryResolvedReferences, unresolvedEntityReferences, unresolvedIdReferences); return Objects.hash(rootEntities, resolvedIds, unresolvedIdsByUniqAttribs, unresolvedIds);
} }
public StringBuilder toString(StringBuilder sb) { public StringBuilder toString(StringBuilder sb) {
...@@ -148,9 +187,9 @@ public final class EntityGraphDiscoveryContext { ...@@ -148,9 +187,9 @@ public final class EntityGraphDiscoveryContext {
sb.append("EntityGraphDiscoveryCtx{"); sb.append("EntityGraphDiscoveryCtx{");
sb.append("rootEntities='").append(rootEntities).append('\''); sb.append("rootEntities='").append(rootEntities).append('\'');
sb.append(", repositoryResolvedReferences=").append(repositoryResolvedReferences); sb.append(", resolvedIds=").append(resolvedIds);
sb.append(", unresolvedEntityReferences='").append(unresolvedEntityReferences).append('\''); sb.append(", unresolvedIdsByUniqAttribs='").append(unresolvedIdsByUniqAttribs).append('\'');
sb.append(", unresolvedIdReferences='").append(unresolvedIdReferences).append('\''); sb.append(", unresolvedIds='").append(unresolvedIds).append('\'');
sb.append('}'); sb.append('}');
return sb; return sb;
...@@ -163,8 +202,8 @@ public final class EntityGraphDiscoveryContext { ...@@ -163,8 +202,8 @@ public final class EntityGraphDiscoveryContext {
public void cleanUp() { public void cleanUp() {
rootEntities.clear(); rootEntities.clear();
unresolvedEntityReferences.clear(); unresolvedIdsByUniqAttribs.clear();
repositoryResolvedReferences.clear(); resolvedIds.clear();
unresolvedIdReferences.clear(); unresolvedIds.clear();
} }
} }
...@@ -41,6 +41,7 @@ import org.apache.atlas.type.AtlasMapType; ...@@ -41,6 +41,7 @@ import org.apache.atlas.type.AtlasMapType;
import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.commons.lang3.StringUtils;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.inject.Inject; import com.google.inject.Inject;
...@@ -49,17 +50,15 @@ import com.google.inject.Provider; ...@@ -49,17 +50,15 @@ import com.google.inject.Provider;
public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
private AtlasTypeRegistry typeRegistry; private final AtlasTypeRegistry typeRegistry;
private final EntityGraphDiscoveryContext discoveredEntities;
private Set<String> processedIds = new HashSet<>(); private final Set<String> processedIds = new HashSet<>();
private final Collection<EntityResolver> entityResolvers = new LinkedHashSet<>();
private EntityGraphDiscoveryContext discoveredEntities = new EntityGraphDiscoveryContext();
private final Collection<EntityResolver> entityResolvers = new LinkedHashSet<>();
@Inject @Inject
public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, final Collection<Provider<EntityResolver>> entityResolverProviders) { public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, Collection<Provider<EntityResolver>> entityResolverProviders) {
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
this.discoveredEntities = new EntityGraphDiscoveryContext(typeRegistry);
for (Provider<EntityResolver> entityResolverProvider : entityResolverProviders) { for (Provider<EntityResolver> entityResolverProvider : entityResolverProviders) {
entityResolvers.add(entityResolverProvider.get()); entityResolvers.add(entityResolverProvider.get());
...@@ -67,8 +66,9 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -67,8 +66,9 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
@VisibleForTesting @VisibleForTesting
public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, final List<EntityResolver> entityResolvers) { public AtlasEntityGraphDiscoveryV1(AtlasTypeRegistry typeRegistry, List<EntityResolver> entityResolvers) {
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
this.discoveredEntities = new EntityGraphDiscoveryContext(typeRegistry);
for (EntityResolver entityResolver : entityResolvers) { for (EntityResolver entityResolver : entityResolvers) {
this.entityResolvers.add(entityResolver); this.entityResolvers.add(entityResolver);
...@@ -96,22 +96,14 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -96,22 +96,14 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
public void cleanUp() throws AtlasBaseException { public void cleanUp() throws AtlasBaseException {
processedIds.clear(); processedIds.clear();
discoveredEntities.cleanUp(); discoveredEntities.cleanUp();
final Collection<EntityResolver> entityResolvers = this.entityResolvers;
for (EntityResolver resolver : entityResolvers) { for (EntityResolver resolver : entityResolvers) {
resolver.cleanUp(); resolver.cleanUp();
} }
} }
protected void resolveReferences() throws AtlasBaseException { protected void discover(List<AtlasEntity> entities) throws AtlasBaseException {
for (EntityResolver resolver : entityResolvers ) {
resolver.init(discoveredEntities);
resolver.resolveEntityReferences();
}
}
protected void discover(final List<AtlasEntity> entities) throws AtlasBaseException {
for (AtlasEntity entity : entities) { for (AtlasEntity entity : entities) {
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName()); AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
...@@ -120,27 +112,41 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -120,27 +112,41 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
discoveredEntities.addRootEntity(entity); discoveredEntities.addRootEntity(entity);
walkEntityGraph(type, entity); walkEntityGraph(type, entity);
} }
} }
private void visitReference(AtlasEntityType type, Object entity, boolean isManagedEntity) throws AtlasBaseException { protected void resolveReferences() throws AtlasBaseException {
for (EntityResolver resolver : entityResolvers) {
resolver.init(discoveredEntities);
resolver.resolveEntityReferences();
}
if (discoveredEntities.hasUnresolvedReferences()) {
throw new AtlasBaseException(AtlasErrorCode.UNRESOLVED_REFERENCES_FOUND,
discoveredEntities.getUnresolvedIds().toString(),
discoveredEntities.getUnresolvedIdsByUniqAttribs().toString());
}
}
private void visitReference(AtlasEntityType type, Object entity) throws AtlasBaseException {
if (entity != null) { if (entity != null) {
if (entity instanceof AtlasObjectId) { if (entity instanceof AtlasObjectId) {
final String guid = ((AtlasObjectId) entity).getGuid(); AtlasObjectId objId = (AtlasObjectId)entity;
discoveredEntities.addUnResolvedIdReference(type, guid);
} else if (entity instanceof AtlasEntity) { if (!objId.isValid()) {
AtlasEntity entityObj = (AtlasEntity) entity; throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Invalid object id " + objId);
if (isManagedEntity) { }
if (!processedIds.contains(entityObj.getGuid())) {
processedIds.add(entityObj.getGuid()); if (!StringUtils.isEmpty(objId.getGuid()) && (objId.isAssignedGuid() || objId.isUnAssignedGuid())) {
discoveredEntities.addUnResolvedId(objId);
discoveredEntities.addRootEntity(entityObj);
visitStruct(type, entityObj);
}
} else { } else {
discoveredEntities.addUnResolvedEntityReference(entityObj); discoveredEntities.addUnresolvedIdByUniqAttribs(objId);
} }
} else if (entity instanceof AtlasEntity) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Use AtlasObjectId to refer to another instance instead of AtlasEntity " + type.getTypeName());
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Invalid object type " + entity.getClass()); throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Invalid object type " + entity.getClass());
} }
...@@ -154,26 +160,18 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -154,26 +160,18 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
if (attrType.getTypeCategory() == TypeCategory.ARRAY) { if (attrType.getTypeCategory() == TypeCategory.ARRAY) {
AtlasArrayType arrayType = (AtlasArrayType) attrType; AtlasArrayType arrayType = (AtlasArrayType) attrType;
AtlasType elemType = arrayType.getElementType(); AtlasType elemType = arrayType.getElementType();
visitCollectionReferences(parentType, attrType, attrDef, elemType, val); visitCollectionReferences(parentType, attrType, attrDef, elemType, val);
} else if (attrType.getTypeCategory() == TypeCategory.MAP) { } else if (attrType.getTypeCategory() == TypeCategory.MAP) {
AtlasType keyType = ((AtlasMapType) attrType).getKeyType(); AtlasType keyType = ((AtlasMapType) attrType).getKeyType();
AtlasType valueType = ((AtlasMapType) attrType).getValueType(); AtlasType valueType = ((AtlasMapType) attrType).getValueType();
visitMapReferences(parentType, attrType, attrDef, keyType, valueType, val); visitMapReferences(parentType, attrType, attrDef, keyType, valueType, val);
} else if (attrType.getTypeCategory() == TypeCategory.STRUCT) { } else if (attrType.getTypeCategory() == TypeCategory.STRUCT) {
visitStruct(attrType, val); visitStruct((AtlasStructType)attrType, val);
} else if (attrType.getTypeCategory() == TypeCategory.ENTITY) { } else if (attrType.getTypeCategory() == TypeCategory.ENTITY) {
if ( val instanceof AtlasObjectId) { visitReference((AtlasEntityType) attrType, val);
visitReference((AtlasEntityType) attrType, val, false);
} else if ( val instanceof AtlasEntity ) {
//TODO - Change this to foreign key checks after changes in the model
if ((parentType instanceof AtlasEntityType) &&
((AtlasEntityType)parentType).isMappedFromRefAttribute(attrDef.getName())) {
visitReference((AtlasEntityType) attrType, val, true);
} else {
visitReference((AtlasEntityType) attrType, val, false);
}
}
} }
} }
} }
...@@ -184,7 +182,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -184,7 +182,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
if (val != null) { if (val != null) {
if (Map.class.isAssignableFrom(val.getClass())) { if (Map.class.isAssignableFrom(val.getClass())) {
Iterator<Map.Entry> it = ((Map) val).entrySet().iterator(); Iterator<Map.Entry> it = ((Map) val).entrySet().iterator();
while (it.hasNext()) { while (it.hasNext()) {
...@@ -197,7 +194,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -197,7 +194,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
void visitCollectionReferences(final AtlasStructType parentType, final AtlasType attrType, final AtlasAttributeDef attrDef, AtlasType elemType, Object val) throws AtlasBaseException { void visitCollectionReferences(final AtlasStructType parentType, final AtlasType attrType, final AtlasAttributeDef attrDef, AtlasType elemType, Object val) throws AtlasBaseException {
if (isPrimitive(elemType.getTypeCategory())) { if (isPrimitive(elemType.getTypeCategory())) {
return; return;
} }
...@@ -220,24 +216,22 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -220,24 +216,22 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
} }
void visitStruct(AtlasType type, Object val) throws AtlasBaseException { void visitStruct(AtlasStructType structType, Object val) throws AtlasBaseException {
if (structType == null) {
if (val == null || !(val instanceof AtlasStruct)) {
return; return;
} }
AtlasStructType structType = (AtlasStructType) type;
for (AtlasStructType.AtlasAttribute attribute : structType.getAllAttributes().values()) { for (AtlasStructType.AtlasAttribute attribute : structType.getAllAttributes().values()) {
AtlasType attrType = attribute.getAttributeType(); AtlasType attrType = attribute.getAttributeType();
Object attrVal = ((AtlasStruct) val).getAttribute(attribute.getName()); Object attrVal = ((AtlasStruct) val).getAttribute(attribute.getName());
visitAttribute(structType, attrType, attribute.getAttributeDef(), attrVal); visitAttribute(structType, attrType, attribute.getAttributeDef(), attrVal);
} }
} }
void walkEntityGraph(AtlasType type, AtlasEntity entity) throws AtlasBaseException { void walkEntityGraph(AtlasEntityType entityType, AtlasEntity entity) throws AtlasBaseException {
visitStruct(type, entity); visitStruct(entityType, entity);
} }
......
...@@ -25,31 +25,29 @@ import org.apache.atlas.AtlasErrorCode; ...@@ -25,31 +25,29 @@ import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.GraphTransaction; import org.apache.atlas.GraphTransaction;
import org.apache.atlas.RequestContextV1; import org.apache.atlas.RequestContextV1;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.SearchFilter;
import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.TypeCategory;
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.AtlasEntityWithAssociations; import org.apache.atlas.model.instance.AtlasEntityWithAssociations;
import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasObjectId;
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.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.graphdb.AtlasVertex;
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.EntityGraphDiscovery;
import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext; import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext;
import org.apache.atlas.repository.store.graph.EntityResolver;
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 com.google.common.annotations.VisibleForTesting; import java.util.Map;
import com.google.inject.Inject;
import com.google.inject.Inject;
public class AtlasEntityStoreV1 implements AtlasEntityStore { public class AtlasEntityStoreV1 implements AtlasEntityStore {
protected EntityGraphDiscovery graphDiscoverer;
protected AtlasTypeRegistry typeRegistry; protected AtlasTypeRegistry typeRegistry;
private EntityGraphMapper graphMapper; private EntityGraphMapper graphMapper;
...@@ -62,22 +60,11 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -62,22 +60,11 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
@Inject @Inject
public void init(AtlasTypeRegistry typeRegistry, EntityGraphDiscovery graphDiscoverer) throws AtlasBaseException { public void init(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
this.graphDiscoverer = graphDiscoverer;
this.typeRegistry = typeRegistry; this.typeRegistry = typeRegistry;
} }
@Override @Override
public EntityMutationResponse createOrUpdate(final AtlasEntity entity) throws AtlasBaseException {
return createOrUpdate(new ArrayList<AtlasEntity>() {{ add(entity); }});
}
@Override
public EntityMutationResponse updateById(final String guid, final AtlasEntity entity) {
return null;
}
@Override
public AtlasEntity getById(final String guid) { public AtlasEntity getById(final String guid) {
return null; return null;
} }
...@@ -89,7 +76,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -89,7 +76,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
@Override @Override
@GraphTransaction @GraphTransaction
public EntityMutationResponse createOrUpdate(final List<AtlasEntity> entities) throws AtlasBaseException { public EntityMutationResponse createOrUpdate(final Map<String, AtlasEntity> entities) throws AtlasBaseException {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("==> AtlasEntityStoreV1.createOrUpdate({}, {})", entities); LOG.debug("==> AtlasEntityStoreV1.createOrUpdate({}, {})", entities);
...@@ -109,11 +96,6 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -109,11 +96,6 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
@Override @Override
public EntityMutationResponse updateByIds(final String guid, final AtlasEntity entity) throws AtlasBaseException {
return null;
}
@Override
public AtlasEntity.AtlasEntities getByIds(final List<String> guid) throws AtlasBaseException { public AtlasEntity.AtlasEntities getByIds(final List<String> guid) throws AtlasBaseException {
return null; return null;
} }
...@@ -144,12 +126,6 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -144,12 +126,6 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
@Override @Override
public EntityMutationResponse batchMutate(final EntityMutations mutations) throws AtlasBaseException {
return null;
}
@Override
public void addClassifications(final String guid, final List<AtlasClassification> classification) throws AtlasBaseException { public void addClassifications(final String guid, final List<AtlasClassification> classification) throws AtlasBaseException {
} }
...@@ -164,42 +140,49 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -164,42 +140,49 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
@Override
public AtlasEntity.AtlasEntities searchEntities(final SearchFilter searchFilter) throws AtlasBaseException {
// TODO: Add checks here to ensure that typename and supertype are mandatory in the request
return null;
}
private EntityMutationContext preCreateOrUpdate(final List<AtlasEntity> atlasEntities) throws AtlasBaseException { private EntityMutationContext preCreateOrUpdate(final List<AtlasEntity> atlasEntities) throws AtlasBaseException {
List<EntityResolver> entityResolvers = new ArrayList<>();
entityResolvers.add(new IDBasedEntityResolver());
entityResolvers.add(new UniqAttrBasedEntityResolver(typeRegistry));
EntityGraphDiscovery graphDiscoverer = new AtlasEntityGraphDiscoveryV1(typeRegistry, entityResolvers);
EntityGraphDiscoveryContext discoveredEntities = graphDiscoverer.discoverEntities(atlasEntities); EntityGraphDiscoveryContext discoveredEntities = graphDiscoverer.discoverEntities(atlasEntities);
EntityMutationContext context = new EntityMutationContext(discoveredEntities); EntityMutationContext context = new EntityMutationContext(discoveredEntities);
for (AtlasEntity entity : discoveredEntities.getRootEntities()) {
AtlasVertex vertex = null; for (AtlasEntity entity : discoveredEntities.getRootEntities()) {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("<== AtlasEntityStoreV1.preCreateOrUpdate({}): {}", entity); LOG.debug("==> AtlasEntityStoreV1.preCreateOrUpdate({}): {}", entity);
} }
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName()); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
if ( entityType == null) { if (entityType == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName()); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName());
} }
if ( discoveredEntities.isResolved(entity.getGuid()) ) { final AtlasVertex vertex;
vertex = discoveredEntities.getResolvedReference(entity.getGuid()); AtlasObjectId objId = entity.getAtlasObjectId();
if (discoveredEntities.isResolvedId(objId) ) {
vertex = discoveredEntities.getResolvedEntityVertex(objId);
context.addUpdated(entity, entityType, vertex); context.addUpdated(entity, entityType, vertex);
String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex); String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex);
RequestContextV1.get().recordEntityUpdate(new AtlasObjectId(entityType.getTypeName(), guid)); RequestContextV1.get().recordEntityUpdate(new AtlasObjectId(entityType.getTypeName(), guid));
} else { } else {
//Create vertices which do not exist in the repository //Create vertices which do not exist in the repository
vertex = graphMapper.createVertexTemplate(entity, entityType); vertex = graphMapper.createVertexTemplate(entity, entityType);
context.addCreated(entity, entityType, vertex); context.addCreated(entity, entityType, vertex);
discoveredEntities.addRepositoryResolvedReference(new AtlasObjectId(entityType.getTypeName(), entity.getGuid()), vertex);
discoveredEntities.addResolvedId(objId, vertex);
discoveredEntities.removeUnResolvedId(objId);
String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex); String guid = AtlasGraphUtilsV1.getIdFromVertex(vertex);
RequestContextV1.get().recordEntityCreate(new AtlasObjectId(entityType.getTypeName(), guid)); RequestContextV1.get().recordEntityCreate(new AtlasObjectId(entityType.getTypeName(), guid));
} }
...@@ -211,12 +194,21 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -211,12 +194,21 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
return context; return context;
} }
private List<AtlasEntity> validateAndNormalize(final List<AtlasEntity> entities) throws AtlasBaseException { private List<AtlasEntity> validateAndNormalize(final Map<String, AtlasEntity> entities) throws AtlasBaseException {
List<AtlasEntity> normalizedEntities = new ArrayList<>(); List<AtlasEntity> normalizedEntities = new ArrayList<>();
List<String> messages = new ArrayList<>(); List<String> messages = new ArrayList<>();
for (String entityId : entities.keySet()) {
if ( !AtlasEntity.isAssigned(entityId) && !AtlasEntity.isUnAssigned(entityId)) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, ": Guid in map key is invalid " + entityId);
}
AtlasEntity entity = entities.get(entityId);
if ( entity == null) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, ": Entity is null for guid " + entityId);
}
for (AtlasEntity entity : entities) {
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName()); AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
if (type == null) { if (type == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName()); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName());
...@@ -227,11 +219,9 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -227,11 +219,9 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
if ( !messages.isEmpty()) { if ( !messages.isEmpty()) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages); throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages);
} }
AtlasEntity normalizedEntity = (AtlasEntity) type.getNormalizedValue(entity); AtlasEntity normalizedEntity = (AtlasEntity) type.getNormalizedValue(entity);
if ( normalizedEntity == null) {
//TODO - Fix this. Should not come here. Should ideally fail above
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, "Failed to validate entity");
}
normalizedEntities.add(normalizedEntity); normalizedEntities.add(normalizedEntity);
} }
...@@ -239,6 +229,5 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -239,6 +229,5 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
public void cleanUp() throws AtlasBaseException { public void cleanUp() throws AtlasBaseException {
this.graphDiscoverer.cleanUp();
} }
} }
...@@ -25,6 +25,7 @@ import org.apache.atlas.exception.AtlasBaseException; ...@@ -25,6 +25,7 @@ import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.TypeCategory;
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.model.instance.AtlasObjectId;
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.Constants; import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graph.AtlasEdgeLabel; import org.apache.atlas.repository.graph.AtlasEdgeLabel;
......
...@@ -88,8 +88,8 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> { ...@@ -88,8 +88,8 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> {
public AtlasEdge toGraph(GraphMutationContext ctx) throws AtlasBaseException { public AtlasEdge toGraph(GraphMutationContext ctx) throws AtlasBaseException {
AtlasEdge result = null; AtlasEdge result = null;
String guid = getId(ctx.getValue()); AtlasObjectId guid = getId(ctx.getValue());
AtlasVertex entityVertex = context.getDiscoveryContext().getResolvedReference(guid); AtlasVertex entityVertex = context.getDiscoveryContext().getResolvedEntityVertex(guid);
if ( ctx.getCurrentEdge().isPresent() ) { if ( ctx.getCurrentEdge().isPresent() ) {
result = updateEdge(ctx.getAttributeDef(), ctx.getValue(), ctx.getCurrentEdge().get(), entityVertex); result = updateEdge(ctx.getAttributeDef(), ctx.getValue(), ctx.getCurrentEdge().get(), entityVertex);
} else if (ctx.getValue() != null) { } else if (ctx.getValue() != null) {
...@@ -166,12 +166,18 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> { ...@@ -166,12 +166,18 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> {
} }
public String getId(Object value) throws AtlasBaseException { public AtlasObjectId getId(Object value) throws AtlasBaseException {
if ( value != null) { if (value != null) {
if ( value instanceof AtlasObjectId) { if ( value instanceof AtlasObjectId) {
return ((AtlasObjectId) value).getGuid(); return ((AtlasObjectId) value);
} else if (value instanceof AtlasEntity) { } else if (value instanceof AtlasEntity) {
return ((AtlasEntity) value).getGuid(); return ((AtlasEntity) value).getAtlasObjectId();
} else if (value instanceof Map) {
AtlasObjectId ret = new AtlasObjectId((Map)value);
if (ret.isValid()) {
return ret;
}
} }
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, (String) value); throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, (String) value);
...@@ -211,7 +217,7 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> { ...@@ -211,7 +217,7 @@ public class EntityGraphMapper implements InstanceGraphMapper<AtlasEdge> {
} }
public AtlasEntityType getInstanceType(Object val) throws AtlasBaseException { public AtlasEntityType getInstanceType(Object val) throws AtlasBaseException {
String guid = getId(val); AtlasObjectId guid = getId(val);
if ( guid != null) { if ( guid != null) {
return (AtlasEntityType) getContext().getType(guid); return (AtlasEntityType) getContext().getType(guid);
......
...@@ -19,40 +19,41 @@ package org.apache.atlas.repository.store.graph.v1; ...@@ -19,40 +19,41 @@ package org.apache.atlas.repository.store.graph.v1;
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.graphdb.AtlasVertex; 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 java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class EntityMutationContext { public class EntityMutationContext {
private final EntityGraphDiscoveryContext context;
private List<AtlasEntity> entitiesCreated = new ArrayList<>(); private final List<AtlasEntity> entitiesCreated = new ArrayList<>();
private List<AtlasEntity> entitiesUpdated = new ArrayList<>(); private final List<AtlasEntity> entitiesUpdated = new ArrayList<>();
private final Map<AtlasObjectId, AtlasEntityType> entityVsType = new HashMap<>();
private EntityGraphDiscoveryContext context; private final Map<AtlasObjectId, AtlasVertex> entityVsVertex = new HashMap<>();
private Map<String, AtlasEntityType> entityVsType = new HashMap<>();
private Map<String, AtlasVertex> entityVsVertex = 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(AtlasEntity entity, AtlasEntityType type, AtlasVertex atlasVertex) {
AtlasObjectId objId = entity.getAtlasObjectId();
entitiesCreated.add(entity); entitiesCreated.add(entity);
entityVsVertex.put(entity.getGuid(), atlasVertex); entityVsType.put(objId, type);
entityVsType.put(entity.getGuid(), type); entityVsVertex.put(objId, 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);
entityVsVertex.put(entity.getGuid(), atlasVertex); entityVsType.put(objId, type);
entityVsType.put(entity.getGuid(), type); entityVsVertex.put(objId, atlasVertex);
}
public EntityGraphDiscoveryContext getDiscoveryContext() {
return this.context;
} }
public Collection<AtlasEntity> getCreatedEntities() { public Collection<AtlasEntity> getCreatedEntities() {
...@@ -64,26 +65,21 @@ public class EntityMutationContext { ...@@ -64,26 +65,21 @@ public class EntityMutationContext {
} }
public AtlasEntityType getType(AtlasEntity entity) { public AtlasEntityType getType(AtlasEntity entity) {
return entityVsType.get(entity.getGuid()); return entityVsType.get(entity.getAtlasObjectId());
} }
public AtlasType getType(String entityId) { public AtlasType getType(AtlasObjectId entityId) {
return entityVsType.get(entityId); return entityVsType.get(entityId);
} }
public AtlasVertex getVertex(AtlasEntity entity) { public AtlasVertex getVertex(AtlasEntity entity) {
return entityVsVertex.get(entity.getGuid()); return entityVsVertex.get(entity.getAtlasObjectId());
} }
public AtlasVertex getVertex(String entityId) { public AtlasVertex getVertex(AtlasObjectId entityId) {
return entityVsVertex.get(entityId); return entityVsVertex.get(entityId);
} }
public EntityGraphDiscoveryContext getDiscoveryContext() {
return this.context;
}
//TODO - equals/hashCode/toString
@Override @Override
public boolean equals(final Object o) { public boolean equals(final Object o) {
...@@ -92,32 +88,29 @@ public class EntityMutationContext { ...@@ -92,32 +88,29 @@ public class EntityMutationContext {
final EntityMutationContext that = (EntityMutationContext) o; final EntityMutationContext that = (EntityMutationContext) o;
if (entitiesCreated != null ? !entitiesCreated.equals(that.entitiesCreated) : that.entitiesCreated != null) return Objects.equals(context, that.context) &&
return false; Objects.equals(entitiesCreated, that.entitiesCreated) &&
if (entitiesUpdated != null ? !entitiesUpdated.equals(that.entitiesUpdated) : that.entitiesUpdated != null) Objects.equals(entitiesUpdated, that.entitiesUpdated) &&
return false; Objects.equals(entityVsType, that.entityVsType) &&
if (context != null ? !context.equals(that.context) : that.context != null) return false; Objects.equals(entityVsVertex, that.entityVsVertex);
if (entityVsType != null ? !entityVsType.equals(that.entityVsType) : that.entityVsType != null) return false;
return !(entityVsVertex != null ? !entityVsVertex.equals(that.entityVsVertex) : that.entityVsVertex != null);
} }
@Override @Override
public int hashCode() { public int hashCode() {
int result = entitiesCreated != null ? entitiesCreated.hashCode() : 0; int result = (context != null ? context.hashCode() : 0);
result = 31 * result + (entitiesUpdated != null ? entitiesUpdated.hashCode() : 0); result = 31 * result + entitiesCreated.hashCode();
result = 31 * result + (context != null ? context.hashCode() : 0); result = 31 * result + entitiesUpdated.hashCode();
result = 31 * result + (entityVsType != null ? entityVsType.hashCode() : 0); result = 31 * result + entityVsType.hashCode();
result = 31 * result + (entityVsVertex != null ? entityVsVertex.hashCode() : 0); result = 31 * result + entityVsVertex.hashCode();
return result; return result;
} }
@Override @Override
public String toString() { public String toString() {
return "EntityMutationContext{" + return "EntityMutationContext{" +
"entitiesCreated=" + entitiesCreated + "context=" + context +
", entitiesCreated=" + entitiesCreated +
", entitiesUpdated=" + entitiesUpdated + ", entitiesUpdated=" + entitiesUpdated +
", context=" + context +
", entityVsType=" + entityVsType + ", entityVsType=" + entityVsType +
", entityVsVertex=" + entityVsVertex + ", entityVsVertex=" + entityVsVertex +
'}'; '}';
......
/**
* 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 org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
public interface EntityStream {
boolean hasNext();
AtlasEntity next();
void reset();
AtlasEntity getById(AtlasObjectId id);
}
...@@ -37,67 +37,70 @@ import java.util.Map; ...@@ -37,67 +37,70 @@ import java.util.Map;
public class IDBasedEntityResolver implements EntityResolver { public class IDBasedEntityResolver implements EntityResolver {
private Map<String, AtlasEntity> idToEntityMap = new HashMap<>(); private final GraphHelper graphHelper = GraphHelper.getInstance();
private final Map<String, AtlasEntity> idToEntityMap = new HashMap<>();
private final GraphHelper graphHelper = GraphHelper.getInstance(); private EntityGraphDiscoveryContext context;
private EntityGraphDiscoveryContext context;
@Override @Override
public void init(EntityGraphDiscoveryContext context) throws AtlasBaseException { public void init(EntityGraphDiscoveryContext context) throws AtlasBaseException {
this.context = context; this.context = context;
for (AtlasEntity entity : context.getRootEntities()) { for (AtlasEntity entity : context.getRootEntities()) {
idToEntityMap.put(entity.getGuid(), entity); idToEntityMap.put(entity.getGuid(), entity);
} }
} }
public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException { public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException {
if (context == null) {
if ( context == null) {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Entity resolver not initialized"); throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Entity resolver not initialized");
} }
List<AtlasObjectId> resolvedReferences = new ArrayList<>(); List<AtlasObjectId> resolvedReferences = new ArrayList<>();
for (AtlasObjectId typeIdPair : context.getUnresolvedIdReferences()) { for (AtlasObjectId objId : context.getUnresolvedIds()) {
if ( AtlasEntity.isAssigned(typeIdPair.getGuid())) { if (objId.isAssignedGuid()) {
//validate in graph repo that given guid, typename exists //validate in graph repo that given guid, typename exists
Optional<AtlasVertex> vertex = resolveGuid(typeIdPair); Optional<AtlasVertex> vertex = resolveGuid(objId);
if ( vertex.isPresent() ) { if (vertex.isPresent()) {
context.addRepositoryResolvedReference(typeIdPair, vertex.get()); context.addResolvedId(objId, vertex.get());
resolvedReferences.add(typeIdPair); resolvedReferences.add(objId);
} }
} else { } else {
//check if root references have this temporary id //check if root references have this temporary id
if (!idToEntityMap.containsKey(typeIdPair.getGuid()) ) { if (!idToEntityMap.containsKey(objId.getGuid()) ) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, "Could not find an entity with the specified id " + typeIdPair + " in the request"); throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, objId.toString());
} }
resolvedReferences.add(objId);
} }
} }
context.removeUnResolvedIdReferences(resolvedReferences); context.removeUnResolvedIds(resolvedReferences);
//Resolve root references //Resolve root references
for (AtlasEntity entity : context.getRootEntities()) { for (AtlasEntity entity : context.getRootEntities()) {
if ( !context.isResolved(entity.getGuid()) && AtlasEntity.isAssigned(entity.getGuid())) { AtlasObjectId objId = entity.getAtlasObjectId();
AtlasObjectId typeIdPair = new AtlasObjectId(entity.getTypeName(), entity.getGuid());
Optional<AtlasVertex> vertex = resolveGuid(typeIdPair); if (!context.isResolvedId(objId) && AtlasEntity.isAssigned(entity.getGuid())) {
Optional<AtlasVertex> vertex = resolveGuid(objId);
if (vertex.isPresent()) { if (vertex.isPresent()) {
context.addRepositoryResolvedReference(typeIdPair, vertex.get()); context.addResolvedId(objId, vertex.get());
context.removeUnResolvedIdReference(typeIdPair); context.removeUnResolvedId(objId);
} }
} }
} }
return context; return context;
} }
private Optional<AtlasVertex> resolveGuid(AtlasObjectId typeIdPair) throws AtlasBaseException { private Optional<AtlasVertex> resolveGuid(AtlasObjectId objId) 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, typeIdPair.getGuid(), vertex = graphHelper.findVertex(Constants.GUID_PROPERTY_KEY, objId.getGuid(),
Constants.TYPE_NAME_PROPERTY_KEY, typeIdPair.getTypeName(), 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
...@@ -105,7 +108,7 @@ public class IDBasedEntityResolver implements EntityResolver { ...@@ -105,7 +108,7 @@ public class IDBasedEntityResolver implements EntityResolver {
if ( vertex != null ) { if ( vertex != null ) {
return Optional.of(vertex); return Optional.of(vertex);
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, typeIdPair.getGuid()); throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, objId.getGuid());
} }
} }
......
/**
* 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 org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class InMemoryMapEntityStream implements EntityStream {
private final Map<AtlasObjectId, AtlasEntity> entities = new HashMap<>();
private Iterator<Map.Entry<AtlasObjectId, AtlasEntity>> iterator;
public InMemoryMapEntityStream(Map<String, AtlasEntity> entityMap) {
for (AtlasEntity entity : entityMap.values()) {
entities.put(entity.getAtlasObjectId(), entity);
}
this.iterator = entities.entrySet().iterator();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public AtlasEntity next() {
return iterator.hasNext() ? iterator.next().getValue() : null;
}
@Override
public void reset() {
iterator = entities.entrySet().iterator();
}
@Override
public AtlasEntity getById(final AtlasObjectId id) {
return entities.get(id);
}
}
...@@ -23,7 +23,6 @@ import org.apache.atlas.exception.AtlasBaseException; ...@@ -23,7 +23,6 @@ import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.TypeCategory;
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.model.instance.AtlasObjectId;
import org.apache.atlas.model.typedef.AtlasStructDef;
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;
...@@ -33,21 +32,20 @@ import org.apache.atlas.type.AtlasEntityType; ...@@ -33,21 +32,20 @@ import org.apache.atlas.type.AtlasEntityType;
import org.apache.atlas.type.AtlasStructType; import org.apache.atlas.type.AtlasStructType;
import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.typesystem.exception.EntityNotFoundException; import org.apache.atlas.typesystem.exception.EntityNotFoundException;
import org.apache.commons.collections.MapUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
public class UniqAttrBasedEntityResolver implements EntityResolver { public class UniqAttrBasedEntityResolver implements EntityResolver {
private static final Logger LOG = LoggerFactory.getLogger(UniqAttrBasedEntityResolver.class); private static final Logger LOG = LoggerFactory.getLogger(UniqAttrBasedEntityResolver.class);
private final AtlasTypeRegistry typeRegistry; private final GraphHelper graphHelper = GraphHelper.getInstance();
private final AtlasTypeRegistry typeRegistry;
private final GraphHelper graphHelper = GraphHelper.getInstance();
private EntityGraphDiscoveryContext context; private EntityGraphDiscoveryContext context;
@Inject @Inject
...@@ -56,41 +54,41 @@ public class UniqAttrBasedEntityResolver implements EntityResolver { ...@@ -56,41 +54,41 @@ public class UniqAttrBasedEntityResolver implements EntityResolver {
} }
@Override @Override
public void init(EntityGraphDiscoveryContext entities) throws AtlasBaseException { public void init(EntityGraphDiscoveryContext context) throws AtlasBaseException {
this.context = entities; this.context = context;
} }
@Override @Override
public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException { public EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException {
if (context == null) {
if ( context == null) {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Unique attribute based entity resolver not initialized"); throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "Unique attribute based entity resolver not initialized");
} }
//Resolve attribute references //Resolve attribute references
List<AtlasEntity> resolvedReferences = new ArrayList<>(); List<AtlasObjectId> resolvedReferences = new ArrayList<>();
for (AtlasEntity entity : context.getUnResolvedEntityReferences()) { for (AtlasObjectId entityId : context.getUnresolvedIdsByUniqAttribs()) {
//query in graph repo that given unique attribute - check for deleted also? //query in graph repo that given unique attribute - check for deleted also?
Optional<AtlasVertex> vertex = resolveByUniqueAttribute(entity); Optional<AtlasVertex> vertex = resolveByUniqueAttribute(entityId);
if (vertex.isPresent()) { if (vertex.isPresent()) {
context.addRepositoryResolvedReference(new AtlasObjectId(entity.getTypeName(), entity.getGuid()), vertex.get()); context.addResolvedId(entityId, vertex.get());
resolvedReferences.add(entity); resolvedReferences.add(entityId);
} }
} }
context.removeUnResolvedEntityReferences(resolvedReferences); context.removeUnresolvedIdsByUniqAttribs(resolvedReferences);
if (context.getUnResolvedEntityReferences().size() > 0) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND, context.getUnResolvedEntityReferences().toString());
}
//Resolve root references //Resolve root references
for (AtlasEntity entity : context.getRootEntities()) { for (AtlasEntity entity : context.getRootEntities()) {
if ( !context.isResolved(entity.getGuid()) ) { AtlasObjectId entityId = entity.getAtlasObjectId();
if (!context.isResolvedId(entityId) ) {
Optional<AtlasVertex> vertex = resolveByUniqueAttribute(entity); Optional<AtlasVertex> vertex = resolveByUniqueAttribute(entity);
if (vertex.isPresent()) { if (vertex.isPresent()) {
context.addRepositoryResolvedReference(new AtlasObjectId(entity.getTypeName(), entity.getGuid()), vertex.get()); context.addResolvedId(entityId, vertex.get());
context.removeUnResolvedId(entityId);
} }
} }
} }
...@@ -108,23 +106,57 @@ public class UniqAttrBasedEntityResolver implements EntityResolver { ...@@ -108,23 +106,57 @@ public class UniqAttrBasedEntityResolver implements EntityResolver {
for (AtlasStructType.AtlasAttribute attr : entityType.getAllAttributes().values()) { for (AtlasStructType.AtlasAttribute attr : entityType.getAllAttributes().values()) {
if (attr.getAttributeDef().getIsUnique()) { if (attr.getAttributeDef().getIsUnique()) {
Object attrVal = entity.getAttribute(attr.getName()); Object attrVal = entity.getAttribute(attr.getName());
if (attrVal != null) {
String qualifiedAttrName = attr.getQualifiedAttributeName(); if (attrVal == null) {
AtlasVertex vertex = null; continue;
try { }
vertex = graphHelper.findVertex(qualifiedAttrName, attrVal,
Constants.ENTITY_TYPE_PROPERTY_KEY, entityType.getTypeName(), Optional<AtlasVertex> vertex = findByTypeAndQualifiedName(entityType.getTypeName(), attr.getQualifiedAttributeName(), attrVal);
Constants.STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE
.name()); if (LOG.isDebugEnabled()) {
LOG.debug("Found vertex by unique attribute : " + attr.getQualifiedAttributeName() + "=" + attrVal);
if (LOG.isDebugEnabled()) { }
LOG.debug("Found vertex by unique attribute : " + qualifiedAttrName + "=" + attrVal);
} if (!vertex.isPresent()) {
if (vertex != null) { vertex = findBySuperTypeAndQualifiedName(entityType.getTypeName(), attr.getQualifiedAttributeName(), attrVal);
return Optional.of(vertex); }
}
} catch (EntityNotFoundException e) { if (vertex.isPresent()) {
//Ignore if not found return vertex;
}
}
}
return Optional.absent();
}
Optional<AtlasVertex> resolveByUniqueAttribute(AtlasObjectId entityId) throws AtlasBaseException {
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entityId.getTypeName());
if (entityType == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entityId.getTypeName());
}
final Map<String, Object> uniqueAttributes = entityId.getUniqueAttributes();
if (MapUtils.isNotEmpty(uniqueAttributes)) {
for (String attrName : uniqueAttributes.keySet()) {
AtlasStructType.AtlasAttribute attr = entityType.getAttribute(attrName);
if (attr.getAttributeDef().getIsUnique()) {
Object attrVal = uniqueAttributes.get(attr.getName());
if (attrVal == null) {
continue;
}
Optional<AtlasVertex> vertex = findByTypeAndQualifiedName(entityId.getTypeName(), attr.getQualifiedAttributeName(), attrVal);
if (!vertex.isPresent()) {
vertex = findBySuperTypeAndQualifiedName(entityId.getTypeName(), attr.getQualifiedAttributeName(), attrVal);
}
if (vertex.isPresent()) {
return vertex;
} }
} }
} }
...@@ -132,6 +164,46 @@ public class UniqAttrBasedEntityResolver implements EntityResolver { ...@@ -132,6 +164,46 @@ public class UniqAttrBasedEntityResolver implements EntityResolver {
return Optional.absent(); return Optional.absent();
} }
Optional<AtlasVertex> findByTypeAndQualifiedName(String typeName, String qualifiedAttrName, Object attrVal) {
AtlasVertex vertex = null;
try {
vertex = graphHelper.findVertex(qualifiedAttrName, attrVal,
Constants.ENTITY_TYPE_PROPERTY_KEY, typeName,
Constants.STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE
.name());
if (LOG.isDebugEnabled()) {
LOG.debug("Found vertex by unique attribute and type {} {} ", qualifiedAttrName + "=" + attrVal, typeName);
}
if (vertex != null) {
return Optional.of(vertex);
}
} catch (EntityNotFoundException e) {
//Ignore if not found
}
return Optional.absent();
}
Optional<AtlasVertex> findBySuperTypeAndQualifiedName(String typeName, String qualifiedAttrName, Object attrVal) {
AtlasVertex vertex = null;
try {
vertex = graphHelper.findVertex(qualifiedAttrName, attrVal,
Constants.SUPER_TYPES_PROPERTY_KEY, typeName,
Constants.STATE_PROPERTY_KEY, AtlasEntity.Status.ACTIVE
.name());
if (LOG.isDebugEnabled()) {
LOG.debug("Found vertex by unique attribute and supertype {} ", qualifiedAttrName + "=" + attrVal, typeName);
}
if (vertex != null) {
return Optional.of(vertex);
}
} catch (EntityNotFoundException e) {
//Ignore if not found
}
return Optional.absent();
}
@Override @Override
public void cleanUp() { public void cleanUp() {
//Nothing to cleanup //Nothing to cleanup
......
...@@ -71,6 +71,8 @@ import java.util.List; ...@@ -71,6 +71,8 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME; import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME;
import static org.apache.atlas.TestUtils.COLUMN_TYPE;
import static org.apache.atlas.TestUtils.NAME;
import static org.apache.atlas.TestUtils.TABLE_TYPE; import static org.apache.atlas.TestUtils.TABLE_TYPE;
import static org.apache.atlas.TestUtils.randomString; import static org.apache.atlas.TestUtils.randomString;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
...@@ -91,6 +93,10 @@ public class AtlasEntityStoreV1Test { ...@@ -91,6 +93,10 @@ public class AtlasEntityStoreV1Test {
@Inject @Inject
MetadataService metadataService; MetadataService metadataService;
private Map<String, AtlasEntity> deptEntityMap;
private Map<String, AtlasEntity> dbEntityMap;
private Map<String, AtlasEntity> tableEntityMap;
private AtlasEntity deptEntity; private AtlasEntity deptEntity;
private AtlasEntity dbEntity; private AtlasEntity dbEntity;
private AtlasEntity tableEntity; private AtlasEntity tableEntity;
...@@ -105,9 +111,13 @@ public class AtlasEntityStoreV1Test { ...@@ -105,9 +111,13 @@ public class AtlasEntityStoreV1Test {
final AtlasTypesDef hiveTypesDef = TestUtilsV2.defineHiveTypes(); final AtlasTypesDef hiveTypesDef = TestUtilsV2.defineHiveTypes();
typeDefStore.createTypesDef(hiveTypesDef); typeDefStore.createTypesDef(hiveTypesDef);
deptEntity = TestUtilsV2.createDeptEg1(); deptEntityMap = TestUtilsV2.createDeptEg1();
dbEntity = TestUtilsV2.createDBEntity(); dbEntityMap = TestUtilsV2.createDBEntity();
tableEntity = TestUtilsV2.createTableEntity(dbEntity.getGuid()); tableEntityMap = TestUtilsV2.createTableEntity(dbEntityMap.keySet().iterator().next());
deptEntity = deptEntityMap.values().iterator().next();
dbEntity = dbEntityMap.values().iterator().next();
tableEntity = tableEntityMap.values().iterator().next();
} }
@AfterClass @AfterClass
...@@ -124,45 +134,46 @@ public class AtlasEntityStoreV1Test { ...@@ -124,45 +134,46 @@ public class AtlasEntityStoreV1Test {
ArrayVertexMapper arrVertexMapper = new ArrayVertexMapper(deleteHandler); ArrayVertexMapper arrVertexMapper = new ArrayVertexMapper(deleteHandler);
MapVertexMapper mapVertexMapper = new MapVertexMapper(deleteHandler); MapVertexMapper mapVertexMapper = new MapVertexMapper(deleteHandler);
List<EntityResolver> entityResolvers = new ArrayList<>();
entityResolvers.add(new IDBasedEntityResolver());
entityResolvers.add(new UniqAttrBasedEntityResolver(typeRegistry));
EntityGraphDiscovery graphDiscovery = new AtlasEntityGraphDiscoveryV1(typeRegistry, entityResolvers);
entityStore = new AtlasEntityStoreV1(new EntityGraphMapper(arrVertexMapper, mapVertexMapper, deleteHandler)); entityStore = new AtlasEntityStoreV1(new EntityGraphMapper(arrVertexMapper, mapVertexMapper, deleteHandler));
entityStore.init(typeRegistry, graphDiscovery); entityStore.init(typeRegistry);
RequestContextV1.clear(); RequestContextV1.clear();
} }
@Test @Test
public void testCreate() throws Exception { public void testCreate() throws Exception {
EntityMutationResponse response = entityStore.createOrUpdate(deptEntity); EntityMutationResponse response = entityStore.createOrUpdate(deptEntityMap);
validateMutationResponse(response, EntityMutations.EntityOperation.CREATE, 5); validateMutationResponse(response, EntityMutations.EntityOperation.CREATE, 5);
AtlasEntityHeader deptEntity = response.getFirstEntityCreated(); AtlasEntityHeader deptEntity = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DEPARTMENT_TYPE);
validateAttributes(deptEntity); final Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> entitiesMutated = response.getEntitiesMutated();
List<AtlasEntityHeader> entitiesCreated = entitiesMutated.get(EntityMutations.EntityOperation.CREATE);
for (AtlasEntityHeader header : entitiesCreated) {
validateAttributes(deptEntityMap, header);
}
//Create DB //Create DB
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(dbEntity); EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(dbEntityMap);
validateMutationResponse(dbCreationResponse, EntityMutations.EntityOperation.CREATE, 1); validateMutationResponse(dbCreationResponse, EntityMutations.EntityOperation.CREATE, 1);
AtlasEntityHeader dbEntity = dbCreationResponse.getFirstEntityCreated(); AtlasEntityHeader dbEntity = dbCreationResponse.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
validateAttributes(dbEntity); validateAttributes(dbEntityMap, dbEntity);
//Create Table //Create Table
//Update DB guid //Update DB guid
AtlasObjectId dbId = (AtlasObjectId) tableEntity.getAttribute("database"); AtlasObjectId dbId = (AtlasObjectId) tableEntity.getAttribute("database");
dbId.setGuid(dbEntity.getGuid()); dbId.setGuid(dbEntity.getGuid());
tableEntityMap.put(dbId.getGuid(), dbEntityMap.values().iterator().next());
tableEntity.setAttribute("database", dbId); tableEntity.setAttribute("database", dbId);
EntityMutationResponse tableCreationResponse = entityStore.createOrUpdate(tableEntity); EntityMutationResponse tableCreationResponse = entityStore.createOrUpdate(tableEntityMap);
validateMutationResponse(tableCreationResponse, EntityMutations.EntityOperation.CREATE, 1); validateMutationResponse(tableCreationResponse, EntityMutations.EntityOperation.CREATE, 1);
AtlasEntityHeader tableEntity = tableCreationResponse.getFirstEntityCreated(); AtlasEntityHeader tableEntity = tableCreationResponse.getFirstCreatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableEntity); validateAttributes(tableEntityMap, tableEntity);
} }
...@@ -171,74 +182,86 @@ public class AtlasEntityStoreV1Test { ...@@ -171,74 +182,86 @@ public class AtlasEntityStoreV1Test {
//clear state //clear state
init(); init();
AtlasEntity entityClone = new AtlasEntity(deptEntity); // Map<String, AtlasEntity> entityCloneMap = new HashMap<>();
// AtlasEntity entityClone = new AtlasEntity(deptEntity);
// List<AtlasObjectId> employees = (List<AtlasObjectId>) entityClone.getAttribute("employees");
// AtlasEntity entityRemoved = clearSubOrdinates(employees, 1);
// entityClone.setAttribute("employees", employees);
// EntityMutationResponse response = entityStore.createOrUpdate(entityCloneMap);
//
// validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 5);
// AtlasEntityHeader deptEntity = response.getFirstEntityUpdated();
// Assert.assertEquals(((List<AtlasEntity>)(((List<AtlasEntity>) deptEntity.getAttribute("employees")).get(1).getAttribute("subordinates"))).size(), 1);
//
// init();
// //add entity back
// addSubordinate(employees.get(1), entityRemoved);
// response = entityStore.createOrUpdate(entityCloneMap);
// validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 5);
// deptEntity = response.getFirstEntityUpdated();
// validateAttributes(deptEntity);
List<AtlasEntity> employees = (List<AtlasEntity>) entityClone.getAttribute("employees");
AtlasEntity entityRemoved = clearSubOrdinates(employees, 1); Map<String, AtlasEntity> tableUpdatedMap = new HashMap<>();
entityClone.setAttribute("employees", employees); tableUpdatedMap.put(dbEntity.getGuid(), dbEntity);
EntityMutationResponse response = entityStore.createOrUpdate(entityClone);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 5);
AtlasEntityHeader deptEntity = response.getFirstEntityUpdated();
Assert.assertEquals(((List<AtlasEntity>)(((List<AtlasEntity>) deptEntity.getAttribute("employees")).get(1).getAttribute("subordinates"))).size(), 1);
init();
//add entity back
addSubordinate(employees.get(1), entityRemoved);
response = entityStore.createOrUpdate(entityClone);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 5);
deptEntity = response.getFirstEntityUpdated();
validateAttributes(deptEntity);
//test array of class with id //test array of class with id
final List<AtlasEntity> columns = new ArrayList<>(); final List<AtlasObjectId> columns = new ArrayList<>();
AtlasEntity col1 = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); AtlasEntity col1 = TestUtilsV2.createColumnEntity(tableEntity.getGuid());
col1.setAttribute(TestUtilsV2.NAME, "col1"); col1.setAttribute(TestUtilsV2.NAME, "col1");
columns.add(col1); columns.add(col1.getAtlasObjectId());
tableUpdatedMap.put(col1.getGuid(), col1);
AtlasEntity tableUpdated = new AtlasEntity(tableEntity); AtlasEntity tableUpdated = new AtlasEntity(tableEntity);
tableUpdated.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns); tableUpdated.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
tableUpdatedMap.put(tableUpdated.getGuid(), tableUpdated);
init(); init();
response = entityStore.createOrUpdate(tableUpdated); EntityMutationResponse response = entityStore.createOrUpdate(tableUpdatedMap);
AtlasEntityHeader updatedTable = response.getFirstEntityUpdated(); AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(tableUpdated.getTypeName());
validateAttributes(updatedTable); validateAttributes(tableUpdatedMap, updatedTable);
//Complete update. Add array elements - col3,col4 //Complete update. Add array elements - col3,col4
AtlasEntity col3 = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); AtlasEntity col3 = TestUtilsV2.createColumnEntity(tableEntity.getGuid());
col1.setAttribute(TestUtilsV2.NAME, "col3"); col1.setAttribute(TestUtilsV2.NAME, "col3");
columns.add(col3); columns.add(col3.getAtlasObjectId());
tableUpdatedMap.put(col3.getGuid(), col3);
AtlasEntity col4 = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); AtlasEntity col4 = TestUtilsV2.createColumnEntity(tableEntity.getGuid());
col1.setAttribute(TestUtilsV2.NAME, "col4"); col1.setAttribute(TestUtilsV2.NAME, "col4");
columns.add(col4); columns.add(col4.getAtlasObjectId());
tableUpdatedMap.put(col4.getGuid(), col4);
tableUpdated.setAttribute(COLUMNS_ATTR_NAME, columns); tableUpdated.setAttribute(COLUMNS_ATTR_NAME, columns);
init(); init();
response = entityStore.createOrUpdate(tableUpdated); response = entityStore.createOrUpdate(tableUpdatedMap);
updatedTable = response.getFirstEntityUpdated(); updatedTable = response.getFirstUpdatedEntityByTypeName(tableUpdated.getTypeName());
validateAttributes(updatedTable); validateAttributes(tableUpdatedMap, updatedTable);
//Swap elements //Swap elements
tableUpdatedMap.clear();
columns.clear(); columns.clear();
columns.add(col4);
columns.add(col3);
tableUpdated.setAttribute(COLUMNS_ATTR_NAME, columns); tableUpdated.setAttribute(COLUMNS_ATTR_NAME, columns);
tableUpdatedMap.put(tableUpdated.getGuid(), tableUpdated);
tableUpdatedMap.put(col3.getGuid(), col3);
tableUpdatedMap.put(col4.getGuid(), col4);
columns.add(col4.getAtlasObjectId());
columns.add(col3.getAtlasObjectId());
init(); init();
response = entityStore.createOrUpdate(tableUpdated); response = entityStore.createOrUpdate(tableUpdatedMap);
updatedTable = response.getFirstEntityUpdated(); updatedTable = response.getFirstUpdatedEntityByTypeName(tableUpdated.getTypeName());
Assert.assertEquals(((List<AtlasEntity>) updatedTable.getAttribute(COLUMNS_ATTR_NAME)).size(), 2); Assert.assertEquals(((List<AtlasObjectId>) updatedTable.getAttribute(COLUMNS_ATTR_NAME)).size(), 2);
assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 1); //col1 is deleted assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 1); //col1 is deleted
//Update array column to null //Update array column to null
tableUpdated.setAttribute(COLUMNS_ATTR_NAME, null); tableUpdated.setAttribute(COLUMNS_ATTR_NAME, null);
init(); init();
response = entityStore.createOrUpdate(tableUpdated); response = entityStore.createOrUpdate(tableUpdatedMap);
updatedTable = response.getFirstEntityUpdated(); updatedTable = response.getFirstUpdatedEntityByTypeName(tableUpdated.getTypeName());
validateAttributes(updatedTable); validateAttributes(tableUpdatedMap, updatedTable);
assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 2); assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.DELETE).size(), 2);
} }
...@@ -246,6 +269,7 @@ public class AtlasEntityStoreV1Test { ...@@ -246,6 +269,7 @@ public class AtlasEntityStoreV1Test {
@Test(dependsOnMethods = "testCreate") @Test(dependsOnMethods = "testCreate")
public void testUpdateEntityWithMap() throws Exception { public void testUpdateEntityWithMap() throws Exception {
final Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
final AtlasEntity tableClone = new AtlasEntity(tableEntity); final AtlasEntity tableClone = new AtlasEntity(tableEntity);
final Map<String, AtlasStruct> partsMap = new HashMap<>(); final Map<String, AtlasStruct> partsMap = new HashMap<>();
partsMap.put("part0", new AtlasStruct(TestUtils.PARTITION_STRUCT_TYPE, partsMap.put("part0", new AtlasStruct(TestUtils.PARTITION_STRUCT_TYPE,
...@@ -255,11 +279,13 @@ public class AtlasEntityStoreV1Test { ...@@ -255,11 +279,13 @@ public class AtlasEntityStoreV1Test {
tableClone.setAttribute("partitionsMap", partsMap); tableClone.setAttribute("partitionsMap", partsMap);
tableCloneMap.put(tableClone.getGuid(), tableClone);
init(); init();
EntityMutationResponse response = entityStore.createOrUpdate(tableClone); EntityMutationResponse response = entityStore.createOrUpdate(tableCloneMap);
final AtlasEntityHeader tableDefinition1 = response.getFirstEntityUpdated(); final AtlasEntityHeader tableDefinition1 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition1); validateAttributes(tableCloneMap, tableDefinition1);
Assert.assertTrue(partsMap.get("part0").equals(((Map<String, AtlasStruct>) tableDefinition1.getAttribute("partitionsMap")).get("part0"))); Assert.assertTrue(partsMap.get("part0").equals(((Map<String, AtlasStruct>) tableDefinition1.getAttribute("partitionsMap")).get("part0")));
...@@ -271,9 +297,9 @@ public class AtlasEntityStoreV1Test { ...@@ -271,9 +297,9 @@ public class AtlasEntityStoreV1Test {
tableClone.setAttribute("partitionsMap", partsMap); tableClone.setAttribute("partitionsMap", partsMap);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition2 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition2 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition2); validateAttributes(tableCloneMap, tableDefinition2);
assertEquals(((Map<String, AtlasStruct>) tableDefinition2.getAttribute("partitionsMap")).size(), 2); assertEquals(((Map<String, AtlasStruct>) tableDefinition2.getAttribute("partitionsMap")).size(), 2);
Assert.assertTrue(partsMap.get("part1").equals(((Map<String, AtlasStruct>) tableDefinition2.getAttribute("partitionsMap")).get("part1"))); Assert.assertTrue(partsMap.get("part1").equals(((Map<String, AtlasStruct>) tableDefinition2.getAttribute("partitionsMap")).get("part1")));
...@@ -287,9 +313,9 @@ public class AtlasEntityStoreV1Test { ...@@ -287,9 +313,9 @@ public class AtlasEntityStoreV1Test {
tableClone.setAttribute("partitionsMap", partsMap); tableClone.setAttribute("partitionsMap", partsMap);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition3 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition3 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition3); validateAttributes(tableCloneMap, tableDefinition3);
assertEquals(((Map<String, AtlasStruct>) tableDefinition3.getAttribute("partitionsMap")).size(), 2); assertEquals(((Map<String, AtlasStruct>) tableDefinition3.getAttribute("partitionsMap")).size(), 2);
Assert.assertNull(((Map<String, AtlasStruct>) tableDefinition3.getAttribute("partitionsMap")).get("part0")); Assert.assertNull(((Map<String, AtlasStruct>) tableDefinition3.getAttribute("partitionsMap")).get("part0"));
...@@ -299,9 +325,9 @@ public class AtlasEntityStoreV1Test { ...@@ -299,9 +325,9 @@ public class AtlasEntityStoreV1Test {
init(); init();
AtlasStruct partition2 = partsMap.get("part2"); AtlasStruct partition2 = partsMap.get("part2");
partition2.setAttribute(TestUtilsV2.NAME, "test2Updated"); partition2.setAttribute(TestUtilsV2.NAME, "test2Updated");
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
final AtlasEntityHeader tableDefinition4 = response.getFirstEntityUpdated(); final AtlasEntityHeader tableDefinition4 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition4); validateAttributes(tableCloneMap, tableDefinition4);
assertEquals(((Map<String, AtlasStruct>) tableDefinition4.getAttribute("partitionsMap")).size(), 2); assertEquals(((Map<String, AtlasStruct>) tableDefinition4.getAttribute("partitionsMap")).size(), 2);
Assert.assertNull(((Map<String, AtlasStruct>) tableDefinition4.getAttribute("partitionsMap")).get("part0")); Assert.assertNull(((Map<String, AtlasStruct>) tableDefinition4.getAttribute("partitionsMap")).get("part0"));
...@@ -312,16 +338,23 @@ public class AtlasEntityStoreV1Test { ...@@ -312,16 +338,23 @@ public class AtlasEntityStoreV1Test {
//Test map pointing to a class //Test map pointing to a class
final Map<String, AtlasEntity> columnsMap = new HashMap<>(); final Map<String, AtlasObjectId> columnsMap = new HashMap<>();
Map<String, AtlasEntity> col0TypeMap = new HashMap<>();
AtlasEntity col0Type = new AtlasEntity(TestUtilsV2.COLUMN_TYPE, AtlasEntity col0Type = new AtlasEntity(TestUtilsV2.COLUMN_TYPE,
new HashMap<String, Object>() {{ new HashMap<String, Object>() {{
put(TestUtilsV2.NAME, "test1"); put(TestUtilsV2.NAME, "test1");
put("type", "string"); put("type", "string");
put("table", new AtlasObjectId(TABLE_TYPE, tableDefinition1.getGuid())); put("table", new AtlasObjectId(TABLE_TYPE, tableDefinition1.getGuid()));
}}); }});
col0TypeMap.put(col0Type.getGuid(), col0Type);
init(); init();
entityStore.createOrUpdate(col0Type); entityStore.createOrUpdate(col0TypeMap);
Map<String, AtlasEntity> col1TypeMap = new HashMap<>();
AtlasEntity col1Type = new AtlasEntity(TestUtils.COLUMN_TYPE, AtlasEntity col1Type = new AtlasEntity(TestUtils.COLUMN_TYPE,
new HashMap<String, Object>() {{ new HashMap<String, Object>() {{
put(TestUtilsV2.NAME, "test2"); put(TestUtilsV2.NAME, "test2");
...@@ -330,43 +363,50 @@ public class AtlasEntityStoreV1Test { ...@@ -330,43 +363,50 @@ public class AtlasEntityStoreV1Test {
}}); }});
init(); init();
entityStore.createOrUpdate(col1Type); col1TypeMap.put(col1Type.getGuid(), col1Type);
entityStore.createOrUpdate(col1TypeMap);
AtlasObjectId col0Id = new AtlasObjectId(col0Type.getTypeName(), col0Type.getGuid());
AtlasObjectId col1Id = new AtlasObjectId(col1Type.getTypeName(), col1Type.getGuid());
columnsMap.put("col0", col0Id);
columnsMap.put("col1", col1Id);
tableCloneMap.put(col0Type.getGuid(), col0Type);
tableCloneMap.put(col1Type.getGuid(), col1Type);
columnsMap.put("col0", col0Type);
columnsMap.put("col1", col1Type);
tableClone.setAttribute(TestUtils.COLUMNS_MAP, columnsMap); tableClone.setAttribute(TestUtils.COLUMNS_MAP, columnsMap);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition5 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition5 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition5); validateAttributes(tableCloneMap, tableDefinition5);
//Swap elements //Swap elements
columnsMap.clear(); columnsMap.clear();
columnsMap.put("col0", col1Type); columnsMap.put("col0", col1Id);
columnsMap.put("col1", col0Type); columnsMap.put("col1", col0Id);
tableClone.setAttribute(TestUtils.COLUMNS_MAP, columnsMap); tableClone.setAttribute(TestUtils.COLUMNS_MAP, columnsMap);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition6 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition6 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition6); validateAttributes(tableCloneMap, tableDefinition6);
//Drop the first key and change the class type as well to col0 //Drop the first key and change the class type as well to col0
columnsMap.clear(); columnsMap.clear();
columnsMap.put("col0", col0Type); columnsMap.put("col0", col0Id);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition7 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition7 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition7); validateAttributes(tableCloneMap, tableDefinition7);
//Clear state //Clear state
tableClone.setAttribute(TestUtils.COLUMNS_MAP, null); tableClone.setAttribute(TestUtils.COLUMNS_MAP, null);
init(); init();
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition8 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition8 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition8); validateAttributes(tableCloneMap, tableDefinition8);
} }
@Test(dependsOnMethods = "testCreate") @Test(dependsOnMethods = "testCreate")
...@@ -374,17 +414,19 @@ public class AtlasEntityStoreV1Test { ...@@ -374,17 +414,19 @@ public class AtlasEntityStoreV1Test {
//clear state //clear state
init(); init();
Map<String, AtlasEntity> entityCloneMap = new HashMap<>();
AtlasEntity entityClone = new AtlasEntity(tableEntity); AtlasEntity entityClone = new AtlasEntity(tableEntity);
entityCloneMap.put(entityClone.getGuid(), entityClone);
//Add a new entry //Add a new entry
Map<String, String> paramsMap = (Map<String, String>) entityClone.getAttribute("parametersMap"); Map<String, String> paramsMap = (Map<String, String>) entityClone.getAttribute("parametersMap");
paramsMap.put("newParam", "value"); paramsMap.put("newParam", "value");
entityClone.setAttribute("parametersMap", paramsMap); entityClone.setAttribute("parametersMap", paramsMap);
EntityMutationResponse response = entityStore.createOrUpdate(entityClone); EntityMutationResponse response = entityStore.createOrUpdate(entityCloneMap);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1); validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
AtlasEntityHeader tableEntity = response.getFirstEntityUpdated(); AtlasEntityHeader tableEntity = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableEntity); validateAttributes(entityCloneMap, tableEntity);
//clear state //clear state
init(); init();
...@@ -393,10 +435,10 @@ public class AtlasEntityStoreV1Test { ...@@ -393,10 +435,10 @@ public class AtlasEntityStoreV1Test {
paramsMap.remove("key1"); paramsMap.remove("key1");
entityClone.setAttribute("parametersMap", paramsMap); entityClone.setAttribute("parametersMap", paramsMap);
response = entityStore.createOrUpdate(entityClone); response = entityStore.createOrUpdate(entityCloneMap);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1); validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
tableEntity = response.getFirstEntityUpdated(); tableEntity = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableEntity); validateAttributes(entityCloneMap, tableEntity);
} }
@Test(dependsOnMethods = "testCreate") @Test(dependsOnMethods = "testCreate")
...@@ -412,10 +454,10 @@ public class AtlasEntityStoreV1Test { ...@@ -412,10 +454,10 @@ public class AtlasEntityStoreV1Test {
List<AtlasStruct> partitions = new ArrayList<AtlasStruct>(){{ add(partition1); add(partition2); }}; List<AtlasStruct> partitions = new ArrayList<AtlasStruct>(){{ add(partition1); add(partition2); }};
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
EntityMutationResponse response = entityStore.createOrUpdate(tableEntity); EntityMutationResponse response = entityStore.createOrUpdate(tableEntityMap);
AtlasEntityHeader tableDefinition = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
//add a new element to array of struct //add a new element to array of struct
init(); init();
...@@ -423,25 +465,25 @@ public class AtlasEntityStoreV1Test { ...@@ -423,25 +465,25 @@ public class AtlasEntityStoreV1Test {
partition3.setAttribute(TestUtilsV2.NAME, "part3"); partition3.setAttribute(TestUtilsV2.NAME, "part3");
partitions.add(partition3); partitions.add(partition3);
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
response = entityStore.createOrUpdate(tableEntity); response = entityStore.createOrUpdate(tableEntityMap);
tableDefinition = response.getFirstEntityUpdated(); tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
//remove one of the struct values //remove one of the struct values
init(); init();
partitions.remove(1); partitions.remove(1);
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
response = entityStore.createOrUpdate(tableEntity); response = entityStore.createOrUpdate(tableEntityMap);
tableDefinition = response.getFirstEntityUpdated(); tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
//Update struct value within array of struct //Update struct value within array of struct
init(); init();
partitions.get(0).setAttribute(TestUtilsV2.NAME, "part4"); partitions.get(0).setAttribute(TestUtilsV2.NAME, "part4");
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
response = entityStore.createOrUpdate(tableEntity); response = entityStore.createOrUpdate(tableEntityMap);
tableDefinition = response.getFirstEntityUpdated(); tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
//add a repeated element to array of struct //add a repeated element to array of struct
...@@ -450,17 +492,17 @@ public class AtlasEntityStoreV1Test { ...@@ -450,17 +492,17 @@ public class AtlasEntityStoreV1Test {
partition4.setAttribute(TestUtilsV2.NAME, "part4"); partition4.setAttribute(TestUtilsV2.NAME, "part4");
partitions.add(partition4); partitions.add(partition4);
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
response = entityStore.createOrUpdate(tableEntity); response = entityStore.createOrUpdate(tableEntityMap);
tableDefinition = response.getFirstEntityUpdated(); tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
// Remove all elements. Should set array attribute to null // Remove all elements. Should set array attribute to null
init(); init();
partitions.clear(); partitions.clear();
tableEntity.setAttribute("partitions", partitions); tableEntity.setAttribute("partitions", partitions);
response = entityStore.createOrUpdate(tableEntity); response = entityStore.createOrUpdate(tableEntityMap);
tableDefinition = response.getFirstEntityUpdated(); tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition); validateAttributes(tableEntityMap, tableDefinition);
} }
...@@ -468,53 +510,57 @@ public class AtlasEntityStoreV1Test { ...@@ -468,53 +510,57 @@ public class AtlasEntityStoreV1Test {
public void testStructs() throws Exception { public void testStructs() throws Exception {
init(); init();
Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
AtlasEntity tableClone = new AtlasEntity(tableEntity); AtlasEntity tableClone = new AtlasEntity(tableEntity);
AtlasStruct serdeInstance = new AtlasStruct(TestUtils.SERDE_TYPE); AtlasStruct serdeInstance = new AtlasStruct(TestUtils.SERDE_TYPE);
serdeInstance.setAttribute(TestUtilsV2.NAME, "serde1Name"); serdeInstance.setAttribute(TestUtilsV2.NAME, "serde1Name");
serdeInstance.setAttribute("serde", "test"); serdeInstance.setAttribute("serde", "test");
serdeInstance.setAttribute("description", "testDesc"); serdeInstance.setAttribute("description", "testDesc");
tableClone.setAttribute("serde1", serdeInstance); tableClone.setAttribute("serde1", serdeInstance);
tableClone.setAttribute("database", dbEntity); tableClone.setAttribute("database", new AtlasObjectId(dbEntity.getTypeName(), new HashMap<String, Object>() {{
put(TestUtilsV2.NAME, dbEntity.getAttribute(TestUtilsV2.NAME));
}}));
tableCloneMap.put(tableClone.getGuid(), tableClone);
EntityMutationResponse response = entityStore.createOrUpdate(tableClone); EntityMutationResponse response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition1 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition1 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition1); validateAttributes(tableCloneMap, tableDefinition1);
//update struct attribute //update struct attribute
init(); init();
serdeInstance.setAttribute("serde", "testUpdated"); serdeInstance.setAttribute("serde", "testUpdated");
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition2 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition2 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
validateAttributes(tableDefinition2); validateAttributes(tableCloneMap, tableDefinition2);
//set to null //set to null
init(); init();
tableClone.setAttribute("description", null); tableClone.setAttribute("description", null);
response = entityStore.createOrUpdate(tableClone); response = entityStore.createOrUpdate(tableCloneMap);
AtlasEntityHeader tableDefinition3 = response.getFirstEntityUpdated(); AtlasEntityHeader tableDefinition3 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
Assert.assertNull(tableDefinition3.getAttribute("description")); Assert.assertNull(tableDefinition3.getAttribute("description"));
validateAttributes(tableDefinition3); validateAttributes(tableCloneMap, tableDefinition3);
} }
private AtlasEntity clearSubOrdinates(List<AtlasEntity> employees, int index) { // private AtlasEntity clearSubOrdinates(List<AtlasObjectId> employees, int index) {
//
AtlasEntity ret = null; // AtlasEntity ret = null;
List<AtlasEntity> subOrdinates = (List<AtlasEntity>) employees.get(index).getAttribute("subordinates"); // AtlasObjectId employee = employees.get(index);
List<AtlasEntity> subOrdClone = new ArrayList<>(subOrdinates); // AtlasEntity subOrdClone = new ArrayList<>(subOrdinates);
ret = subOrdClone.remove(index); // ret = subOrdClone.remove(index);
//
employees.get(index).setAttribute("subordinates", subOrdClone); // employees.get(index).setAttribute("subordinates", subOrdClone);
return ret; // return ret;
} // }
//
private int addSubordinate(AtlasEntity manager, AtlasEntity employee) { // private int addSubordinate(AtlasEntity manager, AtlasEntity employee) {
List<AtlasEntity> subOrdinates = (List<AtlasEntity>) manager.getAttribute("subordinates"); // List<AtlasEntity> subOrdinates = (List<AtlasEntity>) manager.getAttribute("subordinates");
subOrdinates.add(employee); // subOrdinates.add(employee);
//
manager.setAttribute("subordinates", subOrdinates); // manager.setAttribute("subordinates", subOrdinates);
// return subOrdinates.size() - 1;
return subOrdinates.size() - 1; // }
}
private void validateMutationResponse(EntityMutationResponse response, EntityMutations.EntityOperation op, int expectedNumCreated) { private void validateMutationResponse(EntityMutationResponse response, EntityMutations.EntityOperation op, int expectedNumCreated) {
List<AtlasEntityHeader> entitiesCreated = response.getEntitiesByOperation(op); List<AtlasEntityHeader> entitiesCreated = response.getEntitiesByOperation(op);
...@@ -522,13 +568,13 @@ public class AtlasEntityStoreV1Test { ...@@ -522,13 +568,13 @@ public class AtlasEntityStoreV1Test {
Assert.assertEquals(entitiesCreated.size(), expectedNumCreated); Assert.assertEquals(entitiesCreated.size(), expectedNumCreated);
} }
private void validateAttributes(AtlasEntityHeader entity) throws AtlasBaseException, AtlasException { private void validateAttributes(Map<String, AtlasEntity> entityMap, AtlasEntityHeader entity) throws AtlasBaseException, AtlasException {
//TODO : Use the older API for get until new instance API is ready and validated //TODO : Use the older API for get until new instance API is ready and validated
ITypedReferenceableInstance instance = metadataService.getEntityDefinition(entity.getGuid()); ITypedReferenceableInstance instance = metadataService.getEntityDefinition(entity.getGuid());
assertAttributes(entity, instance); assertAttributes(entityMap, entity, instance);
} }
private void assertAttributes(AtlasStruct entity, IInstance instance) throws AtlasBaseException, AtlasException { private void assertAttributes(Map<String, AtlasEntity> entityMap, AtlasStruct entity, IInstance instance) throws AtlasBaseException, AtlasException {
LOG.debug("Asserting type : " + entity.getTypeName()); LOG.debug("Asserting type : " + entity.getTypeName());
AtlasStructType entityType = (AtlasStructType) typeRegistry.getType(instance.getTypeName()); AtlasStructType entityType = (AtlasStructType) typeRegistry.getType(instance.getTypeName());
for (String attrName : entity.getAttributes().keySet()) { for (String attrName : entity.getAttributes().keySet()) {
...@@ -536,11 +582,11 @@ public class AtlasEntityStoreV1Test { ...@@ -536,11 +582,11 @@ public class AtlasEntityStoreV1Test {
Object expected = instance.get(attrName); Object expected = instance.get(attrName);
AtlasType attrType = entityType.getAttributeType(attrName); AtlasType attrType = entityType.getAttributeType(attrName);
assertAttribute(actual, expected, attrType, attrName); assertAttribute(entityMap, actual, expected, attrType, attrName);
} }
} }
private void assertAttribute(Object actual, Object expected, AtlasType attributeType, String attrName) throws AtlasBaseException, AtlasException { private void assertAttribute(Map<String, AtlasEntity> actualEntityMap, Object actual, Object expected, AtlasType attributeType, String attrName) throws AtlasBaseException, AtlasException {
LOG.debug("Asserting attribute : " + attrName); LOG.debug("Asserting attribute : " + attrName);
switch(attributeType.getTypeCategory()) { switch(attributeType.getTypeCategory()) {
...@@ -550,9 +596,16 @@ public class AtlasEntityStoreV1Test { ...@@ -550,9 +596,16 @@ public class AtlasEntityStoreV1Test {
Assert.assertTrue(AtlasEntity.isAssigned(guid)); Assert.assertTrue(AtlasEntity.isAssigned(guid));
} else { } else {
ReferenceableInstance expectedInstance = (ReferenceableInstance) expected; ReferenceableInstance expectedInstance = (ReferenceableInstance) expected;
AtlasEntity actualInstance = (AtlasEntity) actual; if (actual instanceof AtlasObjectId) {
if ( actualInstance != null) { AtlasEntity actualEntity = actualEntityMap.get(((AtlasObjectId) actual).getGuid());
assertAttributes(actualInstance, expectedInstance); if (actualEntity != null) {
assertAttributes(actualEntityMap, actualEntity, expectedInstance);
}
} else {
AtlasEntity actualInstance = (AtlasEntity) actual;
if (actualInstance != null) {
assertAttributes(actualEntityMap , actualInstance, expectedInstance);
}
} }
} }
break; break;
...@@ -575,7 +628,7 @@ public class AtlasEntityStoreV1Test { ...@@ -575,7 +628,7 @@ public class AtlasEntityStoreV1Test {
if (expectedMap != null && actualMap != null) { if (expectedMap != null && actualMap != null) {
Assert.assertEquals(actualMap.size(), expectedMap.size()); Assert.assertEquals(actualMap.size(), expectedMap.size());
for (Object key : actualMap.keySet()) { for (Object key : actualMap.keySet()) {
assertAttribute(actualMap.get(key), expectedMap.get(key), valueType, attrName); assertAttribute(actualEntityMap, actualMap.get(key), expectedMap.get(key), valueType, attrName);
} }
} }
break; break;
...@@ -588,14 +641,14 @@ public class AtlasEntityStoreV1Test { ...@@ -588,14 +641,14 @@ public class AtlasEntityStoreV1Test {
if (CollectionUtils.isNotEmpty(actualList)) { if (CollectionUtils.isNotEmpty(actualList)) {
//actual list could have deleted entities . Hence size may not match. //actual list could have deleted entities . Hence size may not match.
for (int i = 0; i < actualList.size(); i++) { for (int i = 0; i < actualList.size(); i++) {
assertAttribute(actualList.get(i), expectedList.get(i), elemType, attrName); assertAttribute(actualEntityMap, actualList.get(i), expectedList.get(i), elemType, attrName);
} }
} }
break; break;
case STRUCT: case STRUCT:
StructInstance structInstance = (StructInstance) expected; StructInstance structInstance = (StructInstance) expected;
AtlasStruct newStructVal = (AtlasStruct) actual; AtlasStruct newStructVal = (AtlasStruct) actual;
assertAttributes(newStructVal, structInstance); assertAttributes(actualEntityMap, newStructVal, structInstance);
break; break;
default: default:
Assert.fail("Unknown type category"); Assert.fail("Unknown type category");
...@@ -607,17 +660,21 @@ public class AtlasEntityStoreV1Test { ...@@ -607,17 +660,21 @@ public class AtlasEntityStoreV1Test {
init(); init();
//Create new db instance //Create new db instance
final AtlasEntity databaseInstance = TestUtilsV2.createDBEntity(); final Map<String, AtlasEntity> databaseInstance = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityStore.createOrUpdate(databaseInstance); EntityMutationResponse response = entityStore.createOrUpdate(databaseInstance);
final AtlasEntityHeader dbCreated = response.getFirstEntityCreated(); final AtlasEntityHeader dbCreated = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
init(); init();
Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
AtlasEntity tableClone = new AtlasEntity(tableEntity); AtlasEntity tableClone = new AtlasEntity(tableEntity);
tableClone.setAttribute("database", new AtlasObjectId(TestUtils.DATABASE_TYPE, dbCreated.getGuid())); tableClone.setAttribute("database", new AtlasObjectId(TestUtils.DATABASE_TYPE, dbCreated.getGuid()));
response = entityStore.createOrUpdate(tableClone);
final AtlasEntityHeader tableDefinition = response.getFirstEntityUpdated();
tableCloneMap.put(dbCreated.getGuid(), databaseInstance.values().iterator().next());
tableCloneMap.put(tableClone.getGuid(), tableClone);
response = entityStore.createOrUpdate(tableCloneMap);
final AtlasEntityHeader tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
Assert.assertNotNull(tableDefinition.getAttribute("database")); Assert.assertNotNull(tableDefinition.getAttribute("database"));
Assert.assertEquals(((AtlasObjectId) tableDefinition.getAttribute("database")).getGuid(), dbCreated.getGuid()); Assert.assertEquals(((AtlasObjectId) tableDefinition.getAttribute("database")).getGuid(), dbCreated.getGuid());
} }
...@@ -625,9 +682,9 @@ public class AtlasEntityStoreV1Test { ...@@ -625,9 +682,9 @@ public class AtlasEntityStoreV1Test {
@Test @Test
public void testCheckOptionalAttrValueRetention() throws Exception { public void testCheckOptionalAttrValueRetention() throws Exception {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityStore.createOrUpdate(dbEntity); EntityMutationResponse response = entityStore.createOrUpdate(dbEntityMap);
AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated(); AtlasEntityHeader firstEntityCreated = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
//The optional boolean attribute should have a non-null value //The optional boolean attribute should have a non-null value
final String isReplicatedAttr = "isReplicated"; final String isReplicatedAttr = "isReplicated";
...@@ -638,13 +695,16 @@ public class AtlasEntityStoreV1Test { ...@@ -638,13 +695,16 @@ public class AtlasEntityStoreV1Test {
//Update to true //Update to true
init(); init();
AtlasEntity dbEntity = dbEntityMap.values().iterator().next();
dbEntity.setAttribute(isReplicatedAttr, Boolean.TRUE); dbEntity.setAttribute(isReplicatedAttr, Boolean.TRUE);
//Update array //Update array
final HashMap<String, String> params = new HashMap<String, String>() {{ put("param1", "val1"); put("param2", "val2"); }}; final HashMap<String, String> params = new HashMap<String, String>() {{ put("param1", "val1"); put("param2", "val2"); }};
dbEntity.setAttribute(paramsAttr, params); dbEntity.setAttribute(paramsAttr, params);
//Complete update //Complete update
response = entityStore.createOrUpdate(dbEntity);
AtlasEntityHeader firstEntityUpdated = response.getFirstEntityUpdated(); dbEntityMap.put(dbEntity.getGuid(), dbEntity);
response = entityStore.createOrUpdate(dbEntityMap);
AtlasEntityHeader firstEntityUpdated = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
Assert.assertNotNull(firstEntityUpdated.getAttribute(isReplicatedAttr)); Assert.assertNotNull(firstEntityUpdated.getAttribute(isReplicatedAttr));
Assert.assertEquals(firstEntityUpdated.getAttribute(isReplicatedAttr), Boolean.TRUE); Assert.assertEquals(firstEntityUpdated.getAttribute(isReplicatedAttr), Boolean.TRUE);
...@@ -684,6 +744,8 @@ public class AtlasEntityStoreV1Test { ...@@ -684,6 +744,8 @@ public class AtlasEntityStoreV1Test {
typeDefStore.createEntityDef(typeDefinition); typeDefStore.createEntityDef(typeDefinition);
//verify that entity can be created with reserved characters in string value, array value and map key and value //verify that entity can be created with reserved characters in string value, array value and map key and value
Map<String, AtlasEntity> entityCloneMap = new HashMap<>();
AtlasEntity entity = new AtlasEntity(); AtlasEntity entity = new AtlasEntity();
entity.setAttribute(strAttrName, randomStrWithReservedChars()); entity.setAttribute(strAttrName, randomStrWithReservedChars());
entity.setAttribute(arrayAttrName, new String[]{randomStrWithReservedChars()}); entity.setAttribute(arrayAttrName, new String[]{randomStrWithReservedChars()});
...@@ -691,9 +753,10 @@ public class AtlasEntityStoreV1Test { ...@@ -691,9 +753,10 @@ public class AtlasEntityStoreV1Test {
put(randomStrWithReservedChars(), randomStrWithReservedChars()); put(randomStrWithReservedChars(), randomStrWithReservedChars());
}}); }});
final EntityMutationResponse response = entityStore.createOrUpdate(entity); entityCloneMap.put(entity.getGuid(), entity);
final EntityMutationResponse response = entityStore.createOrUpdate(entityCloneMap);
final AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated(); final AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated();
validateAttributes(firstEntityCreated); validateAttributes(entityCloneMap, firstEntityCreated);
//Verify that search with reserved characters works - for string attribute //Verify that search with reserved characters works - for string attribute
...@@ -711,11 +774,12 @@ public class AtlasEntityStoreV1Test { ...@@ -711,11 +774,12 @@ public class AtlasEntityStoreV1Test {
@Test(expectedExceptions = AtlasBaseException.class) @Test(expectedExceptions = AtlasBaseException.class)
public void testCreateRequiredAttrNull() throws Exception { public void testCreateRequiredAttrNull() throws Exception {
//Update required attribute //Update required attribute
Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
AtlasEntity tableEntity = new AtlasEntity(TestUtilsV2.TABLE_TYPE); AtlasEntity tableEntity = new AtlasEntity(TestUtilsV2.TABLE_TYPE);
tableEntity.setAttribute(TestUtilsV2.NAME, "table_" + TestUtils.randomString()); tableEntity.setAttribute(TestUtilsV2.NAME, "table_" + TestUtils.randomString());
tableCloneMap.put(tableEntity.getGuid(), tableEntity);
entityStore.createOrUpdate(tableEntity); entityStore.createOrUpdate(tableCloneMap);
Assert.fail("Expected exception while creating with required attribute null"); Assert.fail("Expected exception while creating with required attribute null");
} }
} }
...@@ -38,7 +38,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter { ...@@ -38,7 +38,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Collection fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Collection fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
Collection ret = null; Collection ret = null;
if (v1Obj != null) { if (v1Obj != null) {
...@@ -57,7 +57,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter { ...@@ -57,7 +57,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter {
Collection v1List = (Collection) v1Obj; Collection v1List = (Collection) v1Obj;
for (Object v1Elem : v1List) { for (Object v1Elem : v1List) {
Object convertedVal = elemConverter.fromV1ToV2(v1Elem, elemType); Object convertedVal = elemConverter.fromV1ToV2(v1Elem, elemType, ctx);
ret.add(convertedVal); ret.add(convertedVal);
} }
...@@ -67,7 +67,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter { ...@@ -67,7 +67,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Collection fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Collection fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
Collection ret = null; Collection ret = null;
if (v2Obj != null) { if (v2Obj != null) {
...@@ -86,7 +86,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter { ...@@ -86,7 +86,7 @@ public class AtlasArrayFormatConverter extends AtlasAbstractFormatConverter {
Collection v2List = (Collection) v2Obj; Collection v2List = (Collection) v2Obj;
for (Object v2Elem : v2List) { for (Object v2Elem : v2List) {
Object convertedVal = elemConverter.fromV2ToV1(v2Elem, elemType); Object convertedVal = elemConverter.fromV2ToV1(v2Elem, elemType, ctx);
ret.add(convertedVal); ret.add(convertedVal);
} }
......
...@@ -40,7 +40,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert ...@@ -40,7 +40,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert
} }
@Override @Override
public AtlasClassification fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public AtlasClassification fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
AtlasClassification ret = null; AtlasClassification ret = null;
if (v1Obj != null) { if (v1Obj != null) {
...@@ -51,7 +51,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert ...@@ -51,7 +51,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert
final Map v1Attribs = (Map) v1Map.get(ATTRIBUTES_PROPERTY_KEY); final Map v1Attribs = (Map) v1Map.get(ATTRIBUTES_PROPERTY_KEY);
if (MapUtils.isNotEmpty(v1Attribs)) { if (MapUtils.isNotEmpty(v1Attribs)) {
ret = new AtlasClassification(type.getTypeName(), fromV1ToV2(classificationType, v1Attribs)); ret = new AtlasClassification(type.getTypeName(), fromV1ToV2(classificationType, v1Attribs, ctx));
} else { } else {
ret = new AtlasClassification(type.getTypeName()); ret = new AtlasClassification(type.getTypeName());
} }
...@@ -65,7 +65,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert ...@@ -65,7 +65,7 @@ public class AtlasClassificationFormatConverter extends AtlasStructFormatConvert
LOG.error("IStruct.getValuesMap() failed", excp); LOG.error("IStruct.getValuesMap() failed", excp);
} }
ret = new AtlasClassification(type.getTypeName(), fromV1ToV2(classificationType, v1Attribs)); ret = new AtlasClassification(type.getTypeName(), fromV1ToV2(classificationType, v1Attribs, ctx));
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or IStruct", throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or IStruct",
v1Obj.getClass().getCanonicalName()); v1Obj.getClass().getCanonicalName());
......
...@@ -53,7 +53,7 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -53,7 +53,7 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
} }
@Override @Override
public Object fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Object fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext context) throws AtlasBaseException {
Object ret = null; Object ret = null;
if (v1Obj != null) { if (v1Obj != null) {
...@@ -67,13 +67,15 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -67,13 +67,15 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
IReferenceableInstance entity = (IReferenceableInstance) v1Obj; IReferenceableInstance entity = (IReferenceableInstance) v1Obj;
Map<String, Object> v1Attribs = null; Map<String, Object> v1Attribs = null;
ret = new AtlasObjectId(entity.getTypeName(), entity.getId()._getId());
try { try {
v1Attribs = entity.getValuesMap(); v1Attribs = entity.getValuesMap();
} catch (AtlasException excp) { } catch (AtlasException excp) {
LOG.error("IReferenceableInstance.getValuesMap() failed", excp); LOG.error("IReferenceableInstance.getValuesMap() failed", excp);
} }
AtlasEntityWithAssociations ret1 = new AtlasEntityWithAssociations(entity.getTypeName(), super.fromV1ToV2(entityType, v1Attribs)); AtlasEntityWithAssociations ret1 = new AtlasEntityWithAssociations(entity.getTypeName(), super.fromV1ToV2(entityType, v1Attribs, context));
ret1.setGuid(entity.getId()._getId()); ret1.setGuid(entity.getId()._getId());
ret1.setStatus(convertState(entity.getId().getState())); ret1.setStatus(convertState(entity.getId().getState()));
AtlasSystemAttributes systemAttributes = entity.getSystemAttributes(); AtlasSystemAttributes systemAttributes = entity.getSystemAttributes();
...@@ -90,16 +92,17 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -90,16 +92,17 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
for (String traitName : entity.getTraits()) { for (String traitName : entity.getTraits()) {
IStruct trait = entity.getTrait(traitName); IStruct trait = entity.getTrait(traitName);
AtlasType classifiType = typeRegistry.getType(traitName); AtlasType classifiType = typeRegistry.getType(traitName);
AtlasClassification classification = (AtlasClassification) traitConverter.fromV1ToV2(trait, classifiType); AtlasClassification classification = (AtlasClassification) traitConverter.fromV1ToV2(trait, classifiType, context);
classifications.add(classification); classifications.add(classification);
} }
ret1.setClassifications(classifications); ret1.setClassifications(classifications);
} }
ret = ret1;
context.addEntity(ret1);
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Id or IReferenceableInstance", throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "IReferenceableInstance",
v1Obj.getClass().getCanonicalName()); v1Obj.getClass().getCanonicalName());
} }
} }
...@@ -116,7 +119,7 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -116,7 +119,7 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
} }
@Override @Override
public Object fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext context) throws AtlasBaseException {
Object ret = null; Object ret = null;
if (v2Obj != null) { if (v2Obj != null) {
...@@ -136,15 +139,21 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter { ...@@ -136,15 +139,21 @@ public class AtlasEntityFormatConverter extends AtlasStructFormatConverter {
if (MapUtils.isEmpty(v2Attribs)) { if (MapUtils.isEmpty(v2Attribs)) {
ret = new Id(idStr, 0, typeName); ret = new Id(idStr, 0, typeName);
} else { } else {
ret = new Referenceable(idStr, typeName, super.fromV2ToV1(entityType, v2Attribs)); ret = new Referenceable(idStr, typeName, super.fromV2ToV1(entityType, v2Attribs, context));
} }
} else if (v2Obj instanceof AtlasEntity) { } else if (v2Obj instanceof AtlasEntity) {
AtlasEntity entity = (AtlasEntity) v2Obj; AtlasEntity entity = (AtlasEntity) v2Obj;
ret = new Referenceable(entity.getGuid(), entity.getTypeName(), ret = new Referenceable(entity.getGuid(), entity.getTypeName(),
fromV2ToV1(entityType, entity.getAttributes())); fromV2ToV1(entityType, entity.getAttributes(), context));
} else if (v2Obj instanceof AtlasObjectId) { // transient-id } else if (v2Obj instanceof AtlasObjectId) { // transient-id
ret = new Referenceable(((AtlasObjectId) v2Obj).getGuid(), type.getTypeName(), null); AtlasEntity entity = context.getById(((AtlasObjectId) v2Obj).getGuid());
if ( entity == null) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "Could not find entity ",
v2Obj.toString());
}
ret = this.fromV2ToV1(entity, typeRegistry.getType(((AtlasObjectId) v2Obj).getTypeName()), context);
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or AtlasEntity or String", throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or AtlasEntity or String",
v2Obj.getClass().getCanonicalName()); v2Obj.getClass().getCanonicalName());
......
...@@ -30,12 +30,12 @@ public class AtlasEnumFormatConverter extends AtlasAbstractFormatConverter { ...@@ -30,12 +30,12 @@ public class AtlasEnumFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Object fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Object fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
return type.getNormalizedValue(v1Obj); return type.getNormalizedValue(v1Obj);
} }
@Override @Override
public Object fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
return type.getNormalizedValue(v2Obj); return type.getNormalizedValue(v2Obj);
} }
} }
......
...@@ -20,12 +20,62 @@ package org.apache.atlas.web.adapters; ...@@ -20,12 +20,62 @@ package org.apache.atlas.web.adapters;
import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityWithAssociations;
import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasType;
import java.util.HashMap;
import java.util.Map;
public interface AtlasFormatConverter { public interface AtlasFormatConverter {
Object fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException; Object fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext context) throws AtlasBaseException;
Object fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException; Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext context) throws AtlasBaseException;
TypeCategory getTypeCategory(); TypeCategory getTypeCategory();
public static class ConverterContext {
private Map<String, AtlasEntityWithAssociations> entities = null;
public void addEntity(AtlasEntityWithAssociations entity) {
if (entities == null) {
entities = new HashMap<>();
}
entities.put(entity.getGuid(), entity);
}
public void addEntity(AtlasEntity entity) {
if (entities == null) {
entities = new HashMap<>();
}
entities.put(entity.getGuid(), new AtlasEntityWithAssociations(entity));
}
public boolean exists(AtlasEntityWithAssociations entity) {
return entities != null ? entities.containsKey(entity.getGuid()) : false;
}
public AtlasEntity getById(String guid) {
if( entities != null) {
return entities.get(guid);
}
return null;
}
public Map<String, AtlasEntityWithAssociations> getEntities() {
return entities;
}
public void addEntities(Map<String, AtlasEntity> entities) {
if (this.entities == null) {
this.entities = new HashMap<>(entities.size());
}
for (String entityId : entities.keySet()) {
this.entities.put(entityId, new AtlasEntityWithAssociations(entities.get(entityId)));
}
}
}
} }
...@@ -47,7 +47,11 @@ import org.apache.atlas.typesystem.exception.TypeNotFoundException; ...@@ -47,7 +47,11 @@ import org.apache.atlas.typesystem.exception.TypeNotFoundException;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map;
@Singleton @Singleton
public class AtlasInstanceRestAdapters { public class AtlasInstanceRestAdapters {
...@@ -63,19 +67,24 @@ public class AtlasInstanceRestAdapters { ...@@ -63,19 +67,24 @@ public class AtlasInstanceRestAdapters {
@Inject @Inject
private MetadataService metadataService; private MetadataService metadataService;
public ITypedReferenceableInstance[] getITypedReferenceables(List<AtlasEntity> entities) throws AtlasBaseException { public ITypedReferenceableInstance[] getITypedReferenceables(Collection<AtlasEntity> entities) throws AtlasBaseException {
ITypedReferenceableInstance[] entitiesInOldFormat = new ITypedReferenceableInstance[entities.size()]; ITypedReferenceableInstance[] entitiesInOldFormat = new ITypedReferenceableInstance[entities.size()];
AtlasFormatConverter.ConverterContext ctx = new AtlasFormatConverter.ConverterContext();
for(Iterator<AtlasEntity> i = entities.iterator(); i.hasNext(); ) {
ctx.addEntity(i.next());
}
Iterator<AtlasEntity> entityIterator = entities.iterator();
for (int i = 0; i < entities.size(); i++) { for (int i = 0; i < entities.size(); i++) {
ITypedReferenceableInstance typedInstance = getITypedReferenceable(entities.get(i)); ITypedReferenceableInstance typedInstance = getITypedReferenceable(entityIterator.next(), ctx);
entitiesInOldFormat[i] = typedInstance; entitiesInOldFormat[i] = typedInstance;
} }
return entitiesInOldFormat; return entitiesInOldFormat;
} }
public ITypedReferenceableInstance getITypedReferenceable(AtlasEntity entity) throws AtlasBaseException { public ITypedReferenceableInstance getITypedReferenceable(AtlasEntity entity, AtlasFormatConverter.ConverterContext ctx) throws AtlasBaseException {
Referenceable ref = getReferenceable(entity); Referenceable ref = getReferenceable(entity, ctx);
try { try {
return metadataService.getTypedReferenceableInstance(ref); return metadataService.getTypedReferenceableInstance(ref);
...@@ -85,10 +94,10 @@ public class AtlasInstanceRestAdapters { ...@@ -85,10 +94,10 @@ public class AtlasInstanceRestAdapters {
} }
} }
public Referenceable getReferenceable(AtlasEntity entity) throws AtlasBaseException { public Referenceable getReferenceable(AtlasEntity entity, final AtlasFormatConverter.ConverterContext ctx) throws AtlasBaseException {
AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.ENTITY); AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.ENTITY);
AtlasType entityType = typeRegistry.getType(entity.getTypeName()); AtlasType entityType = typeRegistry.getType(entity.getTypeName());
Referenceable ref = (Referenceable)converter.fromV2ToV1(entity, entityType); Referenceable ref = (Referenceable)converter.fromV2ToV1(entity, entityType, ctx);
return ref; return ref;
} }
...@@ -96,7 +105,7 @@ public class AtlasInstanceRestAdapters { ...@@ -96,7 +105,7 @@ public class AtlasInstanceRestAdapters {
public ITypedStruct getTrait(AtlasClassification classification) throws AtlasBaseException { public ITypedStruct getTrait(AtlasClassification classification) throws AtlasBaseException {
AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.CLASSIFICATION); AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.CLASSIFICATION);
AtlasType classificationType = typeRegistry.getType(classification.getTypeName()); AtlasType classificationType = typeRegistry.getType(classification.getTypeName());
Struct trait = (Struct)converter.fromV2ToV1(classification, classificationType); Struct trait = (Struct)converter.fromV2ToV1(classification, classificationType, new AtlasFormatConverter.ConverterContext());
try { try {
return metadataService.createTraitInstance(trait); return metadataService.createTraitInstance(trait);
...@@ -112,21 +121,22 @@ public class AtlasInstanceRestAdapters { ...@@ -112,21 +121,22 @@ public class AtlasInstanceRestAdapters {
if (classificationType == null) { if (classificationType == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.CLASSIFICATION.name(), classification.getTypeName()); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.CLASSIFICATION.name(), classification.getTypeName());
} }
AtlasClassification ret = (AtlasClassification)converter.fromV1ToV2(classification, classificationType); AtlasClassification ret = (AtlasClassification)converter.fromV1ToV2(classification, classificationType, new AtlasFormatConverter.ConverterContext());
return ret; return ret;
} }
public AtlasEntityWithAssociations getAtlasEntity(IReferenceableInstance referenceable) throws AtlasBaseException { public Map<String, AtlasEntityWithAssociations> getAtlasEntity(IReferenceableInstance referenceable) throws AtlasBaseException {
AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.ENTITY); AtlasFormatConverter converter = instanceFormatters.getConverter(TypeCategory.ENTITY);
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(referenceable.getTypeName()); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(referenceable.getTypeName());
if (entityType == null) { if (entityType == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), referenceable.getTypeName()); throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), referenceable.getTypeName());
} }
AtlasEntityWithAssociations ret = (AtlasEntityWithAssociations)converter.fromV1ToV2(referenceable, entityType); AtlasFormatConverter.ConverterContext ctx = new AtlasFormatConverter.ConverterContext();
converter.fromV1ToV2(referenceable, entityType, ctx);
return ret; return ctx.getEntities();
} }
......
...@@ -35,7 +35,7 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter { ...@@ -35,7 +35,7 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Map fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Map fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
Map ret = null; Map ret = null;
if (v1Obj != null) { if (v1Obj != null) {
...@@ -52,8 +52,8 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter { ...@@ -52,8 +52,8 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter {
for (Object key : v1Map.keySet()) { for (Object key : v1Map.keySet()) {
Object value = v1Map.get(key); Object value = v1Map.get(key);
Object v2Key = keyConverter.fromV1ToV2(key, keyType); Object v2Key = keyConverter.fromV1ToV2(key, keyType, ctx);
Object v2Value = valueConverter.fromV1ToV2(value, valueType); Object v2Value = valueConverter.fromV1ToV2(value, valueType, ctx);
ret.put(v2Key, v2Value); ret.put(v2Key, v2Value);
} }
...@@ -67,7 +67,7 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter { ...@@ -67,7 +67,7 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Map fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Map fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
Map ret = null; Map ret = null;
if (v2Obj != null) { if (v2Obj != null) {
...@@ -84,8 +84,8 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter { ...@@ -84,8 +84,8 @@ public class AtlasMapFormatConverter extends AtlasAbstractFormatConverter {
for (Object key : v1Map.keySet()) { for (Object key : v1Map.keySet()) {
Object value = v1Map.get(key); Object value = v1Map.get(key);
Object v2Key = keyConverter.fromV2ToV1(key, keyType); Object v2Key = keyConverter.fromV2ToV1(key, keyType, ctx);
Object v2Value = valueConverter.fromV2ToV1(value, valueType); Object v2Value = valueConverter.fromV2ToV1(value, valueType, ctx);
ret.put(v2Key, v2Value); ret.put(v2Key, v2Value);
} }
......
/**
* 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.web.adapters;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.type.AtlasType;
import org.apache.atlas.type.AtlasTypeRegistry;
import org.apache.atlas.typesystem.IReferenceableInstance;
import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.typesystem.persistence.Id;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Map;
public class
AtlasObjectIdConverter extends AtlasAbstractFormatConverter {
public AtlasObjectIdConverter(AtlasFormatConverters registry, AtlasTypeRegistry typeRegistry) {
this(registry, typeRegistry, TypeCategory.OBJECT_ID_TYPE);
}
protected AtlasObjectIdConverter(AtlasFormatConverters registry, AtlasTypeRegistry typeRegistry, TypeCategory typeCategory) {
super(registry, typeRegistry, typeCategory);
}
@Override
public Object fromV1ToV2(Object v1Obj, AtlasType type, AtlasFormatConverter.ConverterContext converterContext) throws AtlasBaseException {
Object ret = null;
if (v1Obj != null) {
if (v1Obj instanceof Id) {
Id id = (Id) v1Obj;
ret = new AtlasObjectId(id.getTypeName(), id._getId());
} else if (v1Obj instanceof IReferenceableInstance) {
IReferenceableInstance entity = (IReferenceableInstance) v1Obj;
ret = new AtlasObjectId(entity.getTypeName(), entity.getId()._getId());
}
}
return ret;
}
@Override
public Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext converterContext) throws AtlasBaseException {
Id ret = null;
if (v2Obj != null) {
if (v2Obj instanceof Map) {
Map v2Map = (Map) v2Obj;
String idStr = (String)v2Map.get(AtlasObjectId.KEY_GUID);
String typeName = type.getTypeName();
if (StringUtils.isEmpty(idStr)) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND);
}
ret = new Id(idStr, 0, typeName);
} else if (v2Obj instanceof AtlasObjectId) { // transient-id
ret = new Id(((AtlasObjectId) v2Obj).getGuid(), 0, type.getTypeName());
} else if (v2Obj instanceof AtlasEntity) {
AtlasEntity entity = (AtlasEntity) v2Obj;
ret = new Id(((AtlasObjectId) v2Obj).getGuid(), 0, type.getTypeName());
} else {
throw new AtlasBaseException(AtlasErrorCode.TYPE_CATEGORY_INVALID, type.getTypeCategory().name());
}
}
return ret;
}
}
...@@ -30,12 +30,12 @@ public class AtlasPrimitiveFormatConverter extends AtlasAbstractFormatConverter ...@@ -30,12 +30,12 @@ public class AtlasPrimitiveFormatConverter extends AtlasAbstractFormatConverter
} }
@Override @Override
public Object fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Object fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
return type.getNormalizedValue(v1Obj); return type.getNormalizedValue(v1Obj);
} }
@Override @Override
public Object fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext ctx) throws AtlasBaseException {
return type.getNormalizedValue(v2Obj); return type.getNormalizedValue(v2Obj);
} }
} }
......
...@@ -50,7 +50,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -50,7 +50,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Object fromV1ToV2(Object v1Obj, AtlasType type) throws AtlasBaseException { public Object fromV1ToV2(Object v1Obj, AtlasType type, ConverterContext converterContext) throws AtlasBaseException {
AtlasStruct ret = null; AtlasStruct ret = null;
if (v1Obj != null) { if (v1Obj != null) {
...@@ -61,7 +61,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -61,7 +61,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
final Map v1Attribs = (Map) v1Map.get(ATTRIBUTES_PROPERTY_KEY); final Map v1Attribs = (Map) v1Map.get(ATTRIBUTES_PROPERTY_KEY);
if (MapUtils.isNotEmpty(v1Attribs)) { if (MapUtils.isNotEmpty(v1Attribs)) {
ret = new AtlasStruct(type.getTypeName(), fromV1ToV2(structType, v1Attribs)); ret = new AtlasStruct(type.getTypeName(), fromV1ToV2(structType, v1Attribs, converterContext));
} else { } else {
ret = new AtlasStruct(type.getTypeName()); ret = new AtlasStruct(type.getTypeName());
} }
...@@ -75,7 +75,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -75,7 +75,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
LOG.error("IStruct.getValuesMap() failed", excp); LOG.error("IStruct.getValuesMap() failed", excp);
} }
ret = new AtlasStruct(type.getTypeName(), fromV1ToV2(structType, v1Attribs)); ret = new AtlasStruct(type.getTypeName(), fromV1ToV2(structType, v1Attribs, converterContext));
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or IStruct", v1Obj.getClass().getCanonicalName()); throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or IStruct", v1Obj.getClass().getCanonicalName());
} }
...@@ -85,7 +85,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -85,7 +85,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
} }
@Override @Override
public Object fromV2ToV1(Object v2Obj, AtlasType type) throws AtlasBaseException { public Object fromV2ToV1(Object v2Obj, AtlasType type, ConverterContext converterContext) throws AtlasBaseException {
Struct ret = null; Struct ret = null;
if (v2Obj != null) { if (v2Obj != null) {
...@@ -102,14 +102,14 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -102,14 +102,14 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
} }
if (MapUtils.isNotEmpty(v2Attribs)) { if (MapUtils.isNotEmpty(v2Attribs)) {
ret = new Struct(type.getTypeName(), fromV2ToV1(structType, v2Attribs)); ret = new Struct(type.getTypeName(), fromV2ToV1(structType, v2Attribs, converterContext));
} else { } else {
ret = new Struct(type.getTypeName()); ret = new Struct(type.getTypeName());
} }
} else if (v2Obj instanceof AtlasStruct) { } else if (v2Obj instanceof AtlasStruct) {
AtlasStruct struct = (AtlasStruct) v2Obj; AtlasStruct struct = (AtlasStruct) v2Obj;
ret = new Struct(type.getTypeName(), fromV2ToV1(structType, struct.getAttributes())); ret = new Struct(type.getTypeName(), fromV2ToV1(structType, struct.getAttributes(), converterContext));
} else { } else {
throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or AtlasStruct", v2Obj.getClass().getCanonicalName()); throw new AtlasBaseException(AtlasErrorCode.UNEXPECTED_TYPE, "Map or AtlasStruct", v2Obj.getClass().getCanonicalName());
} }
...@@ -118,7 +118,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -118,7 +118,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
return ret; return ret;
} }
protected Map<String, Object> fromV2ToV1(AtlasStructType structType, Map attributes) throws AtlasBaseException { protected Map<String, Object> fromV2ToV1(AtlasStructType structType, Map attributes, ConverterContext context) throws AtlasBaseException {
Map<String, Object> ret = null; Map<String, Object> ret = null;
if (MapUtils.isNotEmpty(attributes)) { if (MapUtils.isNotEmpty(attributes)) {
...@@ -132,11 +132,17 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -132,11 +132,17 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
continue; continue;
} }
AtlasFormatConverter attrConverter = converterRegistry.getConverter(attrType.getTypeCategory());
Object v2Value = attributes.get(attr.getName()); Object v2Value = attributes.get(attr.getName());
Object v1Value = attrConverter.fromV2ToV1(v2Value, attrType); Object v1Value = null;
AtlasFormatConverter attrConverter = null;
if (attrType.getTypeCategory() == TypeCategory.ENTITY && !attr.isContainedAttribute()) {
attrConverter = new AtlasObjectIdConverter(converterRegistry, typeRegistry);
v1Value = attrConverter.fromV2ToV1(v2Value, attrType, context);
} else {
attrConverter = converterRegistry.getConverter(attrType.getTypeCategory());
v1Value = attrConverter.fromV2ToV1(v2Value, attrType, context);
}
ret.put(attr.getName(), v1Value); ret.put(attr.getName(), v1Value);
} }
} }
...@@ -144,7 +150,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -144,7 +150,7 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
return ret; return ret;
} }
protected Map<String, Object> fromV1ToV2(AtlasStructType structType, Map attributes) throws AtlasBaseException { protected Map<String, Object> fromV1ToV2(AtlasStructType structType, Map attributes, ConverterContext context) throws AtlasBaseException {
Map<String, Object> ret = null; Map<String, Object> ret = null;
if (MapUtils.isNotEmpty(attributes)) { if (MapUtils.isNotEmpty(attributes)) {
...@@ -152,11 +158,23 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter { ...@@ -152,11 +158,23 @@ public class AtlasStructFormatConverter extends AtlasAbstractFormatConverter {
for (AtlasStructType.AtlasAttribute attr : structType.getAllAttributes().values()) { for (AtlasStructType.AtlasAttribute attr : structType.getAllAttributes().values()) {
AtlasType attrType = attr.getAttributeType(); AtlasType attrType = attr.getAttributeType();
AtlasFormatConverter attrConverter = converterRegistry.getConverter(attrType.getTypeCategory());
if (attrType == null) {
LOG.warn("ignored attribute {}.{}: failed to find AtlasType", structType.getTypeName(), attr.getName());
continue;
}
Object v1Value = attributes.get(attr.getName()); Object v1Value = attributes.get(attr.getName());
Object v2Value = attrConverter.fromV1ToV2(v1Value, attrType); Object v2Value = null;
AtlasFormatConverter attrConverter = null;
if (attrType.getTypeCategory() == TypeCategory.ENTITY && !attr.isContainedAttribute()) {
attrConverter = new AtlasObjectIdConverter(converterRegistry, typeRegistry);
v2Value = attrConverter.fromV1ToV2(v1Value, attrType, context);
} else {
attrConverter = converterRegistry.getConverter(attrType.getTypeCategory());
v2Value = attrConverter.fromV1ToV2(v1Value, attrType, context);
}
ret.put(attr.getAttributeDef().getName(), v2Value); ret.put(attr.getAttributeDef().getName(), v2Value);
} }
} }
......
...@@ -25,6 +25,7 @@ import org.apache.atlas.model.SearchFilter; ...@@ -25,6 +25,7 @@ import org.apache.atlas.model.SearchFilter;
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.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasEntityWithAssociations;
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;
...@@ -53,6 +54,7 @@ import javax.ws.rs.core.Context; ...@@ -53,6 +54,7 @@ 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.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
...@@ -92,9 +94,10 @@ public class EntitiesREST { ...@@ -92,9 +94,10 @@ public class EntitiesREST {
@POST @POST
@Consumes(Servlets.JSON_MEDIA_TYPE) @Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse createOrUpdate(List<AtlasEntity> entities) throws AtlasBaseException { public EntityMutationResponse createOrUpdate(Map<String, AtlasEntity> entities) throws AtlasBaseException {
EntityMutationResponse response = null; EntityMutationResponse response = null;
ITypedReferenceableInstance[] entitiesInOldFormat = restAdapters.getITypedReferenceables(entities);
ITypedReferenceableInstance[] entitiesInOldFormat = restAdapters.getITypedReferenceables(entities.values());
try { try {
final AtlasClient.EntityResult result = metadataService.updateEntities(entitiesInOldFormat); final AtlasClient.EntityResult result = metadataService.updateEntities(entitiesInOldFormat);
...@@ -114,7 +117,7 @@ public class EntitiesREST { ...@@ -114,7 +117,7 @@ public class EntitiesREST {
@PUT @PUT
@Consumes(Servlets.JSON_MEDIA_TYPE) @Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse update(List<AtlasEntity> entities) throws AtlasBaseException { public EntityMutationResponse update(Map<String, AtlasEntity> entities) throws AtlasBaseException {
return createOrUpdate(entities); return createOrUpdate(entities);
} }
...@@ -135,8 +138,10 @@ public class EntitiesREST { ...@@ -135,8 +138,10 @@ public class EntitiesREST {
for (String guid : guids) { for (String guid : guids) {
try { try {
ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid); ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid);
AtlasEntity entity = restAdapters.getAtlasEntity(ref); Map<String, AtlasEntityWithAssociations> entityRet = restAdapters.getAtlasEntity(ref);
entityList.add(entity);
addToEntityList(entityList, entityRet.values());
} catch (AtlasException e) { } catch (AtlasException e) {
throw toAtlasBaseException(e); throw toAtlasBaseException(e);
} }
...@@ -146,6 +151,14 @@ public class EntitiesREST { ...@@ -146,6 +151,14 @@ public class EntitiesREST {
return entities; return entities;
} }
private void addToEntityList(final List<AtlasEntity> entityList, final Collection<AtlasEntityWithAssociations> values) {
for (AtlasEntityWithAssociations val : values) {
if ( !entityList.contains(val)) {
entityList.add(val);
}
}
}
/******* /*******
* Entity Delete * Entity Delete
*******/ *******/
...@@ -168,28 +181,6 @@ public class EntitiesREST { ...@@ -168,28 +181,6 @@ public class EntitiesREST {
} }
/** /**
* Bulk retrieval API for searching on entities by certain predefined attributes ( typeName, superType, name, qualifiedName etc) + optional user defined attributes
*
* @throws AtlasBaseException
*/
@GET
@Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasEntityHeader.AtlasEntityHeaders searchEntities() throws AtlasBaseException {
SearchFilter searchFilter = getSearchFilter();
AtlasEntity.AtlasEntities atlasEntities = entitiesStore.searchEntities(searchFilter);
AtlasEntityHeader.AtlasEntityHeaders entityHeaders = new AtlasEntityHeader.AtlasEntityHeaders();
entityHeaders.setList(new LinkedList<AtlasEntityHeader>());
if (atlasEntities != null) {
for (AtlasEntity atlasEntity : atlasEntities.getList()) {
entityHeaders.getList().add(new AtlasEntityHeader(atlasEntity.getTypeName(), atlasEntity.getAttributes()));
}
}
return entityHeaders;
}
/**
* Bulk API to associate a tag to multiple entities * Bulk API to associate a tag to multiple entities
* *
*/ */
...@@ -219,15 +210,4 @@ public class EntitiesREST { ...@@ -219,15 +210,4 @@ public class EntitiesREST {
throw toAtlasBaseException(e); throw toAtlasBaseException(e);
} }
} }
private SearchFilter getSearchFilter() {
SearchFilter searchFilter = new SearchFilter();
if (null != httpServletRequest && null != httpServletRequest.getParameterMap()) {
for (Map.Entry<String, String[]> entry : httpServletRequest.getParameterMap().entrySet()) {
searchFilter.setParam(entry.getKey(), Arrays.asList(entry.getValue()));
}
}
return searchFilter;
}
} }
...@@ -35,6 +35,7 @@ import org.apache.atlas.typesystem.IStruct; ...@@ -35,6 +35,7 @@ import org.apache.atlas.typesystem.IStruct;
import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedReferenceableInstance;
import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.ITypedStruct;
import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.Referenceable;
import org.apache.atlas.web.adapters.AtlasFormatConverter;
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;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
...@@ -47,6 +48,7 @@ import javax.ws.rs.*; ...@@ -47,6 +48,7 @@ import javax.ws.rs.*;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import java.util.ArrayList; import java.util.ArrayList;
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; import static org.apache.atlas.web.adapters.AtlasInstanceRestAdapters.toEntityMutationResponse;
...@@ -74,45 +76,6 @@ public class EntityREST { ...@@ -74,45 +76,6 @@ public class EntityREST {
} }
/** /**
* Create or Update an entity if it already exists
*
* @param entity The updated entity
* @return
*/
@POST
@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse createOrUpdate(final AtlasEntity entity) throws AtlasBaseException {
EntityMutationResponse response = null;
ITypedReferenceableInstance[] entitiesInOldFormat = restAdapters.getITypedReferenceables(new ArrayList<AtlasEntity>() {{ add(entity); }});
try {
final AtlasClient.EntityResult 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;
}
/**
* Complete Update of an entity identified by its GUID
*
* @param guid
* @param entity The updated entity
* @return
*/
@PUT
@Path("guid/{guid}")
@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse updateByGuid(@PathParam("guid") String guid, AtlasEntity entity, @DefaultValue("false") @QueryParam("partialUpdate") boolean partialUpdate) throws AtlasBaseException {
return createOrUpdate(entity);
}
/**
* Fetch the complete definition of an entity given its GUID. * Fetch the complete definition of an entity given its GUID.
* *
* @param guid GUID for the entity * @param guid GUID for the entity
...@@ -120,10 +83,14 @@ public class EntityREST { ...@@ -120,10 +83,14 @@ public class EntityREST {
@GET @GET
@Path("/guid/{guid}") @Path("/guid/{guid}")
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasEntity getById(@PathParam("guid") String guid) throws AtlasBaseException { public List<AtlasEntityWithAssociations> getById(@PathParam("guid") String guid) throws AtlasBaseException {
List<AtlasEntityWithAssociations> entityList = new ArrayList<>();
try { try {
ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid); ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid);
return restAdapters.getAtlasEntity(ref); Map<String, AtlasEntityWithAssociations> entityRet = restAdapters.getAtlasEntity(ref);
entityList.addAll(entityRet.values());
return entityList;
} catch (AtlasException e) { } catch (AtlasException e) {
throw toAtlasBaseException(e); throw toAtlasBaseException(e);
} }
...@@ -138,10 +105,14 @@ public class EntityREST { ...@@ -138,10 +105,14 @@ public class EntityREST {
@GET @GET
@Path("/guid/{guid}/associations") @Path("/guid/{guid}/associations")
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public AtlasEntityWithAssociations getWithAssociationsByGuid(@PathParam("guid") String guid) throws AtlasBaseException { public List<AtlasEntityWithAssociations> getWithAssociationsByGuid(@PathParam("guid") String guid) throws AtlasBaseException {
List<AtlasEntityWithAssociations> entityList = new ArrayList<>();
try { try {
ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid); ITypedReferenceableInstance ref = metadataService.getEntityDefinition(guid);
return restAdapters.getAtlasEntity(ref); Map<String, AtlasEntityWithAssociations> entityRet = restAdapters.getAtlasEntity(ref);
entityList.addAll(entityRet.values());
return entityList;
} catch (AtlasException e) { } catch (AtlasException e) {
throw toAtlasBaseException(e); throw toAtlasBaseException(e);
} }
...@@ -190,7 +161,9 @@ public class EntityREST { ...@@ -190,7 +161,9 @@ public class EntityREST {
AtlasEntityType type = (AtlasEntityType) validateType(entityType, TypeCategory.ENTITY); AtlasEntityType type = (AtlasEntityType) validateType(entityType, TypeCategory.ENTITY);
validateUniqueAttribute(type, attribute); validateUniqueAttribute(type, attribute);
Referenceable ref = restAdapters.getReferenceable(entity); AtlasFormatConverter.ConverterContext ctx = new AtlasFormatConverter.ConverterContext();
ctx.addEntity(entity);
Referenceable ref = restAdapters.getReferenceable(entity, ctx);
AtlasClient.EntityResult result = metadataService.updateEntityByUniqueAttribute(entityType, attribute, value, ref); AtlasClient.EntityResult result = metadataService.updateEntityByUniqueAttribute(entityType, attribute, value, ref);
return toEntityMutationResponse(result); return toEntityMutationResponse(result);
} }
...@@ -220,19 +193,23 @@ public class EntityREST { ...@@ -220,19 +193,23 @@ public class EntityREST {
@Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON}) @Consumes({Servlets.JSON_MEDIA_TYPE, MediaType.APPLICATION_JSON})
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
@Path("/uniqueAttribute/type/{typeName}/attribute/{attrName}") @Path("/uniqueAttribute/type/{typeName}/attribute/{attrName}")
public AtlasEntity getByUniqueAttribute(@PathParam("typeName") String entityType, public List<AtlasEntityWithAssociations> getByUniqueAttribute(@PathParam("typeName") String entityType,
@PathParam("attrName") String attribute, @PathParam("attrName") String attribute,
@QueryParam("value") String value) throws AtlasBaseException { @QueryParam("value") String value) throws AtlasBaseException {
List<AtlasEntityWithAssociations> entityList = new ArrayList<>();
AtlasEntityType type = (AtlasEntityType) validateType(entityType, TypeCategory.ENTITY); AtlasEntityType type = (AtlasEntityType) validateType(entityType, TypeCategory.ENTITY);
validateUniqueAttribute(type, attribute); validateUniqueAttribute(type, attribute);
try { try {
final ITypedReferenceableInstance entityDefinitionReference = metadataService.getEntityDefinitionReference(entityType, attribute, value); final ITypedReferenceableInstance entityDefinitionReference = metadataService.getEntityDefinitionReference(entityType, attribute, value);
return restAdapters.getAtlasEntity(entityDefinitionReference); Map<String, AtlasEntityWithAssociations> entityRet = restAdapters.getAtlasEntity(entityDefinitionReference);
entityList.addAll(entityRet.values());
} catch (AtlasException e) { } catch (AtlasException e) {
throw toAtlasBaseException(e); throw toAtlasBaseException(e);
} }
return entityList;
} }
......
...@@ -26,6 +26,7 @@ import org.apache.atlas.TestUtilsV2; ...@@ -26,6 +26,7 @@ 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.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasEntityHeader;
import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct; import org.apache.atlas.model.instance.AtlasStruct;
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;
...@@ -68,6 +69,10 @@ public class TestEntitiesREST { ...@@ -68,6 +69,10 @@ 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;
...@@ -78,9 +83,12 @@ public class TestEntitiesREST { ...@@ -78,9 +83,12 @@ public class TestEntitiesREST {
public void setUp() throws Exception { public void setUp() throws Exception {
AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes(); AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes();
typeStore.createTypesDef(typesDef); typeStore.createTypesDef(typesDef);
dbEntity = TestUtilsV2.createDBEntity(); dbEntityMap = TestUtilsV2.createDBEntity();
dbEntity = dbEntityMap.values().iterator().next();
tableEntityMap = TestUtilsV2.createTableEntity(dbEntity.getGuid());
tableEntity = tableEntityMap.values().iterator().next();
tableEntity = TestUtilsV2.createTableEntity(dbEntity.getGuid());
final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid());
columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }}; columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }};
tableEntity.setAttribute("columns", columns); tableEntity.setAttribute("columns", columns);
...@@ -98,9 +106,9 @@ public class TestEntitiesREST { ...@@ -98,9 +106,9 @@ public class TestEntitiesREST {
@Test @Test
public void testCreateOrUpdateEntities() throws Exception { public void testCreateOrUpdateEntities() throws Exception {
List<AtlasEntity> entities = new ArrayList<AtlasEntity>(); Map<String, AtlasEntity> entities = new HashMap<>();
entities.add(dbEntity); entities.put(dbEntity.getGuid(), dbEntity);
entities.add(tableEntity); entities.put(tableEntity.getGuid(), tableEntity);
EntityMutationResponse response = entitiesREST.createOrUpdate(entities); EntityMutationResponse response = entitiesREST.createOrUpdate(entities);
List<AtlasEntityHeader> guids = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); List<AtlasEntityHeader> guids = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
...@@ -129,9 +137,12 @@ public class TestEntitiesREST { ...@@ -129,9 +137,12 @@ 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
AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity();
AtlasEntity dbEntity = dbEntityMap.values().iterator().next();
Map<String, AtlasEntity> tableEntityMap = TestUtilsV2.createTableEntity(dbEntity.getGuid());
AtlasEntity tableEntity = tableEntityMap.values().iterator().next();
AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity.getGuid());
final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid()); final AtlasEntity colEntity = TestUtilsV2.createColumnEntity(tableEntity.getGuid());
List<AtlasEntity> columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }}; List<AtlasEntity> columns = new ArrayList<AtlasEntity>() {{ add(colEntity); }};
tableEntity.setAttribute("columns", columns); tableEntity.setAttribute("columns", columns);
...@@ -139,9 +150,9 @@ public class TestEntitiesREST { ...@@ -139,9 +150,9 @@ public class TestEntitiesREST {
AtlasEntity newDBEntity = serDeserEntity(dbEntity); AtlasEntity newDBEntity = serDeserEntity(dbEntity);
AtlasEntity newTableEntity = serDeserEntity(tableEntity); AtlasEntity newTableEntity = serDeserEntity(tableEntity);
List<AtlasEntity> newEntities = new ArrayList<AtlasEntity>(); Map<String, AtlasEntity> newEntities = new HashMap<>();
newEntities.add(newDBEntity); newEntities.put(newDBEntity.getGuid(), newDBEntity);
newEntities.add(newTableEntity); newEntities.put(newTableEntity.getGuid(), newTableEntity);
EntityMutationResponse response2 = entitiesREST.createOrUpdate(newEntities); EntityMutationResponse response2 = entitiesREST.createOrUpdate(newEntities);
List<AtlasEntityHeader> newGuids = response2.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); List<AtlasEntityHeader> newGuids = response2.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
...@@ -211,7 +222,7 @@ public class TestEntitiesREST { ...@@ -211,7 +222,7 @@ public class TestEntitiesREST {
//date //date
Assert.assertEquals(tableEntity.getAttribute("created"), retrievedTableEntity.getAttribute("created")); Assert.assertEquals(tableEntity.getAttribute("created"), retrievedTableEntity.getAttribute("created"));
//array of Ids //array of Ids
Assert.assertEquals(((List<AtlasEntity>) retrievedTableEntity.getAttribute("columns")).get(0).getGuid(), retrievedColumnEntity.getGuid()); Assert.assertEquals(((List<AtlasObjectId>) retrievedTableEntity.getAttribute("columns")).get(0).getGuid(), retrievedColumnEntity.getGuid());
//array of structs //array of structs
Assert.assertEquals(((List<AtlasStruct>) retrievedTableEntity.getAttribute("partitions")), tableEntity.getAttribute("partitions")); Assert.assertEquals(((List<AtlasStruct>) retrievedTableEntity.getAttribute("partitions")), tableEntity.getAttribute("partitions"));
} }
......
...@@ -29,6 +29,7 @@ import org.apache.atlas.model.instance.EntityMutations; ...@@ -29,6 +29,7 @@ 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.testng.Assert; import org.testng.Assert;
import org.testng.annotations.AfterMethod; import org.testng.annotations.AfterMethod;
...@@ -41,6 +42,7 @@ import javax.inject.Inject; ...@@ -41,6 +42,7 @@ import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
@Guice(modules = {RepositoryMetadataModule.class}) @Guice(modules = {RepositoryMetadataModule.class})
public class TestEntityREST { public class TestEntityREST {
...@@ -51,6 +53,9 @@ public class TestEntityREST { ...@@ -51,6 +53,9 @@ public class TestEntityREST {
@Inject @Inject
private EntityREST entityREST; private EntityREST entityREST;
@Inject
private EntitiesREST entitiesREST;
private AtlasEntity dbEntity; private AtlasEntity dbEntity;
private String dbGuid; private String dbGuid;
...@@ -61,7 +66,8 @@ public class TestEntityREST { ...@@ -61,7 +66,8 @@ public class TestEntityREST {
public void setUp() throws Exception { public void setUp() throws Exception {
AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes(); AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes();
typeStore.createTypesDef(typesDef); typeStore.createTypesDef(typesDef);
dbEntity = TestUtilsV2.createDBEntity(); Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity();
dbEntity = dbEntityMap.values().iterator().next();
} }
@AfterClass @AfterClass
...@@ -74,9 +80,10 @@ public class TestEntityREST { ...@@ -74,9 +80,10 @@ public class TestEntityREST {
RequestContext.clear(); RequestContext.clear();
} }
@Test public void createOrUpdateEntity() throws Exception {
public void testCreateOrUpdateEntity() throws Exception { Map<String, AtlasEntity> dbEntityMap = new HashMap<>();
final EntityMutationResponse response = entityREST.createOrUpdate(dbEntity); dbEntityMap.put(dbEntity.getGuid(), 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);
...@@ -88,18 +95,19 @@ public class TestEntityREST { ...@@ -88,18 +95,19 @@ public class TestEntityREST {
Assert.assertEquals(entitiesMutated.size(), 1); Assert.assertEquals(entitiesMutated.size(), 1);
} }
@Test(dependsOnMethods = "testCreateOrUpdateEntity") @Test
public void testGetEntityById() throws Exception { public void testGetEntityById() throws Exception {
createOrUpdateEntity();
final AtlasEntity response = entityREST.getById(dbGuid); final List<AtlasEntityWithAssociations> response = entityREST.getById(dbGuid);
Assert.assertNotNull(response); Assert.assertNotNull(response);
TestEntitiesREST.verifyAttributes(response.getAttributes(), dbEntity.getAttributes()); TestEntitiesREST.verifyAttributes(response.get(0).getAttributes(), dbEntity.getAttributes());
} }
@Test(dependsOnMethods = "testCreateOrUpdateEntity") @Test
public void testAddAndGetClassification() throws Exception { public void testAddAndGetClassification() throws Exception {
createOrUpdateEntity();
List<AtlasClassification> classifications = new ArrayList<>(); List<AtlasClassification> classifications = new ArrayList<>();
testClassification = new AtlasClassification(TestUtilsV2.CLASSIFICATION, new HashMap<String, Object>() {{ put("tag", "tagName"); }}); testClassification = new AtlasClassification(TestUtilsV2.CLASSIFICATION, new HashMap<String, Object>() {{ put("tag", "tagName"); }});
classifications.add(testClassification); classifications.add(testClassification);
...@@ -122,8 +130,8 @@ public class TestEntityREST { ...@@ -122,8 +130,8 @@ public class TestEntityREST {
@Test(dependsOnMethods = "testAddAndGetClassification") @Test(dependsOnMethods = "testAddAndGetClassification")
public void testGetEntityWithAssociations() throws Exception { public void testGetEntityWithAssociations() throws Exception {
AtlasEntityWithAssociations entity = entityREST.getWithAssociationsByGuid(dbGuid); List<AtlasEntityWithAssociations> entity = entityREST.getWithAssociationsByGuid(dbGuid);
final List<AtlasClassification> retrievedClassifications = entity.getClassifications(); final List<AtlasClassification> retrievedClassifications = entity.get(0).getClassifications();
Assert.assertNotNull(retrievedClassifications); Assert.assertNotNull(retrievedClassifications);
Assert.assertEquals(new ArrayList<AtlasClassification>() {{ add(testClassification); }}, retrievedClassifications); Assert.assertEquals(new ArrayList<AtlasClassification>() {{ add(testClassification); }}, retrievedClassifications);
...@@ -151,8 +159,8 @@ public class TestEntityREST { ...@@ -151,8 +159,8 @@ public class TestEntityREST {
@Test @Test
public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception { public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); Map<String, AtlasEntity> dbEntityMap = TestUtilsV2.createDBEntity();
entityREST.createOrUpdate(dbEntity); entitiesREST.createOrUpdate(dbEntityMap);
final String prevDBName = (String) dbEntity.getAttribute(TestUtilsV2.NAME); final String prevDBName = (String) dbEntity.getAttribute(TestUtilsV2.NAME);
final String updatedDBName = "updatedDBName"; final String updatedDBName = "updatedDBName";
...@@ -164,11 +172,11 @@ public class TestEntityREST { ...@@ -164,11 +172,11 @@ public class TestEntityREST {
Assert.assertTrue(AtlasEntity.isAssigned(dbGuid)); Assert.assertTrue(AtlasEntity.isAssigned(dbGuid));
//Get By unique attribute //Get By unique attribute
AtlasEntity entity = entityREST.getByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, TestUtilsV2.NAME, updatedDBName); List<AtlasEntityWithAssociations> entities = entityREST.getByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, TestUtilsV2.NAME, updatedDBName);
Assert.assertNotNull(entity); Assert.assertNotNull(entities);
Assert.assertNotNull(entity.getGuid()); Assert.assertNotNull(entities.get(0).getGuid());
Assert.assertEquals(entity.getGuid(), dbGuid); Assert.assertEquals(entities.get(0).getGuid(), dbGuid);
TestEntitiesREST.verifyAttributes(entity.getAttributes(), dbEntity.getAttributes()); TestEntitiesREST.verifyAttributes(entities.get(0).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, TestUtilsV2.NAME, (String) dbEntity.getAttribute(TestUtilsV2.NAME));
......
...@@ -564,7 +564,7 @@ public class EntityV2JerseyResourceIT extends BaseResourceIT { ...@@ -564,7 +564,7 @@ public class EntityV2JerseyResourceIT extends BaseResourceIT {
hiveTable.setAttribute("columns", columns); hiveTable.setAttribute("columns", columns);
LOG.debug("Updating entity= " + tableUpdated); LOG.debug("Updating entity= " + tableUpdated);
EntityMutationResponse updateResult = entitiesClientV2.updateEntity(hiveTable.getGuid(), tableUpdated); EntityMutationResponse updateResult = entitiesClientV2.updateEntity(tableUpdated);
assertNotNull(updateResult); assertNotNull(updateResult);
assertNotNull(updateResult.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE)); assertNotNull(updateResult.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE));
assertTrue(updateResult.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).size() > 0); assertTrue(updateResult.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