Commit 68c55925 by Sarath Subramanian Committed by Madhan Neethiraj

ATLAS-1554 : v2 EntityREST implementation for entity partial update

parent c5ea4f0e
No related merge requests found
...@@ -32,6 +32,7 @@ import javax.xml.bind.annotation.XmlAccessorType; ...@@ -32,6 +32,7 @@ import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlRootElement;
import org.apache.atlas.model.typedef.AtlasBaseTypeDef; 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.JsonAutoDetect;
import org.codehaus.jackson.annotate.JsonIgnore; import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonIgnoreProperties; import org.codehaus.jackson.annotate.JsonIgnoreProperties;
...@@ -44,21 +45,21 @@ import org.codehaus.jackson.map.annotate.JsonSerialize; ...@@ -44,21 +45,21 @@ import org.codehaus.jackson.map.annotate.JsonSerialize;
@XmlAccessorType(XmlAccessType.PROPERTY) @XmlAccessorType(XmlAccessType.PROPERTY)
public class EntityMutationResponse { public class EntityMutationResponse {
Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities; Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities;
Map<String,String> guidAssignments; Map<String, String> guidAssignments;
public EntityMutationResponse() { public EntityMutationResponse() {
} }
public EntityMutationResponse(final Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities) { public EntityMutationResponse(final Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
this.mutatedEntities = mutatedEntities; this.mutatedEntities = mutatedEntities;
} }
public Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> getMutatedEntities() { public Map<EntityOperation, List<AtlasEntityHeader>> getMutatedEntities() {
return mutatedEntities; return mutatedEntities;
} }
public void setMutatedEntities(final Map<EntityMutations.EntityOperation, List<AtlasEntityHeader>> mutatedEntities) { public void setMutatedEntities(final Map<EntityOperation, List<AtlasEntityHeader>> mutatedEntities) {
this.mutatedEntities = mutatedEntities; this.mutatedEntities = mutatedEntities;
} }
...@@ -72,7 +73,7 @@ public class EntityMutationResponse { ...@@ -72,7 +73,7 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getEntitiesByOperation(EntityMutations.EntityOperation op) { public List<AtlasEntityHeader> getEntitiesByOperation(EntityOperation op) {
if ( mutatedEntities != null) { if ( mutatedEntities != null) {
return mutatedEntities.get(op); return mutatedEntities.get(op);
} }
...@@ -82,7 +83,7 @@ public class EntityMutationResponse { ...@@ -82,7 +83,7 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getCreatedEntities() { public List<AtlasEntityHeader> getCreatedEntities() {
if ( mutatedEntities != null) { if ( mutatedEntities != null) {
return mutatedEntities.get(EntityMutations.EntityOperation.CREATE); return mutatedEntities.get(EntityOperation.CREATE);
} }
return null; return null;
} }
...@@ -90,7 +91,14 @@ public class EntityMutationResponse { ...@@ -90,7 +91,14 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getUpdatedEntities() { public List<AtlasEntityHeader> getUpdatedEntities() {
if ( mutatedEntities != null) { 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; return null;
} }
...@@ -98,14 +106,14 @@ public class EntityMutationResponse { ...@@ -98,14 +106,14 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getDeletedEntities() { public List<AtlasEntityHeader> getDeletedEntities() {
if ( mutatedEntities != null) { if ( mutatedEntities != null) {
return mutatedEntities.get(EntityMutations.EntityOperation.DELETE); return mutatedEntities.get(EntityOperation.DELETE);
} }
return null; return null;
} }
@JsonIgnore @JsonIgnore
public AtlasEntityHeader getFirstEntityCreated() { public AtlasEntityHeader getFirstEntityCreated() {
final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); final List<AtlasEntityHeader> entitiesByOperation = getEntitiesByOperation(EntityOperation.CREATE);
if ( entitiesByOperation != null && entitiesByOperation.size() > 0) { if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
return entitiesByOperation.get(0); return entitiesByOperation.get(0);
} }
...@@ -115,7 +123,18 @@ public class EntityMutationResponse { ...@@ -115,7 +123,18 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public AtlasEntityHeader getFirstEntityUpdated() { 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) { if ( entitiesByOperation != null && entitiesByOperation.size() > 0) {
return entitiesByOperation.get(0); return entitiesByOperation.get(0);
} }
...@@ -125,45 +144,51 @@ public class EntityMutationResponse { ...@@ -125,45 +144,51 @@ public class EntityMutationResponse {
@JsonIgnore @JsonIgnore
public AtlasEntityHeader getFirstCreatedEntityByTypeName(String typeName) { public AtlasEntityHeader getFirstCreatedEntityByTypeName(String typeName) {
return getFirstEntityByType(getEntitiesByOperation(EntityMutations.EntityOperation.CREATE), typeName); return getFirstEntityByType(getEntitiesByOperation(EntityOperation.CREATE), typeName);
} }
@JsonIgnore @JsonIgnore
public AtlasEntityHeader getFirstDeletedEntityByTypeName(String typeName) { public AtlasEntityHeader getFirstDeletedEntityByTypeName(String typeName) {
return getFirstEntityByType(getEntitiesByOperation(EntityMutations.EntityOperation.DELETE), typeName); return getFirstEntityByType(getEntitiesByOperation(EntityOperation.DELETE), typeName);
} }
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getCreatedEntitiesByTypeName(String typeName) { 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 @JsonIgnore
public AtlasEntityHeader getCreatedEntityByTypeNameAndAttribute(String typeName, String attrName, String attrVal) { 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 @JsonIgnore
public AtlasEntityHeader getUpdatedEntityByTypeNameAndAttribute(String typeName, String attrName, String attrVal) { 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 @JsonIgnore
public List<AtlasEntityHeader> getUpdatedEntitiesByTypeName(String typeName) { public List<AtlasEntityHeader> getUpdatedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE), typeName); return getEntitiesByType(getEntitiesByOperation(EntityOperation.UPDATE), typeName);
} }
@JsonIgnore @JsonIgnore
public List<AtlasEntityHeader> getDeletedEntitiesByTypeName(String typeName) { public List<AtlasEntityHeader> getDeletedEntitiesByTypeName(String typeName) {
return getEntitiesByType(getEntitiesByOperation(EntityMutations.EntityOperation.DELETE), typeName); return getEntitiesByType(getEntitiesByOperation(EntityOperation.DELETE), typeName);
} }
@JsonIgnore @JsonIgnore
public AtlasEntityHeader getFirstUpdatedEntityByTypeName(String typeName) { 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) { if (mutatedEntities == null) {
mutatedEntities = new HashMap<>(); mutatedEntities = new HashMap<>();
} }
......
...@@ -161,6 +161,41 @@ public class AtlasArrayType extends AtlasType { ...@@ -161,6 +161,41 @@ public class AtlasArrayType extends AtlasType {
} }
@Override @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) { public Collection<?> getNormalizedValue(Object obj) {
if (obj == null) { if (obj == null) {
return null; return null;
...@@ -222,6 +257,67 @@ public class AtlasArrayType extends AtlasType { ...@@ -222,6 +257,67 @@ public class AtlasArrayType extends AtlasType {
} }
@Override @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) { public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true; boolean ret = true;
...@@ -265,6 +361,49 @@ public class AtlasArrayType extends AtlasType { ...@@ -265,6 +361,49 @@ public class AtlasArrayType extends AtlasType {
} }
@Override @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() { public AtlasType getTypeForAttribute() {
AtlasType elementAttributeType = elementType.getTypeForAttribute(); AtlasType elementAttributeType = elementType.getTypeForAttribute();
......
...@@ -159,6 +159,21 @@ public class AtlasClassificationType extends AtlasStructType { ...@@ -159,6 +159,21 @@ public class AtlasClassificationType extends AtlasStructType {
} }
@Override @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) { public Object getNormalizedValue(Object obj) {
Object ret = null; Object ret = null;
...@@ -178,6 +193,25 @@ public class AtlasClassificationType extends AtlasStructType { ...@@ -178,6 +193,25 @@ public class AtlasClassificationType extends AtlasStructType {
} }
@Override @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) { public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true; boolean ret = true;
...@@ -192,6 +226,21 @@ public class AtlasClassificationType extends AtlasStructType { ...@@ -192,6 +226,21 @@ public class AtlasClassificationType extends AtlasStructType {
return ret; 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) { public void normalizeAttributeValues(AtlasClassification classification) {
if (classification != null) { if (classification != null) {
for (AtlasClassificationType superType : superTypes) { for (AtlasClassificationType superType : superTypes) {
...@@ -202,6 +251,16 @@ public class AtlasClassificationType extends AtlasStructType { ...@@ -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 @Override
public void normalizeAttributeValues(Map<String, Object> obj) { public void normalizeAttributeValues(Map<String, Object> obj) {
if (obj != null) { if (obj != null) {
...@@ -213,6 +272,16 @@ public class AtlasClassificationType extends AtlasStructType { ...@@ -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) { public void populateDefaultValues(AtlasClassification classification) {
if (classification != null) { if (classification != null) {
for (AtlasClassificationType superType : superTypes) { for (AtlasClassificationType superType : superTypes) {
......
...@@ -142,17 +142,26 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -142,17 +142,26 @@ public class AtlasEntityType extends AtlasStructType {
@Override @Override
public boolean isValidValue(Object obj) { public boolean isValidValue(Object obj) {
if (obj != null) { if (obj != null) {
if (obj instanceof AtlasObjectId) { for (AtlasEntityType superType : superTypes) {
AtlasObjectId objId = (AtlasObjectId ) obj; if (!superType.isValidValue(obj)) {
return isAssignableFrom(objId); return false;
} else { }
for (AtlasEntityType superType : superTypes) { }
if (!superType.isValidValue(obj)) { return super.isValidValue(obj);
return false; }
}
return true;
}
@Override
public boolean isValidValueForUpdate(Object obj) {
if (obj != null) {
for (AtlasEntityType superType : superTypes) {
if (!superType.isValidValueForUpdate(obj)) {
return false;
} }
return super.isValidValue(obj);
} }
return super.isValidValueForUpdate(obj);
} }
return true; return true;
...@@ -170,7 +179,24 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -170,7 +179,24 @@ public class AtlasEntityType extends AtlasStructType {
} else if (obj instanceof Map) { } else if (obj instanceof Map) {
normalizeAttributeValues((Map) obj); normalizeAttributeValues((Map) obj);
ret = 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; ret = obj;
} }
} }
...@@ -189,30 +215,38 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -189,30 +215,38 @@ public class AtlasEntityType extends AtlasStructType {
boolean ret = true; boolean ret = true;
if (obj != null) { if (obj != null) {
if (obj instanceof AtlasObjectId) { if (obj instanceof AtlasEntity || obj instanceof Map) {
AtlasObjectId objId = (AtlasObjectId) obj; for (AtlasEntityType superType : superTypes) {
return isAssignableFrom(objId); ret = superType.validateValue(obj, objName, messages) && ret;
} 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;
} }
// entity validation will be done below, outside of these if/else blocks ret = super.validateValue(obj, objName, messages) && ret;
} else { } else {
ret = false; ret = false;
messages.add(objName + ": invalid value type '" + obj.getClass().getName()); messages.add(objName + ": invalid value type '" + obj.getClass().getName());
} }
}
for (AtlasEntityType superType : superTypes) { return ret;
ret = superType.validateValue(obj, objName, messages) && ret; }
}
ret = super.validateValue(obj, objName, messages) && 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.validateValueForUpdate(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; return ret;
...@@ -239,6 +273,16 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -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 @Override
public void normalizeAttributeValues(Map<String, Object> obj) { public void normalizeAttributeValues(Map<String, Object> obj) {
if (obj != null) { if (obj != null) {
...@@ -250,6 +294,16 @@ public class AtlasEntityType extends AtlasStructType { ...@@ -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) { public void populateDefaultValues(AtlasEntity ent) {
if (ent != null) { if (ent != null) {
for (AtlasEntityType superType : superTypes) { for (AtlasEntityType superType : superTypes) {
......
...@@ -124,6 +124,25 @@ public class AtlasMapType extends AtlasType { ...@@ -124,6 +124,25 @@ public class AtlasMapType extends AtlasType {
} }
@Override @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) { public Map<Object, Object> getNormalizedValue(Object obj) {
if (obj == null) { if (obj == null) {
return null; return null;
...@@ -163,6 +182,45 @@ public class AtlasMapType extends AtlasType { ...@@ -163,6 +182,45 @@ public class AtlasMapType extends AtlasType {
} }
@Override @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) { public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true; boolean ret = true;
...@@ -194,6 +252,37 @@ public class AtlasMapType extends AtlasType { ...@@ -194,6 +252,37 @@ public class AtlasMapType extends AtlasType {
} }
@Override @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() { public AtlasType getTypeForAttribute() {
AtlasType keyAttributeType = keyType.getTypeForAttribute(); AtlasType keyAttributeType = keyType.getTypeForAttribute();
AtlasType valueAttributeType = valueType.getTypeForAttribute(); AtlasType valueAttributeType = valueType.getTypeForAttribute();
......
...@@ -77,6 +77,14 @@ public abstract class AtlasType { ...@@ -77,6 +77,14 @@ public abstract class AtlasType {
return ret; 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 /* for attribute of entity-type, the value would be of AtlasObjectId
* when an attribute instance is created i.e. AtlasAttribute, this method * when an attribute instance is created i.e. AtlasAttribute, this method
* will be called to get AtlasEntityType replaced with AtlasObjectType * will be called to get AtlasEntityType replaced with AtlasObjectType
......
...@@ -582,6 +582,7 @@ public final class TestUtilsV2 { ...@@ -582,6 +582,7 @@ public final class TestUtilsV2 {
ImmutableSet.<String>of(), ImmutableSet.<String>of(),
AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"), AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createRequiredAttrDef("type", "string"), AtlasTypeUtil.createRequiredAttrDef("type", "string"),
AtlasTypeUtil.createOptionalAttrDef("description", "string"),
new AtlasAttributeDef("table", TABLE_TYPE, new AtlasAttributeDef("table", TABLE_TYPE,
true, true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1, AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
......
...@@ -66,10 +66,9 @@ public interface AtlasEntityStore { ...@@ -66,10 +66,9 @@ public interface AtlasEntityStore {
* @return EntityMutationResponse Entity mutations operations with the corresponding set of entities on which these operations were performed * @return EntityMutationResponse Entity mutations operations with the corresponding set of entities on which these operations were performed
* @throws AtlasBaseException * @throws AtlasBaseException
*/ */
EntityMutationResponse createOrUpdate(EntityStream entityStream) throws AtlasBaseException; EntityMutationResponse createOrUpdate(EntityStream entityStream, boolean isPartialUpdate) throws AtlasBaseException;
/** /**
* @deprecated
* Update a single entity * Update a single entity
* @param entityType type of the entity * @param entityType type of the entity
* @param uniqAttributes Attributes that uniquely identify the entity * @param uniqAttributes Attributes that uniquely identify the entity
......
...@@ -37,5 +37,9 @@ public interface EntityGraphDiscovery { ...@@ -37,5 +37,9 @@ public interface EntityGraphDiscovery {
*/ */
EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException; EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException;
void validateAndNormalize(AtlasEntity entity) throws AtlasBaseException;
void validateAndNormalizeForUpdate(AtlasEntity entity) throws AtlasBaseException;
void cleanUp() throws AtlasBaseException; void cleanUp() throws AtlasBaseException;
} }
...@@ -59,9 +59,8 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -59,9 +59,8 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
@Override @Override
public EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException { public EntityGraphDiscoveryContext discoverEntities() throws AtlasBaseException {
// walk through entities in stream and validate them; record entity references // walk through entities in stream and validate them; record entity references
discoverAndValidate(); discover();
// resolve entity references discovered in previous step // resolve entity references discovered in previous step
resolveReferences(); resolveReferences();
...@@ -70,12 +69,58 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -70,12 +69,58 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
} }
@Override @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 { public void cleanUp() throws AtlasBaseException {
discoveryContext.cleanUp(); discoveryContext.cleanUp();
} }
protected void discoverAndValidate() throws AtlasBaseException { protected void discover() throws AtlasBaseException {
EntityStream entityStream = discoveryContext.getEntityStream(); EntityStream entityStream = discoveryContext.getEntityStream();
Set<String> walkedEntities = new HashSet<>(); Set<String> walkedEntities = new HashSet<>();
...@@ -261,7 +306,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -261,7 +306,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
return; return;
} }
validateAndNormalize(entity);
AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName()); AtlasEntityType type = typeRegistry.getEntityTypeByName(entity.getTypeName());
recordObjectReference(entity.getGuid()); recordObjectReference(entity.getGuid());
...@@ -274,28 +318,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery { ...@@ -274,28 +318,6 @@ public class AtlasEntityGraphDiscoveryV1 implements EntityGraphDiscovery {
return typeCategory == TypeCategory.PRIMITIVE || typeCategory == TypeCategory.ENUM; 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) { private void recordObjectReference(String guid) {
discoveryContext.addReferencedGuid(guid); discoveryContext.addReferencedGuid(guid);
} }
......
...@@ -136,7 +136,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -136,7 +136,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
@Override @Override
@GraphTransaction @GraphTransaction
public EntityMutationResponse createOrUpdate(EntityStream entityStream) throws AtlasBaseException { public EntityMutationResponse createOrUpdate(EntityStream entityStream, boolean isPartialUpdate) throws AtlasBaseException {
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
LOG.debug("==> createOrUpdate()"); LOG.debug("==> createOrUpdate()");
} }
...@@ -145,12 +145,12 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -145,12 +145,12 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entities to create/update."); throw new AtlasBaseException(AtlasErrorCode.INVALID_PARAMETERS, "no entities to create/update.");
} }
// Create/Update entities
EntityGraphMapper entityGraphMapper = new EntityGraphMapper(deleteHandler, typeRegistry); EntityGraphMapper entityGraphMapper = new EntityGraphMapper(deleteHandler, typeRegistry);
// Create/Update entities EntityMutationContext context = preCreateOrUpdate(entityStream, entityGraphMapper, isPartialUpdate);
EntityMutationContext context = preCreateOrUpdate(entityStream, entityGraphMapper);
EntityMutationResponse ret = entityGraphMapper.mapAttributes(context); EntityMutationResponse ret = entityGraphMapper.mapAttributes(context, isPartialUpdate);
ret.setGuidAssignments(context.getGuidAssignments()); ret.setGuidAssignments(context.getGuidAssignments());
...@@ -164,8 +164,21 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -164,8 +164,21 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
@Override @Override
@GraphTransaction @GraphTransaction
public EntityMutationResponse updateByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes, public EntityMutationResponse updateByUniqueAttributes(AtlasEntityType entityType, Map<String, Object> uniqAttributes,
AtlasEntity entity) throws AtlasBaseException { AtlasEntity updatedEntity) throws AtlasBaseException {
throw new AtlasBaseException(AtlasErrorCode.INTERNAL_ERROR, "updateByUniqueAttributes() not implemented yet");
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 @GraphTransaction
...@@ -256,7 +269,7 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -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); EntityGraphDiscovery graphDiscoverer = new AtlasEntityGraphDiscoveryV1(typeRegistry, entityStream);
EntityGraphDiscoveryContext discoveryContext = graphDiscoverer.discoverEntities(); EntityGraphDiscoveryContext discoveryContext = graphDiscoverer.discoverEntities();
EntityMutationContext context = new EntityMutationContext(discoveryContext); EntityMutationContext context = new EntityMutationContext(discoveryContext);
...@@ -265,9 +278,16 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -265,9 +278,16 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
AtlasVertex vertex = discoveryContext.getResolvedEntityVertex(guid); AtlasVertex vertex = discoveryContext.getResolvedEntityVertex(guid);
AtlasEntity entity = entityStream.getByGuid(guid); AtlasEntity entity = entityStream.getByGuid(guid);
if (vertex != null) { if (entity != null) {
// entity would be null if guid is not in the stream but referenced by an entity in the stream
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 (!isPartialUpdate) {
graphDiscoverer.validateAndNormalize(entity);
} else {
graphDiscoverer.validateAndNormalizeForUpdate(entity);
}
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName()); AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
String guidVertex = AtlasGraphUtilsV1.getIdFromVertex(vertex); String guidVertex = AtlasGraphUtilsV1.getIdFromVertex(vertex);
...@@ -277,21 +297,22 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore { ...@@ -277,21 +297,22 @@ public class AtlasEntityStoreV1 implements AtlasEntityStore {
} }
context.addUpdated(guid, entity, entityType, vertex); context.addUpdated(guid, entity, entityType, vertex);
} } else {
} else { graphDiscoverer.validateAndNormalize(entity);
AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
//Create vertices which do not exist in the repository AtlasEntityType entityType = typeRegistry.getEntityTypeByName(entity.getTypeName());
vertex = entityGraphMapper.createVertex(entity);
discoveryContext.addResolvedGuid(guid, vertex); //Create vertices which do not exist in the repository
vertex = entityGraphMapper.createVertex(entity);
String generatedGuid = AtlasGraphUtilsV1.getIdFromVertex(vertex); discoveryContext.addResolvedGuid(guid, vertex);
entity.setGuid(generatedGuid); String generatedGuid = AtlasGraphUtilsV1.getIdFromVertex(vertex);
context.addCreated(guid, entity, entityType, vertex); entity.setGuid(generatedGuid);
context.addCreated(guid, entity, entityType, vertex);
}
} }
} }
......
...@@ -63,6 +63,7 @@ import java.util.Set; ...@@ -63,6 +63,7 @@ import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.CREATE; 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.UPDATE;
import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.DELETE; import static org.apache.atlas.model.instance.EntityMutations.EntityOperation.DELETE;
...@@ -103,7 +104,7 @@ public class EntityGraphMapper { ...@@ -103,7 +104,7 @@ public class EntityGraphMapper {
return ret; return ret;
} }
public EntityMutationResponse mapAttributes(EntityMutationContext context) throws AtlasBaseException { public EntityMutationResponse mapAttributes(EntityMutationContext context, boolean isPartialUpdate) throws AtlasBaseException {
EntityMutationResponse resp = new EntityMutationResponse(); EntityMutationResponse resp = new EntityMutationResponse();
Collection<AtlasEntity> createdEntities = context.getCreatedEntities(); Collection<AtlasEntity> createdEntities = context.getCreatedEntities();
...@@ -129,7 +130,12 @@ public class EntityGraphMapper { ...@@ -129,7 +130,12 @@ public class EntityGraphMapper {
mapAttributes(updatedEntity, vertex, UPDATE, context); mapAttributes(updatedEntity, vertex, UPDATE, context);
resp.addEntity(UPDATE, constructHeader(updatedEntity, entityType, vertex)); if (isPartialUpdate) {
resp.addEntity(PARTIAL_UPDATE, constructHeader(updatedEntity, entityType, vertex));
} else {
resp.addEntity(UPDATE, constructHeader(updatedEntity, entityType, vertex));
}
} }
} }
......
...@@ -163,7 +163,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -163,7 +163,7 @@ public abstract class AtlasDeleteHandlerV1Test {
public void testDeleteAndCreate() throws Exception { public void testDeleteAndCreate() throws Exception {
init(); init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity)); EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
init(); init();
//delete entity should mark it as deleted //delete entity should mark it as deleted
...@@ -182,7 +182,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -182,7 +182,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init(); init();
//Create the same entity again, should create new entity //Create the same entity again, should create new entity
AtlasEntity newDBEntity = TestUtilsV2.createDBEntity((String) dbEntity.getAttribute(NAME)); 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()); assertNotEquals(newCreationResponse.getFirstEntityCreated().getGuid(), response.getFirstEntityCreated().getGuid());
//TODO - Enable after GET is ready //TODO - Enable after GET is ready
...@@ -197,7 +197,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -197,7 +197,7 @@ public abstract class AtlasDeleteHandlerV1Test {
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); final AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
init(); init();
EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity)); EntityMutationResponse dbCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(dbEntity), false);
final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity); final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
final AtlasEntity columnEntity = TestUtilsV2.createColumnEntity(tableEntity); final AtlasEntity columnEntity = TestUtilsV2.createColumnEntity(tableEntity);
...@@ -207,7 +207,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -207,7 +207,7 @@ public abstract class AtlasDeleteHandlerV1Test {
input.addReferredEntity(columnEntity); input.addReferredEntity(columnEntity);
init(); 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 columnCreated = tblCreationResponse.getFirstCreatedEntityByTypeName(COLUMN_TYPE);
final AtlasEntityHeader tableCreated = tblCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE); final AtlasEntityHeader tableCreated = tblCreationResponse.getFirstCreatedEntityByTypeName(TABLE_TYPE);
...@@ -227,7 +227,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -227,7 +227,7 @@ public abstract class AtlasDeleteHandlerV1Test {
//Deleting table should update process //Deleting table should update process
AtlasEntity process = TestUtilsV2.createProcessEntity(null, Arrays.asList(tableCreated.getAtlasObjectId())); AtlasEntity process = TestUtilsV2.createProcessEntity(null, Arrays.asList(tableCreated.getAtlasObjectId()));
init(); init();
final EntityMutationResponse processCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(process)); final EntityMutationResponse processCreationResponse = entityStore.createOrUpdate(new AtlasEntityStream(process), false);
init(); init();
entityStore.deleteById(tableCreated.getGuid()); entityStore.deleteById(tableCreated.getGuid());
...@@ -242,7 +242,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -242,7 +242,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Create a table entity, with 3 composite column entities // Create a table entity, with 3 composite column entities
init(); init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); 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); final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity); AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
...@@ -258,7 +258,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -258,7 +258,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init(); 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 column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME)); final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
...@@ -296,7 +296,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -296,7 +296,7 @@ public abstract class AtlasDeleteHandlerV1Test {
entitiesInfo1.addReferredEntity(columnEntity3New); entitiesInfo1.addReferredEntity(columnEntity3New);
init(); init();
deletionResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo1)); deletionResponse = entityStore.createOrUpdate(new AtlasEntityStream(entitiesInfo1), false);
//TODO - enable after fixing unique atribute resolver //TODO - enable after fixing unique atribute resolver
assertEquals(deletionResponse.getDeletedEntities().size(), 1); assertEquals(deletionResponse.getDeletedEntities().size(), 1);
...@@ -347,7 +347,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -347,7 +347,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init(); init();
RequestContextV1.clear(); 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 deptCreated = hrDeptCreationResponse.getFirstUpdatedEntityByTypeName(DEPARTMENT_TYPE);
final AtlasEntityHeader maxEmployeeCreated = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max"); final AtlasEntityHeader maxEmployeeCreated = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max");
final AtlasEntityHeader johnEmployeeCreated = hrDeptCreationResponse.getUpdatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "John"); final AtlasEntityHeader johnEmployeeCreated = hrDeptCreationResponse.getUpdatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "John");
...@@ -372,7 +372,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -372,7 +372,7 @@ public abstract class AtlasDeleteHandlerV1Test {
maxEmployee.setAttribute("manager", janeEmployeeCreated.getAtlasObjectId()); maxEmployee.setAttribute("manager", janeEmployeeCreated.getAtlasObjectId());
init(); init();
EntityMutationResponse entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee)); EntityMutationResponse entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee), false);
assertEquals(entityResult.getUpdatedEntities().size(), 1); assertEquals(entityResult.getUpdatedEntities().size(), 1);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid)); assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
...@@ -391,7 +391,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -391,7 +391,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Update max's mentor reference to jane. // Update max's mentor reference to jane.
maxEmployee.setAttribute("mentor", janeEmployeeCreated.getAtlasObjectId()); maxEmployee.setAttribute("mentor", janeEmployeeCreated.getAtlasObjectId());
init(); init();
entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee)); entityResult = entityStore.createOrUpdate(new AtlasEntityStream(maxEmployee), false);
assertEquals(entityResult.getUpdatedEntities().size(), 1); assertEquals(entityResult.getUpdatedEntities().size(), 1);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid)); assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
...@@ -411,7 +411,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -411,7 +411,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init(); init();
maxEmployee.setAttribute("manager", juliusEmployeeCreated.getAtlasObjectId()); 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 //TODO ATLAS-499 should have updated julius' subordinates
assertEquals(entityResult.getUpdatedEntities().size(), 2); assertEquals(entityResult.getUpdatedEntities().size(), 2);
assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid)); assertTrue(extractGuids(entityResult.getUpdatedEntities()).contains(maxGuid));
...@@ -464,7 +464,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -464,7 +464,7 @@ public abstract class AtlasDeleteHandlerV1Test {
public void testDisconnectBidirectionalReferences() throws Exception { public void testDisconnectBidirectionalReferences() throws Exception {
AtlasEntity.AtlasEntitiesWithExtInfo hrDept = TestUtilsV2.createDeptEg2(); AtlasEntity.AtlasEntitiesWithExtInfo hrDept = TestUtilsV2.createDeptEg2();
init(); 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 deptCreated = hrDeptCreationResponse.getFirstCreatedEntityByTypeName(DEPARTMENT_TYPE);
final AtlasEntityHeader maxEmployee = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max"); final AtlasEntityHeader maxEmployee = hrDeptCreationResponse.getCreatedEntityByTypeNameAndAttribute(TestUtilsV2.EMPLOYEE_TYPE, NAME, "Max");
...@@ -647,7 +647,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -647,7 +647,7 @@ public abstract class AtlasDeleteHandlerV1Test {
AtlasEntityStream entityStream = new AtlasEntityStream(structCreationObj); AtlasEntityStream entityStream = new AtlasEntityStream(structCreationObj);
EntityMutationResponse response = entityStore.createOrUpdate(entityStream); EntityMutationResponse response = entityStore.createOrUpdate(entityStream, false);
Assert.assertEquals(response.getCreatedEntities().size(), 3); Assert.assertEquals(response.getCreatedEntities().size(), 3);
final List<String> structTarget = metadataService.getEntityList("StructTarget"); final List<String> structTarget = metadataService.getEntityList("StructTarget");
...@@ -726,7 +726,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -726,7 +726,7 @@ public abstract class AtlasDeleteHandlerV1Test {
// Create a table entity, with 3 composite column entities // Create a table entity, with 3 composite column entities
init(); init();
final AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); 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); final AtlasEntity tableEntity = TestUtilsV2.createTableEntity(dbEntity);
AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity); AtlasEntity.AtlasEntitiesWithExtInfo entitiesInfo = new AtlasEntity.AtlasEntitiesWithExtInfo(tableEntity);
...@@ -742,7 +742,7 @@ public abstract class AtlasDeleteHandlerV1Test { ...@@ -742,7 +742,7 @@ public abstract class AtlasDeleteHandlerV1Test {
init(); 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 column1Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity1.getAttribute(NAME));
final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME)); final AtlasEntityHeader column2Created = tblCreationResponse.getCreatedEntityByTypeNameAndAttribute(COLUMN_TYPE, NAME, (String) columnEntity2.getAttribute(NAME));
......
...@@ -133,7 +133,7 @@ public class EntityREST { ...@@ -133,7 +133,7 @@ public class EntityREST {
@Consumes(Servlets.JSON_MEDIA_TYPE) @Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
public EntityMutationResponse createOrUpdate(AtlasEntityWithExtInfo entity) throws AtlasBaseException { 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 { ...@@ -164,29 +164,19 @@ public class EntityREST {
* an entity which is identified by its type and unique attribute eg: Referenceable.qualifiedName. * an entity which is identified by its type and unique attribute eg: Referenceable.qualifiedName.
* Null updates are not possible * Null updates are not possible
*******/ *******/
@Deprecated
@PUT @PUT
@Consumes(Servlets.JSON_MEDIA_TYPE) @Consumes(Servlets.JSON_MEDIA_TYPE)
@Produces(Servlets.JSON_MEDIA_TYPE) @Produces(Servlets.JSON_MEDIA_TYPE)
@Path("/uniqueAttribute/type/{typeName}") @Path("/uniqueAttribute/type/{typeName}")
public EntityMutationResponse partialUpdateByUniqueAttribute(@PathParam("typeName") String typeName, public EntityMutationResponse partialUpdateByUniqueAttributes(@PathParam("typeName") String typeName,
@Context HttpServletRequest servletRequest, @Context HttpServletRequest servletRequest,
AtlasEntity entity) throws Exception { AtlasEntity entity) throws Exception {
AtlasEntityType entityType = ensureEntityType(typeName); AtlasEntityType entityType = ensureEntityType(typeName);
Map<String, Object> attributes = getAttributes(servletRequest); Map<String, Object> uniqueAttributes = getAttributes(servletRequest);
validateUniqueAttribute(entityType, attributes);
// legacy API supports only one unique attribute validateUniqueAttribute(entityType, uniqueAttributes);
String attribute = attributes.keySet().toArray(new String[1])[0];
String value = (String)attributes.get(attribute);
AtlasFormatConverter.ConverterContext ctx = new AtlasFormatConverter.ConverterContext(); return entitiesStore.updateByUniqueAttributes(entityType, uniqueAttributes, entity);
ctx.addEntity(entity);
Referenceable ref = restAdapters.getReferenceable(entity, ctx);
CreateUpdateEntitiesResult result = metadataService.updateEntityByUniqueAttribute(typeName, attribute, value, ref);
return toEntityMutationResponse(result);
} }
@Deprecated @Deprecated
...@@ -239,7 +229,7 @@ public class EntityREST { ...@@ -239,7 +229,7 @@ public class EntityREST {
EntityStream entityStream = new AtlasEntityStream(entities); EntityStream entityStream = new AtlasEntityStream(entities);
return entitiesStore.createOrUpdate(entityStream); return entitiesStore.createOrUpdate(entityStream, false);
} }
/******* /*******
......
...@@ -153,6 +153,37 @@ public class TestEntityREST { ...@@ -153,6 +153,37 @@ public class TestEntityREST {
} }
@Test @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 { public void testUpdateGetDeleteEntityByUniqueAttribute() throws Exception {
AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); AtlasEntity dbEntity = TestUtilsV2.createDBEntity();
EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity)); EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntitiesWithExtInfo(dbEntity));
...@@ -165,8 +196,9 @@ public class TestEntityREST { ...@@ -165,8 +196,9 @@ public class TestEntityREST {
dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName); dbEntity.setAttribute(TestUtilsV2.NAME, updatedDBName);
response = entityREST.partialUpdateByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity); response = entityREST.partialUpdateByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, prevDBName), dbEntity);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.UPDATE).get(0).getGuid(), dbGuid);
Assert.assertEquals(response.getEntitiesByOperation(EntityMutations.EntityOperation.PARTIAL_UPDATE).get(0).getGuid(), dbGuid);
//Get By unique attribute //Get By unique attribute
AtlasEntityWithExtInfo entity = entityREST.getByUniqueAttributes(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, updatedDBName)); 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