Commit 68c55925 by Sarath Subramanian Committed by Madhan Neethiraj

ATLAS-1554 : v2 EntityREST implementation for entity partial update

parent c5ea4f0e
......@@ -32,6 +32,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef;
import org.apache.atlas.model.instance.EntityMutations.EntityOperation;
import org.codehaus.jackson.annotate.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
......@@ -44,21 +45,21 @@ import org.codehaus.jackson.map.annotate.JsonSerialize;
@XmlAccessorType(XmlAccessType.PROPERTY)
public class EntityMutationResponse {
Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities;
Map<String,String> guidAssignments;
Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities;
Map<String, String> guidAssignments;
public EntityMutationResponse() {
}
public EntityMutationResponse(final Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
public EntityMutationResponse(final Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
this.mutatedEntities = mutatedEntities;
}
public Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> getMutatedEntities() {
public Map<EntityOperation, List<AtlasEntityHeader>> getMutatedEntities() {
return mutatedEntities;
}
public void setMutatedEntities(final Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
public void setMutatedEntities(final Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
this.mutatedEntities = mutatedEntities;
}
......@@ -72,7 +73,7 @@ public class EntityMutationResponse {
@JsonIgnore
public List<AtlasEntityHeader> getEntitiesByOperation(EntityMutations.EntityOperation op) {
public List<AtlasEntityHeader> getEntitiesByOperation(EntityOperation op) {
if ( mutatedEntities != null) {
return mutatedEntities.get(op);
}
......@@ -82,7 +83,7 @@ public class EntityMutationResponse {
@JsonIgnore
public List<AtlasEntityHeader> getCreatedEntities() {
if ( mutatedEntities != null) {
return mutatedEntities.get(EntityMutations.EntityOperation.CREATE);
return mutatedEntities.get(EntityOperation.CREATE);
}
return null;
}
......@@ -90,7 +91,14 @@ public class EntityMutationResponse {
@JsonIgnore
public List<AtlasEntityHeader> getUpdatedEntities() {
if ( mutatedEntities != null) {
return mutatedEntities.get(EntityMutations.EntityOperation.UPDATE);
return mutatedEntities.get(EntityOperation.UPDATE);
}
return null;
}
public List<AtlasEntityHeader> getPartialUpdatedEntities() {
if ( mutatedEntities != null) {
return mutatedEntities.get(EntityOperation.PARTIAL_UPDATE);
}
return null;
}
......@@ -98,14 +106,14 @@ public class EntityMutationResponse {
@JsonIgnore
public List<AtlasEntityHeader> getDeletedEntities() {
if ( mutatedEntities != null) {
return mutatedEntities.get(EntityMutations.EntityOperation.DELETE);
return mutatedEntities.get(EntityOperation.DELETE);
}
return null;
}
@JsonIgnore
public AtlasEntityHeader getFirstEntityCreated() {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityMutations.EntityOperation.CREATE);
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityOperation.CREATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
return entitiesByOperation.get(0);
}
......@@ -115,7 +123,18 @@ public class EntityMutationResponse {
@JsonIgnore
public AtlasEntityHeader getFirstEntityUpdated() {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE);
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityOperation.UPDATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
return entitiesByOperation.get(0);
}
return null;
}
@JsonIgnore
public AtlasEntityHeader getFirstEntityPartialUpdated() {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityOperation.PARTIAL_UPDATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
return entitiesByOperation.get(0);
}
......@@ -125,45 +144,51 @@ public class EntityMutationResponse {
@JsonIgnore
public AtlasEntityHeader getFirstCreatedEntityByTypeName(String typeName) {
return getFirstEntityByType(getEntitiesByOperation(EntityMutations.EntityOperation.CREATE), typeName);
return getFirstEntityByType(getEntitiesByOperation(EntityOperation.CREATE), typeName);
}
@JsonIgnore
public AtlasEntityHeader getFirstDeletedEntityByTypeName(String typeName) {
return getFirstEntityByType(getEntitiesByOperation(EntityMutations.EntityOperation.DELETE), typeName);
return getFirstEntityByType(getEntitiesByOperation(EntityOperation.DELETE), typeName);
}
@JsonIgnore
public List<AtlasEntityHeader> getCreatedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityMutations.EntityOperation.CREATE), typeName);
return getEntitiesByType(getEntitiesByOperation(EntityOperation.CREATE), typeName);
}
@JsonIgnore
public List<AtlasEntityHeader> getPartialUpdatedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityOperation.PARTIAL_UPDATE), typeName);
}
@JsonIgnore
public AtlasEntityHeader getCreatedEntityByTypeNameAndAttribute(String typeName, String attrName, String attrVal) {
return getEntityByTypeAndUniqueAttribute(getEntitiesByOperation(EntityMutations.EntityOperation.CREATE), typeName, attrName, attrVal);
return getEntityByTypeAndUniqueAttribute(getEntitiesByOperation(EntityOperation.CREATE), typeName, attrName, attrVal);
}
@JsonIgnore
public AtlasEntityHeader getUpdatedEntityByTypeNameAndAttribute(String typeName, String attrName, String attrVal) {
return getEntityByTypeAndUniqueAttribute(getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE), typeName, attrName, attrVal);
return getEntityByTypeAndUniqueAttribute(getEntitiesByOperation(EntityOperation.UPDATE), typeName, attrName, attrVal);
}
@JsonIgnore
public List<AtlasEntityHeader> getUpdatedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE), typeName);
return getEntitiesByType(getEntitiesByOperation(EntityOperation.UPDATE), typeName);
}
@JsonIgnore
public List<AtlasEntityHeader> getDeletedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityMutations.EntityOperation.DELETE), typeName);
return getEntitiesByType(getEntitiesByOperation(EntityOperation.DELETE), typeName);
}
@JsonIgnore
public AtlasEntityHeader getFirstUpdatedEntityByTypeName(String typeName) {
return getFirstEntityByType(getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE), typeName);
return getFirstEntityByType(getEntitiesByOperation(EntityOperation.UPDATE), typeName);
}
public void addEntity(EntityMutations.EntityOperation op, AtlasEntityHeader header) {
public void addEntity(EntityOperation op, AtlasEntityHeader header) {
if (mutatedEntities == null) {
mutatedEntities = new HashMap<>();
}
......
......@@ -161,6 +161,41 @@ public class AtlasArrayType extends AtlasType {
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
if (obj instanceof List || obj instanceof Set) {
Collection objList = (Collection) obj;
if (!isValidElementCount(objList.size())) {
return false;
}
for (Object element : objList) {
if (!elementType.isValidValueForUpdate(element)) {
return false;
}
}
} else if (obj.getClass().isArray()) {
int arrayLen = Array.getLength(obj);
if (!isValidElementCount(arrayLen)) {
return false;
}
for (int i = 0; i < arrayLen; i++) {
if (!elementType.isValidValueForUpdate(Array.get(obj, i))) {
return false;
}
}
} else {
return false; // invalid type
}
}
return true;
}
@Override
public Collection<?> getNormalizedValue(Object obj) {
if (obj == null) {
return null;
......@@ -222,6 +257,67 @@ public class AtlasArrayType extends AtlasType {
}
@Override
public Collection<?> getNormalizedValueForUpdate(Object obj) {
if (obj == null) {
return null;
}
if (obj instanceof List || obj instanceof Set) {
List<Object> ret = new ArrayList<>();
Collection objList = (Collection) obj;
if (!isValidElementCount(objList.size())) {
return null;
}
for (Object element : objList) {
if (element != null) {
Object normalizedValue = elementType.getNormalizedValueForUpdate(element);
if (normalizedValue != null) {
ret.add(normalizedValue);
} else {
return null; // invalid element value
}
} else {
ret.add(element);
}
}
return ret;
} else if (obj.getClass().isArray()) {
List<Object> ret = new ArrayList<>();
int arrayLen = Array.getLength(obj);
if (!isValidElementCount(arrayLen)) {
return null;
}
for (int i = 0; i < arrayLen; i++) {
Object element = Array.get(obj, i);
if (element != null) {
Object normalizedValue = elementType.getNormalizedValueForUpdate(element);
if (normalizedValue != null) {
ret.add(normalizedValue);
} else {
return null; // invalid element value
}
} else {
ret.add(element);
}
}
return ret;
}
return null;
}
@Override
public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true;
......@@ -265,6 +361,49 @@ public class AtlasArrayType extends AtlasType {
}
@Override
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
boolean ret = true;
if (obj != null) {
if (obj instanceof List || obj instanceof Set) {
Collection objList = (Collection) obj;
if (!isValidElementCount(objList.size())) {
ret = false;
messages.add(objName + ": incorrect number of values. found=" + objList.size()
+ "; expected: minCount=" + minCount + ", maxCount=" + maxCount);
}
int idx = 0;
for (Object element : objList) {
ret = elementType.validateValueForUpdate(element, objName + "[" + idx + "]", messages) && ret;
idx++;
}
} else if (obj.getClass().isArray()) {
int arrayLen = Array.getLength(obj);
if (!isValidElementCount(arrayLen)) {
ret = false;
messages.add(objName + ": incorrect number of values. found=" + arrayLen
+ "; expected: minCount=" + minCount + ", maxCount=" + maxCount);
}
for (int i = 0; i < arrayLen; i++) {
ret = elementType.validateValueForUpdate(Array.get(obj, i), objName + "[" + i + "]", messages) && ret;
}
} else {
ret = false;
messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName());
}
}
return ret;
}
@Override
public AtlasType getTypeForAttribute() {
AtlasType elementAttributeType = elementType.getTypeForAttribute();
......
......@@ -159,6 +159,21 @@ public class AtlasClassificationType extends AtlasStructType {
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
for (AtlasClassificationType superType : superTypes) {
if (!superType.isValidValueForUpdate(obj)) {
return false;
}
}
return super.isValidValueForUpdate(obj);
}
return true;
}
@Override
public Object getNormalizedValue(Object obj) {
Object ret = null;
......@@ -178,6 +193,25 @@ public class AtlasClassificationType extends AtlasStructType {
}
@Override
public Object getNormalizedValueForUpdate(Object obj) {
Object ret = null;
if (obj != null) {
if (isValidValueForUpdate(obj)) {
if (obj instanceof AtlasClassification) {
normalizeAttributeValuesForUpdate((AtlasClassification) obj);
ret = obj;
} else if (obj instanceof Map) {
normalizeAttributeValuesForUpdate((Map) obj);
ret = obj;
}
}
}
return ret;
}
@Override
public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true;
......@@ -192,6 +226,21 @@ public class AtlasClassificationType extends AtlasStructType {
return ret;
}
@Override
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
boolean ret = true;
if (obj != null) {
for (AtlasClassificationType superType : superTypes) {
ret = superType.validateValueForUpdate(obj, objName, messages) && ret;
}
ret = super.validateValueForUpdate(obj, objName, messages) && ret;
}
return ret;
}
public void normalizeAttributeValues(AtlasClassification classification) {
if (classification != null) {
for (AtlasClassificationType superType : superTypes) {
......@@ -202,6 +251,16 @@ public class AtlasClassificationType extends AtlasStructType {
}
}
public void normalizeAttributeValuesForUpdate(AtlasClassification classification) {
if (classification != null) {
for (AtlasClassificationType superType : superTypes) {
superType.normalizeAttributeValuesForUpdate(classification);
}
super.normalizeAttributeValuesForUpdate(classification);
}
}
@Override
public void normalizeAttributeValues(Map<String, Object> obj) {
if (obj != null) {
......@@ -213,6 +272,16 @@ public class AtlasClassificationType extends AtlasStructType {
}
}
public void normalizeAttributeValuesForUpdate(Map<String, Object> obj) {
if (obj != null) {
for (AtlasClassificationType superType : superTypes) {
superType.normalizeAttributeValuesForUpdate(obj);
}
super.normalizeAttributeValuesForUpdate(obj);
}
}
public void populateDefaultValues(AtlasClassification classification) {
if (classification != null) {
for (AtlasClassificationType superType : superTypes) {
......
......@@ -142,10 +142,6 @@ public class AtlasEntityType extends AtlasStructType {
@Override
public boolean isValidValue(Object obj) {
if (obj != null) {
if (obj instanceof AtlasObjectId) {
AtlasObjectId objId = (AtlasObjectId ) obj;
return isAssignableFrom(objId);
} else {
for (AtlasEntityType superType : superTypes) {
if (!superType.isValidValue(obj)) {
return false;
......@@ -153,6 +149,19 @@ public class AtlasEntityType extends AtlasStructType {
}
return super.isValidValue(obj);
}
return true;
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
for (AtlasEntityType superType : superTypes) {
if (!superType.isValidValueForUpdate(obj)) {
return false;
}
}
return super.isValidValueForUpdate(obj);
}
return true;
......@@ -170,7 +179,24 @@ public class AtlasEntityType extends AtlasStructType {
} else if (obj instanceof Map) {
normalizeAttributeValues((Map) obj);
ret = obj;
} else if (obj instanceof AtlasObjectId) {
}
}
}
return ret;
}
@Override
public Object getNormalizedValueForUpdate(Object obj) {
Object ret = null;
if (obj != null) {
if (isValidValueForUpdate(obj)) {
if (obj instanceof AtlasEntity) {
normalizeAttributeValuesForUpdate((AtlasEntity) obj);
ret = obj;
} else if (obj instanceof Map) {
normalizeAttributeValuesForUpdate((Map) obj);
ret = obj;
}
}
......@@ -189,30 +215,38 @@ public class AtlasEntityType extends AtlasStructType {
boolean ret = true;
if (obj != null) {
if (obj instanceof AtlasObjectId) {
AtlasObjectId objId = (AtlasObjectId) obj;
return isAssignableFrom(objId);
} else if (obj instanceof AtlasEntity) {
// entity validation will be done below, outside of these if/else blocks
} else if (obj instanceof Map) {
AtlasObjectId objId = new AtlasObjectId((Map) obj);
if (isAssignableFrom(objId)) {
return true;
if (obj instanceof AtlasEntity || obj instanceof Map) {
for (AtlasEntityType superType : superTypes) {
ret = superType.validateValue(obj, objName, messages) && ret;
}
// entity validation will be done below, outside of these if/else blocks
ret = super.validateValue(obj, objName, messages) && ret;
} else {
ret = false;
messages.add(objName + ": invalid value type '" + obj.getClass().getName());
}
}
return ret;
}
@Override
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
boolean ret = true;
if (obj != null) {
if (obj instanceof AtlasEntity || obj instanceof Map) {
for (AtlasEntityType superType : superTypes) {
ret = superType.validateValue(obj, objName, messages) && ret;
ret = superType.validateValueForUpdate(obj, objName, messages) && ret;
}
ret = super.validateValue(obj, objName, messages) && ret;
ret = super.validateValueForUpdate(obj, objName, messages) && ret;
} else {
ret = false;
messages.add(objName + ": invalid value type '" + obj.getClass().getName());
}
}
return ret;
......@@ -239,6 +273,16 @@ public class AtlasEntityType extends AtlasStructType {
}
}
public void normalizeAttributeValuesForUpdate(AtlasEntity ent) {
if (ent != null) {
for (AtlasEntityType superType : superTypes) {
superType.normalizeAttributeValuesForUpdate(ent);
}
super.normalizeAttributeValuesForUpdate(ent);
}
}
@Override
public void normalizeAttributeValues(Map<String, Object> obj) {
if (obj != null) {
......@@ -250,6 +294,16 @@ public class AtlasEntityType extends AtlasStructType {
}
}
public void normalizeAttributeValuesForUpdate(Map<String, Object> obj) {
if (obj != null) {
for (AtlasEntityType superType : superTypes) {
superType.normalizeAttributeValuesForUpdate(obj);
}
super.normalizeAttributeValuesForUpdate(obj);
}
}
public void populateDefaultValues(AtlasEntity ent) {
if (ent != null) {
for (AtlasEntityType superType : superTypes) {
......
......@@ -124,6 +124,25 @@ public class AtlasMapType extends AtlasType {
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
if (obj instanceof Map) {
Map<Object, Objects> map = (Map<Object, Objects>) obj;
for (Map.Entry e : map.entrySet()) {
if (!keyType.isValidValueForUpdate(e.getKey()) || !valueType.isValidValueForUpdate(e.getValue())) {
return false; // invalid key/value
}
}
} else {
return false; // invalid type
}
}
return true;
}
@Override
public Map<Object, Object> getNormalizedValue(Object obj) {
if (obj == null) {
return null;
......@@ -163,6 +182,45 @@ public class AtlasMapType extends AtlasType {
}
@Override
public Map<Object, Object> getNormalizedValueForUpdate(Object obj) {
if (obj == null) {
return null;
}
if (obj instanceof Map) {
Map<Object, Object> ret = new HashMap<>();
Map<Object, Objects> map = (Map<Object, Objects>) obj;
for (Map.Entry e : map.entrySet()) {
Object normalizedKey = keyType.getNormalizedValueForUpdate(e.getKey());
if (normalizedKey != null) {
Object value = e.getValue();
if (value != null) {
Object normalizedValue = valueType.getNormalizedValueForUpdate(e.getValue());
if (normalizedValue != null) {
ret.put(normalizedKey, normalizedValue);
} else {
return null; // invalid value
}
} else {
ret.put(normalizedKey, value);
}
} else {
return null; // invalid key
}
}
return ret;
}
return null;
}
@Override
public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true;
......@@ -194,6 +252,37 @@ public class AtlasMapType extends AtlasType {
}
@Override
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
boolean ret = true;
if (obj != null) {
if (obj instanceof Map) {
Map<Object, Objects> map = (Map<Object, Objects>) obj;
for (Map.Entry e : map.entrySet()) {
Object key = e.getKey();
if (!keyType.isValidValueForUpdate(key)) {
ret = false;
messages.add(objName + "." + key + ": invalid key for type " + getTypeName());
} else {
Object value = e.getValue();
ret = valueType.validateValueForUpdate(value, objName + "." + key, messages) && ret;
}
}
} else {
ret = false;
messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName());
}
}
return ret;
}
@Override
public AtlasType getTypeForAttribute() {
AtlasType keyAttributeType = keyType.getTypeForAttribute();
AtlasType valueAttributeType = valueType.getTypeForAttribute();
......
......@@ -199,7 +199,7 @@ public class AtlasStructType extends AtlasType {
}
}
} else if (obj instanceof Map) {
Map map = (Map) obj;
Map map = AtlasTypeUtil.toStructAttributes((Map) obj);
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
if (!isAssignableValue(map.get(attributeDef.getName()), attributeDef)) {
......@@ -215,6 +215,42 @@ public class AtlasStructType extends AtlasType {
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
Map<String, Object> attributes;
if (obj instanceof AtlasStruct) {
AtlasStruct structObj = (AtlasStruct) obj;
attributes = structObj.getAttributes();
} else if (obj instanceof Map) {
attributes = AtlasTypeUtil.toStructAttributes((Map) obj);
} else {
return false;
}
if (MapUtils.isNotEmpty(attributes)) {
for (Map.Entry<String, Object> e : attributes.entrySet()) {
String attrName = e.getKey();
Object attrValue = e.getValue();
AtlasAttributeDef attrDef = structDef.getAttribute(attrName);
if (attrValue == null || attrDef == null) {
continue;
}
if (!isAssignableValueForUpdate(attrValue, attrDef)) {
return false;
}
}
}
}
return true;
}
@Override
public Object getNormalizedValue(Object obj) {
Object ret = null;
......@@ -234,6 +270,25 @@ public class AtlasStructType extends AtlasType {
}
@Override
public Object getNormalizedValueForUpdate(Object obj) {
Object ret = null;
if (obj != null) {
if (isValidValueForUpdate(obj)) {
if (obj instanceof AtlasStruct) {
normalizeAttributeValuesForUpdate((AtlasStruct) obj);
ret = obj;
} else if (obj instanceof Map) {
normalizeAttributeValuesForUpdate((Map) obj);
ret = obj;
}
}
}
return ret;
}
@Override
public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true;
......@@ -243,7 +298,6 @@ public class AtlasStructType extends AtlasType {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
String attrName = attributeDef.getName();
AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
if (attribute != null) {
......@@ -255,7 +309,6 @@ public class AtlasStructType extends AtlasType {
ret = dataType.validateValue(value, fieldName, messages) && ret;
} else if (!attributeDef.getIsOptional()) {
ret = false;
messages.add(fieldName + ": mandatory attribute value missing in type " + getTypeName());
}
}
......@@ -276,7 +329,6 @@ public class AtlasStructType extends AtlasType {
ret = dataType.validateValue(value, fieldName, messages) && ret;
} else if (!attributeDef.getIsOptional()) {
ret = false;
messages.add(fieldName + ": mandatory attribute value missing in type " + getTypeName());
}
}
......@@ -290,6 +342,47 @@ public class AtlasStructType extends AtlasType {
return ret;
}
@Override
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
boolean ret = true;
Map<String, Object> attributes = null;
if (obj != null) {
if (obj instanceof AtlasStruct) {
AtlasStruct structObj = (AtlasStruct) obj;
attributes = structObj.getAttributes();
} else if (obj instanceof Map) {
attributes = AtlasTypeUtil.toStructAttributes((Map) obj);
} else {
ret = false;
messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName());
}
if (MapUtils.isNotEmpty(attributes)) {
for (Map.Entry<String, Object> e : attributes.entrySet()) {
String attrName = e.getKey();
Object attrValue = e.getValue();
AtlasAttribute attribute = allAttributes.get(attrName);
if (attrValue == null) {
continue;
}
if (attribute != null) {
AtlasType dataType = attribute.getAttributeType();
String fieldName = objName + "." + attrName;
ret = dataType.validateValueForUpdate(attrValue, fieldName, messages) && ret;
}
}
}
}
return ret;
}
public void normalizeAttributeValues(AtlasStruct obj) {
if (obj != null) {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
......@@ -306,6 +399,19 @@ public class AtlasStructType extends AtlasType {
}
}
public void normalizeAttributeValuesForUpdate(AtlasStruct obj) {
if (obj != null) {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
String attributeName = attributeDef.getName();
if (obj.hasAttribute(attributeName)) {
Object attributeValue = getNormalizedValueForUpdate(obj.getAttribute(attributeName), attributeDef);
obj.setAttribute(attributeName, attributeValue);
}
}
}
}
public void normalizeAttributeValues(Map<String, Object> obj) {
if (obj != null) {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
......@@ -322,6 +428,20 @@ public class AtlasStructType extends AtlasType {
}
}
public void normalizeAttributeValuesForUpdate(Map<String, Object> obj) {
if (obj != null) {
for (AtlasAttributeDef attrDef : structDef.getAttributeDefs()) {
String attrName = attrDef.getName();
Object attrValue = obj.get(attrName);
if (obj.containsKey(attrName)) {
attrValue = getNormalizedValueForUpdate(attrValue, attrDef);
obj.put(attrName, attrValue);
}
}
}
}
public void populateDefaultValues(AtlasStruct obj) {
if (obj != null) {
Map<String, Object> attributes = obj.getAttributes();
......@@ -376,6 +496,24 @@ public class AtlasStructType extends AtlasType {
return ret;
}
private boolean isAssignableValueForUpdate(Object value, AtlasAttributeDef attributeDef) {
boolean ret = true;
if (value != null) {
AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
if (attribute != null) {
AtlasType attrType = attribute.getAttributeType();
if (!attrType.isValidValueForUpdate(value)) {
ret = false; // invalid value
}
}
}
return ret;
}
private Object getNormalizedValue(Object value, AtlasAttributeDef attributeDef) {
AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
......@@ -394,6 +532,20 @@ public class AtlasStructType extends AtlasType {
return null;
}
private Object getNormalizedValueForUpdate(Object value, AtlasAttributeDef attributeDef) {
AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
if (attribute != null) {
AtlasType attrType = attribute.getAttributeType();
if (value != null) {
return attrType.getNormalizedValueForUpdate(value);
}
}
return null;
}
public String getQualifiedAttributeName(String attrName) throws AtlasBaseException {
if ( allAttributes.containsKey(attrName)) {
return allAttributes.get(attrName).getQualifiedName();
......
......@@ -77,6 +77,14 @@ public abstract class AtlasType {
return ret;
}
public boolean isValidValueForUpdate(Object obj) { return isValidValue(obj); }
public Object getNormalizedValueForUpdate(Object obj) { return getNormalizedValue(obj); }
public boolean validateValueForUpdate(Object obj, String objName, List<String> messages) {
return validateValue(obj, objName, messages);
}
/* for attribute of entity-type, the value would be of AtlasObjectId
* when an attribute instance is created i.e. AtlasAttribute, this method
* will be called to get AtlasEntityType replaced with AtlasObjectType
......
......@@ -582,6 +582,7 @@ public final class TestUtilsV2 {
ImmutableSet.<String>of(),
AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createRequiredAttrDef("type", "string"),
AtlasTypeUtil.createOptionalAttrDef("description", "string"),
new AtlasAttributeDef("table", TABLE_TYPE,
true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
......
......@@ -66,10 +66,9 @@ public interface AtlasEntityStore {
* @return EntityMutationResponse Entity mutations operations with the corresponding set of entities on which these operations were performed
* @throws AtlasBaseException
*/
EntityMutationResponse createOrUpdate(EntityStream entityStream) throws AtlasBaseException;
EntityMutationResponse createOrUpdate(EntityStream entityStream, boolean isPartialUpdate) throws AtlasBaseException;
/**
* @deprecated
* Update a single entity
* @param entityType type of the entity
* @param uniqAttributes Attributes that uniquely identify the entity
......
......@@ -37,5 +37,9 @@ public interface EntityGraphDiscovery {
*/
EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException;
void validateAndNormalize(AtlasEntity entity) throws AtlasBaseException;
void validateAndNormalizeForUpdate(AtlasEntity entity) throws AtlasBaseException;
void cleanUp() throws AtlasBaseException;
}
......@@ -59,9 +59,8 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
@Override
public EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException {
// walk through entities in stream and validate them; record entity references
discoverAndValidate();
discover();
// resolve entity references discovered in previous step
resolveReferences();
......@@ -70,12 +69,58 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
}
@Override
public void validateAndNormalize(AtlasEntity entity) throws AtlasBaseException {
List<String> messages = new ArrayList<>();
if (!AtlasEntity.isAssigned(entity.getGuid()) && !AtlasEntity.isUnAssigned(entity.getGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_OBJECT_ID, "invalid guid " + entity.getGuid());
}
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
if (type == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName());
}
type.validateValue(entity, entity.getTypeName(), messages);
if (!messages.isEmpty()) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages);
}
type.getNormalizedValue(entity);
}
@Override
public void validateAndNormalizeForUpdate(AtlasEntity entity) throws AtlasBaseException {
List<String> messages = new ArrayList<>();
if (!AtlasEntity.isAssigned(entity.getGuid()) && !AtlasEntity.isUnAssigned(entity.getGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_OBJECT_ID, "invalid guid " + entity.getGuid());
}
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
if (type == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName());
}
type.validateValueForUpdate(entity, entity.getTypeName(), messages);
if (!messages.isEmpty()) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages);
}
type.getNormalizedValueForUpdate(entity);
}
@Override
public void cleanUp() throws AtlasBaseException {
discoveryContext.cleanUp();
}
protected void discoverAndValidate() throws AtlasBaseException {
protected void discover() throws AtlasBaseException {
EntityStream entityStream = discoveryContext.getEntityStream();
Set<String> walkedEntities = new HashSet<>();
......@@ -261,7 +306,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
return;
}
validateAndNormalize(entity);
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
recordObjectReference(entity.getGuid());
......@@ -274,28 +318,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
return typeCategory == TypeCategory.PRIMITIVE || typeCategory == TypeCategory.ENUM;
}
private void validateAndNormalize(AtlasEntity entity) throws AtlasBaseException {
List<String> messages = new ArrayList<>();
if (!AtlasEntity.isAssigned(entity.getGuid()) && !AtlasEntity.isUnAssigned(entity.getGuid())) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_OBJECT_ID, "invalid guid " + entity.getGuid());
}
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
if (type == null) {
throw new AtlasBaseException(AtlasErrorCode.TYPE_NAME_INVALID, TypeCategory.ENTITY.name(), entity.getTypeName());
}
type.validateValue(entity, entity.getTypeName(), messages);
if (!messages.isEmpty()) {
throw new AtlasBaseException(AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS, messages);
}
type.getNormalizedValue(entity);
}
private void recordObjectReference(String guid) {
discoveryContext.addReferencedGuid(guid);
}
......
......@@ -136,7 +136,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
@Override
@GraphTransaction
public EntityMutationResponse createOrUpdate(EntityStream entityStream) throws AtlasBaseException {
public EntityMutationResponse createOrUpdate(EntityStream entityStream, boolean isPartialUpdate) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("==> createOrUpdate()");
}
......@@ -145,12 +145,12 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entities to create/update.");
}
// Create/Update entities
EntityGraphMapper entityGraphMapper = new EntityGraphMapper(deleteHandler, typeRegistry);
// Create/Update entities
EntityMutationContext context = preCreateOrUpdate(entityStream, entityGraphMapper);
EntityMutationContext context = preCreateOrUpdate(entityStream, entityGraphMapper, isPartialUpdate);
EntityMutationResponse ret = entityGraphMapper.mapAttributes(context);
EntityMutationResponse ret = entityGraphMapper.mapAttributes(context, isPartialUpdate);
ret.setGuidAssignments(context.getGuidAssignments());
......@@ -164,8 +164,21 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
@Override
@GraphTransaction
public EntityMutationResponse updateByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes,
AtlasEntity entity) throws AtlasBaseException {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "updateByUniqueAttributes() not implemented yet");
AtlasEntity updatedEntity) throws AtlasBaseException {
if (LOG.isDebugEnabled()) {
LOG.debug("==> updateByUniqueAttributes({}, {})", entityType.getTypeName(), uniqAttributes);
}
if (updatedEntity == null) {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entity to update.");
}
AtlasVertex entityVertex = AtlasGraphUtilsV1.getVertexByUniqueAttributes(entityType, uniqAttributes);
updatedEntity.setGuid(AtlasGraphUtilsV1.getIdFromVertex(entityVertex));
return createOrUpdate(new AtlasEntityStream(updatedEntity), true);
}
@GraphTransaction
......@@ -256,7 +269,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
}
private EntityMutationContext preCreateOrUpdate(EntityStream entityStream, EntityGraphMapper entityGraphMapper) throws AtlasBaseException {
private EntityMutationContext preCreateOrUpdate(EntityStream entityStream, EntityGraphMapper entityGraphMapper, boolean isPartialUpdate) throws AtlasBaseException {
EntityGraphDiscovery graphDiscoverer = new AtlasEntityGraphDiscoveryV1(typeRegistry, entityStream);
EntityGraphDiscoveryContext discoveryContext = graphDiscoverer.discoverEntities();
EntityMutationContext context = new EntityMutationContext(discoveryContext);
......@@ -265,9 +278,16 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
AtlasVertex vertex = discoveryContext.getResolvedEntityVertex(guid);
AtlasEntity entity = entityStream.getByGuid(guid);
if (entity != null) {
if (vertex != null) {
// entity would be null if guid is not in the stream but referenced by an entity in the stream
if (entity != null) {
if (!isPartialUpdate) {
graphDiscoverer.validateAndNormalize(entity);
} else {
graphDiscoverer.validateAndNormalizeForUpdate(entity);
}
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
String guidVertex = AtlasGraphUtilsV1.getIdFromVertex(vertex);
......@@ -277,8 +297,9 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
}
context.addUpdated(guid, entity, entityType, vertex);
}
} else {
graphDiscoverer.validateAndNormalize(entity);
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
//Create vertices which do not exist in the repository
......@@ -291,7 +312,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
entity.setGuid(generatedGuid);
context.addCreated(guid, entity, entityType, vertex);
}
}
}
......
......@@ -63,6 +63,7 @@ import java.util.Set;
import java.util.UUID;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.CREATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.PARTIAL_UPDATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.UPDATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.DELETE;
......@@ -103,7 +104,7 @@ public class EntityGraphMapper {
return ret;
}
public EntityMutationResponse mapAttributes(EntityMutationContext context) throws AtlasBaseException {
public EntityMutationResponse mapAttributes(EntityMutationContext context, boolean isPartialUpdate) throws AtlasBaseException {
EntityMutationResponse resp = new EntityMutationResponse();
Collection<AtlasEntity> createdEntities = context.getCreatedEntities();
......@@ -129,8 +130,13 @@ public class EntityGraphMapper {
mapAttributes(updatedEntity, vertex, UPDATE, context);
if (isPartialUpdate) {
resp.addEntity(PARTIAL_UPDATE, constructHeader(updatedEntity, entityType, vertex));
} else {
resp.addEntity(UPDATE, constructHeader(updatedEntity, entityType, vertex));
}
}
}
RequestContextV1 req = RequestContextV1.get();
......
......@@ -163,7 +163,7 @@ public abstract class AtlasDeleteHandlerV1Test {
public void testDeleteAndCreate() throws Exception {
init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
init();
//delete entity should mark it as deleted
......@@ -182,7 +182,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init();
//Create the same entity again, should create new entity
AtlasEntity newDBEntity = TestUtilsV2.createDBEntity((String) dbEntity.getAttribute(NAME));
EntityMutationResponse newCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(newDBEntity));
EntityMutationResponse newCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(newDBEntity), false);
assertNotEquals(newCreationResponse.getFirstEntityCreated().getGuid(), response.getFirstEntityCreated().getGuid());
//TODO - Enable after GET is ready
......@@ -197,7 +197,7 @@ public abstract class AtlasDeleteHandlerV1Test {
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
init();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
final AtlasEntity columnEntity = TestUtilsV2.createColumnEntity(tableEntity);
......@@ -207,7 +207,7 @@ public abstract class AtlasDeleteHandlerV1Test {
input.addReferredEntity(columnEntity);
init();
EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(input));
EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(input), false);
final AtlasEntityHeader columnCreated = tblCreationResponse.getFirstCreatedEntityByTypeName(COLUMN_TYPE);
final AtlasEntityHeader tableCreated = tblCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE);
......@@ -227,7 +227,7 @@ public abstract class AtlasDeleteHandlerV1Test {
//Deleting table should update process
AtlasEntity process = TestUtilsV2.createProcessEntity(null, Arrays.asList(tableCreated.getAtlasObjectId()));
init();
final EntityMutationResponse processCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(process));
final EntityMutationResponse processCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(process), false);
init();
entityStore.deleteById(tableCreated.getGuid());
......@@ -242,7 +242,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Create a table entity, with 3 composite column entities
init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
......@@ -258,7 +258,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init();
final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
final AtlasEntityHeader column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
......@@ -296,7 +296,7 @@ public abstract class AtlasDeleteHandlerV1Test {
entitiesInfo1.addReferredEntity(columnEntity3New);
init();
deletionResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo1));
deletionResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo1), false);
//TODO - enable after fixing unique atribute resolver
assertEquals(deletionResponse.getDeletedEntities().size(), 1);
......@@ -347,7 +347,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init();
RequestContextV1.clear();
final EntityMutationResponse hrDeptCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(hrDept));
final EntityMutationResponse hrDeptCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(hrDept), false);
final AtlasEntityHeader deptCreated = hrDeptCreationResponse.getFirstUpdatedEntityByTypeName(DEPARTMENT_TYPE);
final AtlasEntityHeader maxEmployeeCreated = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max");
final AtlasEntityHeader johnEmployeeCreated = hrDeptCreationResponse.getUpdatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "John");
......@@ -372,7 +372,7 @@ public abstract class AtlasDeleteHandlerV1Test {
maxEmployee.setAttribute("manager", janeEmployeeCreated.getAtlasObjectId());
init();
EntityMutationResponse entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee));
EntityMutationResponse entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee), false);
assertEquals(entityResult.getUpdatedEntities().size(), 1);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
......@@ -391,7 +391,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Update max's mentor reference to jane.
maxEmployee.setAttribute("mentor", janeEmployeeCreated.getAtlasObjectId());
init();
entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee));
entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee), false);
assertEquals(entityResult.getUpdatedEntities().size(), 1);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
......@@ -411,7 +411,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init();
maxEmployee.setAttribute("manager", juliusEmployeeCreated.getAtlasObjectId());
entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee));
entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee), false);
//TODO ATLAS-499 should have updated julius' subordinates
assertEquals(entityResult.getUpdatedEntities().size(), 2);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
......@@ -464,7 +464,7 @@ public abstract class AtlasDeleteHandlerV1Test {
public void testDisconnectBidirectionalReferences() throws Exception {
AtlasEntity.AtlasEntitiesWithExtInfo hrDept = TestUtilsV2.createDeptEg2();
init();
final EntityMutationResponse hrDeptCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(hrDept));
final EntityMutationResponse hrDeptCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(hrDept), false);
final AtlasEntityHeader deptCreated = hrDeptCreationResponse.getFirstCreatedEntityByTypeName(DEPARTMENT_TYPE);
final AtlasEntityHeader maxEmployee = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max");
......@@ -647,7 +647,7 @@ public abstract class AtlasDeleteHandlerV1Test {
AtlasEntityStream entityStream = new AtlasEntityStream(structCreationObj);
EntityMutationResponse response = entityStore.createOrUpdate(entityStream);
EntityMutationResponse response = entityStore.createOrUpdate(entityStream, false);
Assert.assertEquals(response.getCreatedEntities().size(), 3);
final List<String> structTarget = metadataService.getEntityList("StructTarget");
......@@ -726,7 +726,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Create a table entity, with 3 composite column entities
init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
......@@ -742,7 +742,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init();
final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
final AtlasEntityHeader column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
......
......@@ -18,6 +18,7 @@
package org.apache.atlas.repository.store.graph.v1;
import com.google.common.collect.ImmutableSet;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.AtlasException;
import org.apache.atlas.RepositoryMetadataModule;
import org.apache.atlas.RequestContextV1;
......@@ -68,7 +69,10 @@ import java.util.List;
import java.util.Map;
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.randomString;
import static org.apache.atlas.TestUtilsV2.TABLE_TYPE;
import static org.testng.Assert.assertEquals;
@Guice(modules = RepositoryMetadataModule.class)
......@@ -130,7 +134,7 @@ public class AtlasEntityStoreV1Test {
@Test
public void testCreate() throws Exception {
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity), false);
validateMutationResponse(response, EntityOperation.CREATE, 5);
AtlasEntityHeader dept1 = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DEPARTMENT_TYPE);
......@@ -150,7 +154,7 @@ public class AtlasEntityStoreV1Test {
//Create DB
init();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
validateMutationResponse(dbCreationResponse, EntityOperation.CREATE, 1);
AtlasEntityHeader db1 = dbCreationResponse.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
......@@ -163,10 +167,10 @@ public class AtlasEntityStoreV1Test {
tblEntity.addReferredEntity(dbEntity.getEntity());
init();
EntityMutationResponse tableCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(tblEntity));
EntityMutationResponse tableCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(tblEntity), false);
validateMutationResponse(tableCreationResponse, EntityOperation.CREATE, 1);
AtlasEntityHeader tableEntity = tableCreationResponse.getFirstCreatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader tableEntity = tableCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE);
validateEntity(tblEntity, getEntityFromStore(tableEntity));
}
......@@ -193,7 +197,7 @@ public class AtlasEntityStoreV1Test {
entitiesInfo.addReferredEntity(col2);
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
......@@ -213,7 +217,7 @@ public class AtlasEntityStoreV1Test {
entitiesInfo.addReferredEntity(col4);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
......@@ -225,7 +229,7 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
Assert.assertEquals(((List<AtlasObjectId>) updatedTable.getAttribute(COLUMNS_ATTR_NAME)).size(), 2);
......@@ -236,7 +240,7 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute(COLUMNS_ATTR_NAME, null);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(tableEntity.getTypeName());
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
......@@ -254,9 +258,9 @@ public class AtlasEntityStoreV1Test {
entitiesInfo.addReferredEntity(tableEntity);
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition1 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader tableDefinition1 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition1));
Assert.assertTrue(partsMap.get("part0").equals(((Map<String, AtlasStruct>) tableDefinition1.getAttribute("partitionsMap")).get("part0")));
......@@ -266,9 +270,9 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute("partitionsMap", partsMap);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition2 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader tableDefinition2 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition2));
assertEquals(((Map<String, AtlasStruct>) tableDefinition2.getAttribute("partitionsMap")).size(), 2);
......@@ -280,9 +284,9 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute("partitionsMap", partsMap);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition3 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader tableDefinition3 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition3));
assertEquals(((Map<String, AtlasStruct>) tableDefinition3.getAttribute("partitionsMap")).size(), 2);
......@@ -294,9 +298,9 @@ public class AtlasEntityStoreV1Test {
partition2.setAttribute(TestUtilsV2.NAME, "test2Updated");
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition4 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader tableDefinition4 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition4));
assertEquals(((Map<String, AtlasStruct>) tableDefinition4.getAttribute("partitionsMap")).size(), 2);
......@@ -314,7 +318,7 @@ public class AtlasEntityStoreV1Test {
col0WithExtendedInfo.addReferredEntity(dbEntity.getEntity());
init();
entityStore.createOrUpdate(new AtlasEntityStream(col0WithExtendedInfo));
entityStore.createOrUpdate(new AtlasEntityStream(col0WithExtendedInfo), false);
AtlasEntity col1 = new AtlasEntity(TestUtils.COLUMN_TYPE, TestUtilsV2.NAME, "test2");
col1.setAttribute("type", "string");
......@@ -325,7 +329,7 @@ public class AtlasEntityStoreV1Test {
col1WithExtendedInfo.addReferredEntity(dbEntity.getEntity());
init();
entityStore.createOrUpdate(new AtlasEntityStream(col1WithExtendedInfo));
entityStore.createOrUpdate(new AtlasEntityStream(col1WithExtendedInfo), false);
Map<String, AtlasObjectId> columnsMap = new HashMap<String, AtlasObjectId>();
columnsMap.put("col0", col0.getAtlasObjectId());
......@@ -336,8 +340,8 @@ public class AtlasEntityStoreV1Test {
entitiesInfo.addReferredEntity(col0);
entitiesInfo.addReferredEntity(col1);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader tableDefinition5 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition5 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition5));
//Swap elements
......@@ -347,23 +351,23 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute(TestUtils.COLUMNS_MAP, columnsMap);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader tableDefinition6 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition6 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition6));
//Drop the first key and change the class type as well to col0
columnsMap.clear();
columnsMap.put("col0", col0.getAtlasObjectId());
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader tableDefinition7 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition7 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition7));
//Clear state
tableEntity.setAttribute(TestUtils.COLUMNS_MAP, null);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader tableDefinition8 = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader tableDefinition8 = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(tableDefinition8));
}
......@@ -378,17 +382,17 @@ public class AtlasEntityStoreV1Test {
Map<String, String> paramsMap = (Map<String, String>) tableEntity.getAttribute("parametersMap");
paramsMap.put("newParam", "value");
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//Remove an entry
paramsMap.remove("key1");
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
validateMutationResponse(response, EntityMutations.EntityOperation.UPDATE, 1);
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
}
......@@ -405,44 +409,44 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute("partitions", partitions);
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//add a new element to array of struct
partitions.add(new AtlasStruct(TestUtils.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part3"));
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//remove one of the struct values
init();
partitions.remove(1);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//Update struct value within array of struct
init();
partitions.get(0).setAttribute(TestUtilsV2.NAME, "part4");
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//add a repeated element to array of struct
partitions.add(new AtlasStruct(TestUtils.PARTITION_STRUCT_TYPE, TestUtilsV2.NAME, "part4"));
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
// Remove all elements. Should set array attribute to null
partitions.clear();
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
}
......@@ -460,22 +464,22 @@ public class AtlasEntityStoreV1Test {
tableEntity.setAttribute("database", new AtlasObjectId(databaseEntity.getTypeName(), TestUtilsV2.NAME, databaseEntity.getAttribute(TestUtilsV2.NAME)));
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
AtlasEntityHeader updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//update struct attribute
serdeInstance.setAttribute("serde", "testUpdated");
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
//set to null
tableEntity.setAttribute("description", null);
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo));
updatedTable = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
updatedTable = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
Assert.assertNull(updatedTable.getAttribute("description"));
validateEntity(entitiesInfo, getEntityFromStore(updatedTable));
}
......@@ -506,7 +510,7 @@ public class AtlasEntityStoreV1Test {
//Create new db instance
final AtlasEntity databaseInstance = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(databaseInstance));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(databaseInstance), false);
final AtlasEntityHeader dbCreated = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
init();
......@@ -517,8 +521,8 @@ public class AtlasEntityStoreV1Test {
tableCloneMap.put(dbCreated.getGuid(), databaseInstance);
tableCloneMap.put(tableClone.getGuid(), tableClone);
response = entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap));
final AtlasEntityHeader tableDefinition = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.TABLE_TYPE);
response = entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap), false);
final AtlasEntityHeader tableDefinition = response.getFirstUpdatedEntityByTypeName(TABLE_TYPE);
Assert.assertNotNull(tableDefinition.getAttribute("database"));
Assert.assertEquals(((AtlasObjectId) tableDefinition.getAttribute("database")).getGuid(), dbCreated.getGuid());
}
......@@ -529,7 +533,7 @@ public class AtlasEntityStoreV1Test {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
init();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
AtlasEntityHeader firstEntityCreated = response.getFirstCreatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
//The optional boolean attribute should have a non-null value
......@@ -547,7 +551,7 @@ public class AtlasEntityStoreV1Test {
//Complete update
init();
response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity));
response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
AtlasEntityHeader firstEntityUpdated = response.getFirstUpdatedEntityByTypeName(TestUtilsV2.DATABASE_TYPE);
Assert.assertNotNull(firstEntityUpdated);
......@@ -599,7 +603,7 @@ public class AtlasEntityStoreV1Test {
AtlasEntityWithExtInfo entityWithExtInfo = new AtlasEntityWithExtInfo(entity);
final EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entityWithExtInfo));
final EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entityWithExtInfo), false);
final AtlasEntityHeader firstEntityCreated = response.getFirstEntityCreated();
validateEntity(entityWithExtInfo, getEntityFromStore(firstEntityCreated));
......@@ -616,14 +620,197 @@ public class AtlasEntityStoreV1Test {
public void testCreateRequiredAttrNull() throws Exception {
//Update required attribute
Map<String, AtlasEntity> tableCloneMap = new HashMap<>();
AtlasEntity tableEntity = new AtlasEntity(TestUtilsV2.TABLE_TYPE);
AtlasEntity tableEntity = new AtlasEntity(TABLE_TYPE);
tableEntity.setAttribute(TestUtilsV2.NAME, "table_" + TestUtils.randomString());
tableCloneMap.put(tableEntity.getGuid(), tableEntity);
entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap));
entityStore.createOrUpdate(new InMemoryMapEntityStream(tableCloneMap), false);
Assert.fail("Expected exception while creating with required attribute null");
}
@Test
public void testPartialUpdateAttr() throws Exception {
//Update optional attribute
init();
AtlasEntity dbEntity = new AtlasEntity(TestUtilsV2.DATABASE_TYPE);
dbEntity.setAttribute("name", RandomStringUtils.randomAlphanumeric(10));
dbEntity.setAttribute("description", "us db");
dbEntity.setAttribute("isReplicated", false);
dbEntity.setAttribute("created", "09081988");
dbEntity.setAttribute("namespace", "db namespace");
dbEntity.setAttribute("cluster", "Fenton_Cluster");
dbEntity.setAttribute("colo", "10001");
EntityStream dbStream = new AtlasEntityStream(new AtlasEntitiesWithExtInfo(dbEntity));
EntityMutationResponse response = entityStore.createOrUpdate(dbStream, false);
AtlasEntityHeader dbHeader = response.getFirstEntityCreated();
AtlasEntity createdDbEntity = getEntityFromStore(dbHeader);
// update the db entity
dbEntity = new AtlasEntity(TestUtilsV2.DATABASE_TYPE);
dbEntity.setGuid(createdDbEntity.getGuid());
// dbEntity.setAttribute("name", createdDbEntity.getAttribute("name"));
// dbEntity.setAttribute("description", "another db"); // required attr
dbEntity.setAttribute("created", "08151947"); // optional attr
dbEntity.setAttribute("isReplicated", true); // optional attr
dbStream = new AtlasEntityStream(new AtlasEntitiesWithExtInfo(dbEntity));
// fail full update if required attributes are not specified.
try {
entityStore.createOrUpdate(dbStream, false);
} catch (AtlasBaseException ex) {
Assert.assertEquals(ex.getAtlasErrorCode(), AtlasErrorCode.INSTANCE_CRUD_INVALID_PARAMS);
}
// do partial update without providing required attributes
dbStream.reset();
response = entityStore.createOrUpdate(dbStream, true);
dbHeader = response.getFirstEntityPartialUpdated();
AtlasEntity updatedDbEntity = getEntityFromStore(dbHeader);
assertEquals(updatedDbEntity.getAttribute("name"), createdDbEntity.getAttribute("name"));
assertEquals(updatedDbEntity.getAttribute("description"), createdDbEntity.getAttribute("description"));
assertEquals(updatedDbEntity.getAttribute("isReplicated"), true);
assertEquals(updatedDbEntity.getAttribute("created"), "08151947");
assertEquals(updatedDbEntity.getAttribute("namespace"), createdDbEntity.getAttribute("namespace"));
assertEquals(updatedDbEntity.getAttribute("cluster"), createdDbEntity.getAttribute("cluster"));
assertEquals(updatedDbEntity.getAttribute("colo"), createdDbEntity.getAttribute("colo"));
// create a new table type
AtlasEntity tblEntity = new AtlasEntity(TABLE_TYPE);
tblEntity.setAttribute("name", RandomStringUtils.randomAlphanumeric(10));
tblEntity.setAttribute("type", "type");
tblEntity.setAttribute("tableType", "MANAGED");
tblEntity.setAttribute("database", updatedDbEntity.getAtlasObjectId());
// create new column entity
AtlasEntity col1 = TestUtilsV2.createColumnEntity(tblEntity);
AtlasEntity col2 = TestUtilsV2.createColumnEntity(tblEntity);
col1.setAttribute(TestUtilsV2.NAME, "col1");
col2.setAttribute(TestUtilsV2.NAME, "col2");
List<AtlasObjectId> columns = new ArrayList<>();
columns.add(col1.getAtlasObjectId());
columns.add(col2.getAtlasObjectId());
tblEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
AtlasEntitiesWithExtInfo tableEntityInfo = new AtlasEntitiesWithExtInfo(tblEntity);
tableEntityInfo.addReferredEntity(col1.getGuid(), col1);
tableEntityInfo.addReferredEntity(col2.getGuid(), col2);
EntityStream tblStream = new AtlasEntityStream(tableEntityInfo);
response = entityStore.createOrUpdate(tblStream, false);
AtlasEntityHeader tblHeader = response.getFirstEntityCreated();
AtlasEntity createdTblEntity = getEntityFromStore(tblHeader);
columns = (List<AtlasObjectId>) createdTblEntity.getAttribute(TestUtilsV2.COLUMNS_ATTR_NAME);
assertEquals(columns.size(), 2);
// update - add 2 more columns to table
AtlasEntity col3 = TestUtilsV2.createColumnEntity(createdTblEntity);
col3.setAttribute(TestUtilsV2.NAME, "col3");
col3.setAttribute("description", "description col3");
AtlasEntity col4 = TestUtilsV2.createColumnEntity(createdTblEntity);
col4.setAttribute(TestUtilsV2.NAME, "col4");
col4.setAttribute("description", "description col4");
columns.clear();
columns.add(col3.getAtlasObjectId());
columns.add(col4.getAtlasObjectId());
tblEntity = new AtlasEntity(TABLE_TYPE);
tblEntity.setGuid(createdTblEntity.getGuid());
tblEntity.setAttribute(TestUtilsV2.COLUMNS_ATTR_NAME, columns);
tableEntityInfo = new AtlasEntitiesWithExtInfo(tblEntity);
tableEntityInfo.addReferredEntity(col3.getGuid(), col3);
tableEntityInfo.addReferredEntity(col4.getGuid(), col4);
tblStream = new AtlasEntityStream(tableEntityInfo);
response = entityStore.createOrUpdate(tblStream, true);
tblHeader = response.getFirstEntityPartialUpdated();
AtlasEntity updatedTblEntity = getEntityFromStore(tblHeader);
columns = (List<AtlasObjectId>) tblHeader.getAttribute(TestUtilsV2.COLUMNS_ATTR_NAME);
assertEquals(columns.size(), 2);
}
@Test
public void testPartialUpdateArrayAttr() throws Exception {
// Create a table entity, with 3 reference column entities
init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntitiesWithExtInfo(tableEntity);
final AtlasEntity columnEntity1 = TestUtilsV2.createColumnEntity(tableEntity);
columnEntity1.setAttribute("description", "desc for col1");
entitiesInfo.addReferredEntity(columnEntity1);
final AtlasEntity columnEntity2 = TestUtilsV2.createColumnEntity(tableEntity);
columnEntity2.setAttribute("description", "desc for col2");
entitiesInfo.addReferredEntity(columnEntity2);
final AtlasEntity columnEntity3 = TestUtilsV2.createColumnEntity(tableEntity);
columnEntity3.setAttribute("description", "desc for col3");
entitiesInfo.addReferredEntity(columnEntity3);
tableEntity.setAttribute(COLUMNS_ATTR_NAME, Arrays.asList(columnEntity1.getAtlasObjectId(), columnEntity2.getAtlasObjectId(), columnEntity3.getAtlasObjectId()));
init();
final EntityMutationResponse tblCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo), false);
final AtlasEntityHeader createdTblHeader = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(TABLE_TYPE, NAME, (String) tableEntity.getAttribute(NAME));
final AtlasEntity createdTblEntity = getEntityFromStore(createdTblHeader);
final AtlasEntityHeader column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
final AtlasEntityHeader column3Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity3.getAttribute(NAME));
// update only description attribute of all 3 columns
AtlasEntity col1 = new AtlasEntity(COLUMN_TYPE);
col1.setGuid(column1Created.getGuid());
col1.setAttribute("description", "desc for col1:updated");
AtlasEntity col2 = new AtlasEntity(COLUMN_TYPE);
col2.setGuid(column2Created.getGuid());
col2.setAttribute("description", "desc for col2:updated");
AtlasEntity col3 = new AtlasEntity(COLUMN_TYPE);
col3.setGuid(column3Created.getGuid());
col3.setAttribute("description", "desc for col3:updated");
final AtlasEntity tableEntity1 = new AtlasEntity(TABLE_TYPE);
tableEntity1.setGuid(createdTblHeader.getGuid());
tableEntity1.setAttribute(COLUMNS_ATTR_NAME, Arrays.asList(col1.getAtlasObjectId(), col2.getAtlasObjectId(), col3.getAtlasObjectId()));
AtlasEntitiesWithExtInfo tableInfo = new AtlasEntitiesWithExtInfo(tableEntity1);
tableInfo.addReferredEntity(col1.getGuid(), col1);
tableInfo.addReferredEntity(col2.getGuid(), col2);
tableInfo.addReferredEntity(col3.getGuid(), col3);
init();
final EntityMutationResponse tblUpdateResponse = entityStore.createOrUpdate(new AtlasEntityStream(tableInfo), true);
final AtlasEntityHeader updatedTblHeader = tblUpdateResponse.getFirstEntityPartialUpdated();
final AtlasEntity updatedTblEntity2 = getEntityFromStore(updatedTblHeader);
List<AtlasEntityHeader> updatedColHeaders = tblUpdateResponse.getPartialUpdatedEntitiesByTypeName(COLUMN_TYPE);
final AtlasEntity updatedCol1Entity = getEntityFromStore(updatedColHeaders.get(0));
final AtlasEntity updatedCol2Entity = getEntityFromStore(updatedColHeaders.get(1));
final AtlasEntity updatedCol3Entity = getEntityFromStore(updatedColHeaders.get(2));
assertEquals(col1.getAttribute("description"), updatedCol1Entity.getAttribute("description"));
assertEquals(col2.getAttribute("description"), updatedCol2Entity.getAttribute("description"));
assertEquals(col3.getAttribute("description"), updatedCol3Entity.getAttribute("description"));
}
private String randomStrWithReservedChars() {
return randomString() + "\"${}%";
......
......@@ -133,7 +133,7 @@ public class EntityREST {
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse createOrUpdate(AtlasEntityWithExtInfo entity) throws AtlasBaseException {
return entitiesStore.createOrUpdate(new AtlasEntityStream(entity));
return entitiesStore.createOrUpdate(new AtlasEntityStream(entity), false);
}
/**
......@@ -164,29 +164,19 @@ public class EntityREST {
* an entity which is identified by its type and unique attribute eg: Referenceable.qualifiedName.
* Null updates are not possible
*******/
@Deprecated
@PUT
@Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE)
@Path("/uniqueAttribute/type/{typeName}")
public EntityMutationResponse partialUpdateByUniqueAttribute(@PathParam("typeName") String typeName,
public EntityMutationResponse partialUpdateByUniqueAttributes(@PathParam("typeName") String typeName,
@Context HttpServletRequest servletRequest,
AtlasEntity entity) throws Exception {
AtlasEntityType entityType = ensureEntityType(typeName);
Map<String, Object> attributes = getAttributes(servletRequest);
Map<String, Object> uniqueAttributes = getAttributes(servletRequest);
validateUniqueAttribute(entityType, attributes);
validateUniqueAttribute(entityType, uniqueAttributes);
// legacy API supports only one unique attribute
String attribute = attributes.keySet().toArray(new String[1])[0];
String value = (String)attributes.get(attribute);
AtlasFormatConverter.ConverterContext ctx = new AtlasFormatConverter.ConverterContext();
ctx.addEntity(entity);
Referenceable ref = restAdapters.getReferenceable(entity, ctx);
CreateUpdateEntitiesResult result = metadataService.updateEntityByUniqueAttribute(typeName, attribute, value, ref);
return toEntityMutationResponse(result);
return entitiesStore.updateByUniqueAttributes(entityType, uniqueAttributes, entity);
}
@Deprecated
......@@ -239,7 +229,7 @@ public class EntityREST {
EntityStream entityStream = new AtlasEntityStream(entities);
return entitiesStore.createOrUpdate(entityStream);
return entitiesStore.createOrUpdate(entityStream, false);
}
/*******
......
......@@ -153,6 +153,37 @@ public class TestEntityREST {
}
@Test
public void testPartialUpdateByUniqueAttribute() throws Exception {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity));
String dbGuid = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE).get(0).getGuid();
Assert.assertTrue(AtlasEntity.isAssigned(dbGuid));
final String prevDBName = (String) dbEntity.getAttribute(TestUtilsV2.NAME);
final String updatedDBName = prevDBName + ":updated";
Map<String, Object> dbAttrs = dbEntity.getAttributes();
// partial update only db name
dbEntity = new AtlasEntity(TestUtilsV2.DATABASE_TYPE);
dbEntity.setGuid(dbGuid);
dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName);
dbAttrs.putAll(dbEntity.getAttributes());
response = entityREST.partialUpdateByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.PARTIAL_UPDATE).get(0).getGuid(), dbGuid);
//Get By unique attribute
AtlasEntityWithExtInfo entity = entityREST.getByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, updatedDBName));
Assert.assertNotNull(entity);
Assert.assertNotNull(entity.getEntity().getGuid());
Assert.assertEquals(entity.getEntity().getGuid(), dbGuid);
TestEntitiesREST.verifyAttributes(entity.getEntity().getAttributes(), dbAttrs);
}
@Test
public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity));
......@@ -165,8 +196,9 @@ public class TestEntityREST {
dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName);
response = entityREST.partialUpdateByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).get(0).getGuid(), dbGuid);
response = entityREST.partialUpdateByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.PARTIAL_UPDATE).get(0).getGuid(), dbGuid);
//Get By unique attribute
AtlasEntityWithExtInfo entity = entityREST.getByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, updatedDBName));
......
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