You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ma...@apache.org on 2017/01/20 01:59:58 UTC
[3/3] incubator-atlas git commit: ATLAS-1467: instance
create/full-Update implementation
ATLAS-1467: instance create/full-Update implementation
Signed-off-by: Madhan Neethiraj <ma...@apache.org>
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/2f1cb57a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/2f1cb57a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/2f1cb57a
Branch: refs/heads/master
Commit: 2f1cb57a757e15c97a2b1437e282be48c553d4e8
Parents: 511c886
Author: Suma Shivaprasad <su...@gmail.com>
Authored: Thu Jan 19 17:47:00 2017 -0800
Committer: Madhan Neethiraj <ma...@apache.org>
Committed: Thu Jan 19 17:51:04 2017 -0800
----------------------------------------------------------------------
.../java/org/apache/atlas/AtlasErrorCode.java | 7 +-
.../atlas/model/instance/AtlasEntity.java | 14 +-
.../atlas/model/instance/AtlasEntityHeader.java | 11 +-
.../atlas/model/instance/EntityMutations.java | 3 +-
.../atlas/model/typedef/AtlasStructDef.java | 5 +-
.../atlas/type/AtlasClassificationType.java | 63 +--
.../org/apache/atlas/type/AtlasEntityType.java | 114 ++--
.../org/apache/atlas/type/AtlasStructType.java | 139 ++++-
.../test/java/org/apache/atlas/TestUtilsV2.java | 74 ++-
.../atlas/type/TestAtlasTypeRegistry.java | 10 +-
release-log.txt | 4 +
.../apache/atlas/RepositoryMetadataModule.java | 26 +-
.../atlas/discovery/EntityDiscoveryService.java | 2 +-
.../atlas/discovery/EntityLineageService.java | 2 +-
.../atlas/repository/graph/GraphHelper.java | 2 +-
.../store/graph/AtlasEntityStore.java | 8 +-
.../store/graph/EntityGraphDiscovery.java | 39 ++
.../graph/EntityGraphDiscoveryContext.java | 170 ++++++
.../repository/store/graph/EntityResolver.java | 30 ++
.../store/graph/v1/ArrayVertexMapper.java | 179 ++++++
.../graph/v1/AtlasEntityGraphDiscoveryV1.java | 244 +++++++++
.../store/graph/v1/AtlasEntityStoreV1.java | 139 ++++-
.../store/graph/v1/AtlasEnumDefStoreV1.java | 12 +-
.../store/graph/v1/AtlasGraphUtilsV1.java | 82 ++-
.../store/graph/v1/AtlasStructDefStoreV1.java | 18 +-
.../store/graph/v1/DeleteHandlerV1.java | 539 +++++++++++++++++++
.../store/graph/v1/EntityGraphMapper.java | 185 +++++++
.../store/graph/v1/EntityMutationContext.java | 124 +++++
.../store/graph/v1/GraphMutationContext.java | 195 +++++++
.../store/graph/v1/HardDeleteHandlerV1.java | 43 ++
.../store/graph/v1/IDBasedEntityResolver.java | 118 ++++
.../store/graph/v1/InstanceGraphMapper.java | 39 ++
.../store/graph/v1/MapVertexMapper.java | 200 +++++++
.../store/graph/v1/SoftDeleteHandlerV1.java | 72 +++
.../store/graph/v1/StructVertexMapper.java | 203 +++++++
.../graph/v1/UniqAttrBasedEntityResolver.java | 136 +++++
.../util/AtlasRepositoryConfiguration.java | 12 +
.../atlas/lineage/EntityLineageServiceTest.java | 12 +-
.../store/graph/AtlasTypeDefGraphStoreTest.java | 3 +-
.../store/graph/v1/AtlasEntityStoreV1Test.java | 236 ++++++++
.../java/org/apache/atlas/RequestContextV1.java | 122 +++++
.../adapters/AtlasEntityFormatConverter.java | 4 +-
.../web/adapters/AtlasInstanceRestAdapters.java | 4 +-
.../adapters/AtlasStructFormatConverter.java | 32 +-
.../org/apache/atlas/web/rest/EntitiesREST.java | 2 +-
.../org/apache/atlas/web/util/LineageUtils.java | 2 +-
.../atlas/web/adapters/TestEntitiesREST.java | 4 +-
.../atlas/web/adapters/TestEntityREST.java | 4 +-
.../atlas/web/resources/BaseResourceIT.java | 6 +-
.../EntityDiscoveryJerseyResourceIT.java | 4 +-
.../web/resources/EntityV2JerseyResourceIT.java | 22 +-
51 files changed, 3450 insertions(+), 270 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
index a6438ed..f0aae0c 100644
--- a/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
+++ b/intg/src/main/java/org/apache/atlas/AtlasErrorCode.java
@@ -62,6 +62,7 @@ public enum AtlasErrorCode {
INSTANCE_LINEAGE_INVALID_PARAMS(404, "ATLAS4046E", "Invalid lineage query parameters passed {0}: {1}"),
INSTANCE_LINEAGE_QUERY_FAILED(404, "ATLAS4047E", "Instance lineage query failed {0}"),
DISCOVERY_QUERY_FAILED(404, "ATLAS4048E", "Discovery query failed {0}"),
+ INSTANCE_CRUD_INVALID_PARAMS(404, "ATLAS4049E", "Invalid instance creation/updation parameters passed : {0}"),
// All data conflict errors go here
@@ -72,7 +73,11 @@ public enum AtlasErrorCode {
// All internal errors go here
INTERNAL_ERROR(500, "ATLAS5001E", "Internal server error {0}"),
INDEX_CREATION_FAILED(500, "ATLAS5002E", "Index creation failed for {0}"),
- INDEX_ROLLBACK_FAILED(500, "ATLAS5003E", "Index rollback failed for {0}");
+ INDEX_ROLLBACK_FAILED(500, "ATLAS5003E", "Index rollback failed for {0}"),
+
+ INSTANCE_BY_UNIQUE_ATTRIBUTE_NOT_FOUND(400, "ATLAS40018E", "Instance {0} with unique attribute {1} does not exist"),
+
+ UNKNOWN_ATTRIBUTE(400, "ATLAS40019E", "Attribute {0} not found for type {1}");
private String errorCode;
private String errorMessage;
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntity.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntity.java b/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntity.java
index 2ad0f76..9494fe4 100644
--- a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntity.java
+++ b/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntity.java
@@ -55,15 +55,15 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
/**
* Status of the entity - can be active or deleted. Deleted entities are not removed from Atlas store.
*/
- public enum Status { STATUS_ACTIVE, STATUS_DELETED }
+ public enum Status { ACTIVE, DELETED }
private String guid = null;
- private Status status = Status.STATUS_ACTIVE;
+ private Status status = Status.ACTIVE;
private String createdBy = null;
private String updatedBy = null;
private Date createTime = null;
private Date updateTime = null;
- private Long version = null;
+ private Long version = new Long(0);
@JsonIgnore
private static AtomicLong s_nextId = new AtomicLong(System.nanoTime());
@@ -89,7 +89,6 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
setUpdatedBy(null);
setCreateTime(null);
setUpdateTime(null);
- setVersion(null);
}
public AtlasEntity(AtlasEntity other) {
@@ -247,7 +246,7 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
@JsonIgnore
public boolean isUnassigned() {
- return guid != null && guid.length() > 0 && guid.charAt(0) == '-';
+ return isUnAssigned(guid);
}
@JsonIgnore
@@ -266,6 +265,11 @@ public class AtlasEntity extends AtlasStruct implements Serializable {
return true;
}
+ @JsonIgnore
+ public static boolean isUnAssigned(String guid) {
+ return guid != null && guid.length() > 0 && guid.charAt(0) == '-';
+ }
+
private String nextInternalId() {
return "-" + Long.toString(s_nextId.getAndIncrement());
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntityHeader.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntityHeader.java b/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntityHeader.java
index e7b70aa..5797a69 100644
--- a/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntityHeader.java
+++ b/intg/src/main/java/org/apache/atlas/model/instance/AtlasEntityHeader.java
@@ -18,6 +18,7 @@
package org.apache.atlas.model.instance;
import java.io.Serializable;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -49,7 +50,7 @@ public class AtlasEntityHeader extends AtlasStruct implements Serializable {
private static final long serialVersionUID = 1L;
private String guid = null;
- private AtlasEntity.Status status = AtlasEntity.Status.STATUS_ACTIVE;
+ private AtlasEntity.Status status = AtlasEntity.Status.ACTIVE;
private String displayText = null;
public AtlasEntityHeader() {
@@ -66,11 +67,15 @@ public class AtlasEntityHeader extends AtlasStruct implements Serializable {
public AtlasEntityHeader(String typeName, Map<String, Object> attributes) {
super(typeName, attributes);
+ }
+
- setGuid(null);
- setStatus(null);
+ public AtlasEntityHeader(String typeName, String guid, Map<String, Object> attributes) {
+ super(typeName, attributes);
+ setGuid(guid);
}
+
public AtlasEntityHeader(AtlasEntityHeader other) {
super(other);
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/model/instance/EntityMutations.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/instance/EntityMutations.java b/intg/src/main/java/org/apache/atlas/model/instance/EntityMutations.java
index 3501c90..74e3c57 100644
--- a/intg/src/main/java/org/apache/atlas/model/instance/EntityMutations.java
+++ b/intg/src/main/java/org/apache/atlas/model/instance/EntityMutations.java
@@ -43,7 +43,8 @@ public class EntityMutations implements Serializable {
private List<EntityMutation> entityMutations = new ArrayList<>();
public enum EntityOperation {
- CREATE_OR_UPDATE,
+ CREATE,
+ UPDATE,
PARTIAL_UPDATE,
DELETE,
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java
index aee26ef..2c00f54 100644
--- a/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java
+++ b/intg/src/main/java/org/apache/atlas/model/typedef/AtlasStructDef.java
@@ -19,6 +19,7 @@ package org.apache.atlas.model.typedef;
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -183,7 +184,7 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
return findAttribute(attributeDefs, attrName) != null;
}
- private static AtlasAttributeDef findAttribute(List<AtlasAttributeDef> attributeDefs, String attrName) {
+ public static AtlasAttributeDef findAttribute(Collection<AtlasAttributeDef> attributeDefs, String attrName) {
AtlasAttributeDef ret = null;
if (CollectionUtils.isNotEmpty(attributeDefs)) {
@@ -451,6 +452,8 @@ public class AtlasStructDef extends AtlasBaseTypeDef implements Serializable {
}
}
+
+
/**
* class that captures details of a constraint.
*/
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
index 8772720..7d89848 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasClassificationType.java
@@ -46,8 +46,6 @@ public class AtlasClassificationType extends AtlasStructType {
private List<AtlasClassificationType> superTypes = Collections.emptyList();
private Set<String> allSuperTypes = Collections.emptySet();
- private Map<String, AtlasAttributeDef> allAttributeDefs = Collections.emptyMap();
- private Map<String, AtlasType> allAttributeTypes = new HashMap<>();
public AtlasClassificationType(AtlasClassificationDef classificationDef) {
super(classificationDef);
@@ -72,7 +70,7 @@ public class AtlasClassificationType extends AtlasStructType {
List<AtlasClassificationType> s = new ArrayList<>();
Set<String> allS = new HashSet<>();
- Map<String, AtlasAttributeDef> allA = new HashMap<>();
+ Map<String, AtlasAttribute> allA = new HashMap<>();
getTypeHierarchyInfo(typeRegistry, allS, allA);
@@ -89,8 +87,7 @@ public class AtlasClassificationType extends AtlasStructType {
this.superTypes = Collections.unmodifiableList(s);
this.allSuperTypes = Collections.unmodifiableSet(allS);
- this.allAttributeDefs = Collections.unmodifiableMap(allA);
- this.allAttributeTypes = new HashMap<>(); // this will be rebuilt on calls to getAttributeType()
+ this.allAttributes = Collections.unmodifiableMap(allA);
}
public Set<String> getSuperTypes() {
@@ -99,51 +96,6 @@ public class AtlasClassificationType extends AtlasStructType {
public Set<String> getAllSuperTypes() { return allSuperTypes; }
- public Map<String, AtlasAttributeDef> getAllAttributeDefs() { return allAttributeDefs; }
-
- @Override
- public AtlasType getAttributeType(String attributeName) {
- AtlasType ret = allAttributeTypes.get(attributeName);
-
- if (ret == null) {
- ret = super.getAttributeType(attributeName);
-
- if (ret == null) {
- for (AtlasClassificationType superType : superTypes) {
- ret = superType.getAttributeType(attributeName);
-
- if (ret != null) {
- break;
- }
- }
- }
-
- if (ret != null) {
- allAttributeTypes.put(attributeName, ret);
- }
- }
-
- return ret;
- }
-
-
- @Override
- public AtlasAttributeDef getAttributeDef(String attributeName) {
- AtlasAttributeDef ret = super.getAttributeDef(attributeName);
-
- if (ret == null) {
- for (AtlasClassificationType superType : superTypes) {
- ret = superType.getAttributeDef(attributeName);
-
- if (ret != null) {
- break;
- }
- }
- }
-
- return ret;
- }
-
public boolean isSuperTypeOf(AtlasClassificationType classificationType) {
return classificationType != null && classificationType.getAllSuperTypes().contains(this.getTypeName());
}
@@ -243,10 +195,10 @@ public class AtlasClassificationType extends AtlasStructType {
private void getTypeHierarchyInfo(AtlasTypeRegistry typeRegistry,
Set<String> allSuperTypeNames,
- Map<String, AtlasAttributeDef> allAttributeDefs) throws AtlasBaseException {
+ Map<String, AtlasAttribute> allAttributes) throws AtlasBaseException {
List<String> visitedTypes = new ArrayList<>();
- collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributeDefs, visitedTypes);
+ collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributes, visitedTypes);
}
/*
@@ -255,7 +207,7 @@ public class AtlasClassificationType extends AtlasStructType {
*/
private void collectTypeHierarchyInfo(AtlasTypeRegistry typeRegistry,
Set<String> allSuperTypeNames,
- Map<String, AtlasAttributeDef> allAttributeDefs,
+ Map<String, AtlasAttribute> allAttributes,
List<String> visitedTypes) throws AtlasBaseException {
if (visitedTypes.contains(classificationDef.getName())) {
throw new AtlasBaseException(AtlasErrorCode.CIRCULAR_REFERENCE, classificationDef.getName(),
@@ -270,7 +222,7 @@ public class AtlasClassificationType extends AtlasStructType {
if (type instanceof AtlasClassificationType) {
AtlasClassificationType superType = (AtlasClassificationType) type;
- superType.collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributeDefs, visitedTypes);
+ superType.collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributes, visitedTypes);
}
}
visitedTypes.remove(classificationDef.getName());
@@ -280,7 +232,8 @@ public class AtlasClassificationType extends AtlasStructType {
if (CollectionUtils.isNotEmpty(classificationDef.getAttributeDefs())) {
for (AtlasAttributeDef attributeDef : classificationDef.getAttributeDefs()) {
- allAttributeDefs.put(attributeDef.getName(), attributeDef);
+ AtlasType type = typeRegistry.getType(attributeDef.getTypeName());
+ allAttributes.put(attributeDef.getName(), new AtlasAttribute(this, classificationDef, attributeDef, type));
}
}
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
index 3625f72..caadecc 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasEntityType.java
@@ -21,9 +21,11 @@ package org.apache.atlas.type;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.typedef.AtlasEntityDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -45,8 +47,6 @@ public class AtlasEntityType extends AtlasStructType {
private List<AtlasEntityType> superTypes = Collections.emptyList();
private Set<String> allSuperTypes = Collections.emptySet();
- private Map<String, AtlasAttributeDef> allAttributeDefs = Collections.emptyMap();
- private Map<String, AtlasType> allAttributeTypes = new HashMap<>();
public AtlasEntityType(AtlasEntityDef entityDef) {
super(entityDef);
@@ -70,7 +70,7 @@ public class AtlasEntityType extends AtlasStructType {
List<AtlasEntityType> s = new ArrayList<>();
Set<String> allS = new HashSet<>();
- Map<String, AtlasAttributeDef> allA = new HashMap<>();
+ Map<String, AtlasAttribute> allA = new HashMap<>();
getTypeHierarchyInfo(typeRegistry, allS, allA);
@@ -86,8 +86,7 @@ public class AtlasEntityType extends AtlasStructType {
this.superTypes = Collections.unmodifiableList(s);
this.allSuperTypes = Collections.unmodifiableSet(allS);
- this.allAttributeDefs = Collections.unmodifiableMap(allA);
- this.allAttributeTypes = new HashMap<>(); // this will be rebuilt on calls to getAttributeType()
+ this.allAttributes = Collections.unmodifiableMap(allA);
}
public Set<String> getSuperTypes() {
@@ -98,50 +97,6 @@ public class AtlasEntityType extends AtlasStructType {
return allSuperTypes;
}
- public Map<String, AtlasAttributeDef> getAllAttributeDefs() { return allAttributeDefs; }
-
- @Override
- public AtlasType getAttributeType(String attributeName) {
- AtlasType ret = allAttributeTypes.get(attributeName);
-
- if (ret == null) {
- ret = super.getAttributeType(attributeName);
-
- if (ret == null) {
- for (AtlasEntityType superType : superTypes) {
- ret = superType.getAttributeType(attributeName);
-
- if (ret != null) {
- break;
- }
- }
- }
-
- if (ret != null) {
- allAttributeTypes.put(attributeName, ret);
- }
- }
-
- return ret;
- }
-
- @Override
- public AtlasAttributeDef getAttributeDef(String attributeName) {
- AtlasAttributeDef ret = super.getAttributeDef(attributeName);
-
- if (ret == null) {
- for (AtlasEntityType superType : superTypes) {
- ret = superType.getAttributeDef(attributeName);
-
- if (ret != null) {
- break;
- }
- }
- }
-
- return ret;
- }
-
public boolean isSuperTypeOf(AtlasEntityType entityType) {
return entityType != null && entityType.getAllSuperTypes().contains(this.getTypeName());
}
@@ -150,6 +105,10 @@ public class AtlasEntityType extends AtlasStructType {
return entityType != null && allSuperTypes.contains(entityType.getTypeName());
}
+ public boolean isSubTypeOf(String entityTypeName) {
+ return StringUtils.isNotEmpty(entityTypeName) && allSuperTypes.contains(entityTypeName);
+ }
+
@Override
public AtlasEntity createDefaultValue() {
AtlasEntity ret = new AtlasEntity(entityDef.getName());
@@ -162,13 +121,17 @@ public class AtlasEntityType extends AtlasStructType {
@Override
public boolean isValidValue(Object obj) {
if (obj != null) {
- for (AtlasEntityType superType : superTypes) {
- if (!superType.isValidValue(obj)) {
- return false;
+ if (obj instanceof AtlasObjectId) {
+ AtlasObjectId objId = (AtlasObjectId ) obj;
+ return validateAtlasObjectId(objId);
+ } else {
+ for (AtlasEntityType superType : superTypes) {
+ if (!superType.isValidValue(obj)) {
+ return false;
+ }
}
+ return super.isValidValue(obj);
}
-
- return super.isValidValue(obj);
}
return true;
@@ -186,6 +149,8 @@ public class AtlasEntityType extends AtlasStructType {
} else if (obj instanceof Map) {
normalizeAttributeValues((Map) obj);
ret = obj;
+ } else if (obj instanceof AtlasObjectId) {
+ ret = obj;
}
}
}
@@ -194,10 +159,20 @@ public class AtlasEntityType extends AtlasStructType {
}
@Override
+ public AtlasAttribute getAttribute(String attributeName) {
+ return findAttribute(allAttributes.values(), attributeName);
+ }
+
+ @Override
public boolean validateValue(Object obj, String objName, List<String> messages) {
boolean ret = true;
if (obj != null) {
+ if (obj instanceof AtlasObjectId) {
+ AtlasObjectId objId = (AtlasObjectId ) obj;
+ return validateAtlasObjectId(objId);
+ }
+
for (AtlasEntityType superType : superTypes) {
ret = superType.validateValue(obj, objName, messages) && ret;
}
@@ -241,10 +216,10 @@ public class AtlasEntityType extends AtlasStructType {
private void getTypeHierarchyInfo(AtlasTypeRegistry typeRegistry,
Set<String> allSuperTypeNames,
- Map<String, AtlasAttributeDef> allAttributeDefs) throws AtlasBaseException {
+ Map<String, AtlasAttribute> allAttributes) throws AtlasBaseException {
List<String> visitedTypes = new ArrayList<>();
- collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributeDefs, visitedTypes);
+ collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributes, visitedTypes);
}
/*
@@ -253,7 +228,7 @@ public class AtlasEntityType extends AtlasStructType {
*/
private void collectTypeHierarchyInfo(AtlasTypeRegistry typeRegistry,
Set<String> allSuperTypeNames,
- Map<String, AtlasAttributeDef> allAttributeDefs,
+ Map<String, AtlasAttribute> allAttributes,
List<String> visitedTypes) throws AtlasBaseException {
if (visitedTypes.contains(entityDef.getName())) {
throw new AtlasBaseException(AtlasErrorCode.CIRCULAR_REFERENCE, entityDef.getName(),
@@ -267,19 +242,36 @@ public class AtlasEntityType extends AtlasStructType {
if (type instanceof AtlasEntityType) {
AtlasEntityType superType = (AtlasEntityType) type;
-
- superType.collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributeDefs, visitedTypes);
+ superType.collectTypeHierarchyInfo(typeRegistry, allSuperTypeNames, allAttributes, visitedTypes);
}
}
visitedTypes.remove(entityDef.getName());
-
allSuperTypeNames.addAll(entityDef.getSuperTypes());
}
if (CollectionUtils.isNotEmpty(entityDef.getAttributeDefs())) {
for (AtlasAttributeDef attributeDef : entityDef.getAttributeDefs()) {
- allAttributeDefs.put(attributeDef.getName(), attributeDef);
+
+ AtlasType type = typeRegistry.getType(attributeDef.getTypeName());
+ allAttributes.put(attributeDef.getName(), new AtlasAttribute(this, entityDef, attributeDef, type));
+ }
+ }
+ }
+
+ private boolean validateAtlasObjectId(AtlasObjectId objId) {
+ if (StringUtils.isEmpty(objId.getTypeName()) || StringUtils.isEmpty(objId.getGuid())) {
+ return false;
+ } else {
+ String typeName = objId.getTypeName();
+ if (!typeName.equals(getTypeName())) {
+ //TODO - Enable below after enabling subType check
+// if ( !isSuperTypeOf(typeName)) {
+// return false;
+// }
+ return false;
}
}
+ return AtlasEntity.isAssigned(objId.getGuid()) || AtlasEntity.isUnAssigned((objId.getGuid()));
}
+
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
----------------------------------------------------------------------
diff --git a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
index e20af76..4712508 100644
--- a/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
+++ b/intg/src/main/java/org/apache/atlas/type/AtlasStructType.java
@@ -20,6 +20,8 @@ package org.apache.atlas.type;
import org.apache.atlas.AtlasErrorCode;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.model.TypeCategory;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.typedef.AtlasStructDef;
import org.apache.atlas.model.typedef.AtlasStructDef.AtlasAttributeDef;
@@ -30,6 +32,7 @@ import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -49,10 +52,9 @@ public class AtlasStructType extends AtlasType {
private final AtlasStructDef structDef;
- private Map<String, AtlasType> attrTypes = Collections.emptyMap();
private Set<String> foreignKeyAttributes = new HashSet<>();
private Map<String, TypeAttributePair> mappedFromRefAttributes = new HashMap<>();
-
+ protected Map<String, AtlasAttribute> allAttributes = Collections.emptyMap();
public AtlasStructType(AtlasStructDef structDef) {
super(structDef);
@@ -70,9 +72,12 @@ public class AtlasStructType extends AtlasType {
public AtlasStructDef getStructDef() { return structDef; }
- public AtlasType getAttributeType(String attributeName) { return attrTypes.get(attributeName); }
+ public AtlasType getAttributeType(String attributeName) {
+ AtlasAttribute attribute = allAttributes.get(attributeName);
+ return attribute != null ? attribute.getAttributeType() : null;
+ }
- public AtlasAttributeDef getAttributeDef(String attributeName) { return structDef.getAttribute(attributeName); }
+ public AtlasAttributeDef getAttributeDef(String attributeName) { return allAttributes.get(attributeName) != null ? allAttributes.get(attributeName).getAttributeDef() : null; }
public boolean isForeignKeyAttribute(String attributeName) {
return foreignKeyAttributes.contains(attributeName);
@@ -101,10 +106,12 @@ public class AtlasStructType extends AtlasType {
@Override
public void resolveReferences(AtlasTypeRegistry typeRegistry) throws AtlasBaseException {
- Map<String, AtlasType> a = new HashMap<>();
+ Map<String, AtlasAttribute> a = new HashMap<>();
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
+
AtlasType attrType = typeRegistry.getType(attributeDef.getTypeName());
+ AtlasAttribute attribute = new AtlasAttribute(this, structDef, attributeDef, attrType);
resolveConstraints(attributeDef, attrType);
@@ -122,10 +129,10 @@ public class AtlasStructType extends AtlasType {
arrayType.setMaxCount(attributeDef.getValuesMaxCount());
}
- a.put(attributeDef.getName(), attrType);
+ a.put(attributeDef.getName(), attribute);
}
- this.attrTypes = Collections.unmodifiableMap(a);
+ this.allAttributes = Collections.unmodifiableMap(a);
}
@Override
@@ -137,6 +144,29 @@ public class AtlasStructType extends AtlasType {
return ret;
}
+ public Map<String, AtlasAttribute> getAllAttributes() {
+ return allAttributes;
+ }
+
+ public AtlasAttribute getAttribute(String attributeName) {
+ return findAttribute(allAttributes.values(), attributeName);
+ }
+
+ public static AtlasAttribute findAttribute(Collection<AtlasAttribute> attributes, String attrName) {
+ AtlasAttribute ret = null;
+
+ if (CollectionUtils.isNotEmpty(attributes)) {
+ for (AtlasAttribute attribute : attributes) {
+ if (org.apache.hadoop.util.StringUtils.equalsIgnoreCase(attribute.getAttributeDef().getName(), attrName)) {
+ ret = attribute;
+ break;
+ }
+ }
+ }
+
+ return ret;
+ }
+
@Override
public boolean isValidValue(Object obj) {
if (obj != null) {
@@ -157,7 +187,7 @@ public class AtlasStructType extends AtlasType {
}
}
} else {
- return false; // invalid type
+ return false;
}
}
@@ -193,9 +223,11 @@ public class AtlasStructType extends AtlasType {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
String attrName = attributeDef.getName();
- AtlasType dataType = attrTypes.get(attributeDef.getName());
- if (dataType != null) {
+ AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
+
+ if (attribute != null) {
+ AtlasType dataType = attribute.getAttributeType();
Object value = structObj.getAttribute(attrName);
String fieldName = objName + "." + attrName;
@@ -213,9 +245,10 @@ public class AtlasStructType extends AtlasType {
for (AtlasAttributeDef attributeDef : structDef.getAttributeDefs()) {
String attrName = attributeDef.getName();
- AtlasType dataType = attrTypes.get(attributeDef.getName());
+ AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
- if (dataType != null) {
+ if (attribute != null) {
+ AtlasType dataType = attribute.getAttributeType();
Object value = map.get(attrName);
String fieldName = objName + "." + attrName;
@@ -230,7 +263,6 @@ public class AtlasStructType extends AtlasType {
}
} else {
ret = false;
-
messages.add(objName + "=" + obj + ": invalid value for type " + getTypeName());
}
}
@@ -292,9 +324,10 @@ public class AtlasStructType extends AtlasType {
Object ret = null;
if (attributeDef != null) {
- AtlasType dataType = attrTypes.get(attributeDef.getName());
+ AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
- if (dataType != null) {
+ if (attribute != null) {
+ AtlasType dataType = attribute.getAttributeType();
ret = dataType.createDefaultValue();
}
}
@@ -306,12 +339,14 @@ public class AtlasStructType extends AtlasType {
boolean ret = true;
if (value != null) {
- AtlasType attrType = attrTypes.get(attributeDef.getName());
+ AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
- if (attrType != null) {
- if (!attrType.isValidValue(value)) {
- ret = false; // invalid value
- }
+ if (attribute != null) {
+ AtlasType attrType = attribute.getAttributeType();
+
+ if (!attrType.isValidValue(value)) {
+ ret = false; // invalid value
+ }
}
} else if (!attributeDef.getIsOptional()) {
ret = false; // mandatory attribute not present
@@ -321,9 +356,11 @@ public class AtlasStructType extends AtlasType {
}
private Object getNormalizedValue(Object value, AtlasAttributeDef attributeDef) {
- AtlasType attrType = attrTypes.get(attributeDef.getName());
+ AtlasAttribute attribute = allAttributes.get(attributeDef.getName());
+
+ if (attribute != null) {
+ AtlasType attrType = attribute.getAttributeType();
- if (attrType != null) {
if (value == null) {
if (!attributeDef.getIsOptional()) {
return attrType.createDefaultValue();
@@ -419,8 +456,8 @@ public class AtlasStructType extends AtlasType {
String.valueOf(constraintDef.getParams()));
}
- AtlasStructType structType = (AtlasStructType)attribType;
- AtlasAttributeDef refAttrib = structType.getAttributeDef(refAttribName);
+ AtlasStructType structType = (AtlasStructType) attribType;
+ AtlasAttributeDef refAttrib = structType.getStructDef().getAttribute(refAttribName);
if (refAttrib == null) {
throw new AtlasBaseException(AtlasErrorCode.CONSTRAINT_NOT_EXIST,
@@ -447,4 +484,58 @@ public class AtlasStructType extends AtlasType {
this.attributeName = attributeName;
}
}
+
+ public String getQualifiedAttributeName(String attrName) throws AtlasBaseException {
+ if ( allAttributes.containsKey(attrName)) {
+ return allAttributes.get(attrName).getQualifiedName();
+ }
+
+ throw new AtlasBaseException(AtlasErrorCode.UNKNOWN_ATTRIBUTE, attrName, structDef.getName());
+ }
+
+ public static class AtlasAttribute {
+
+ private final AtlasStructType structType;
+ private final AtlasStructDef structDef;
+ private final AtlasType attributeType;
+ private final AtlasAttributeDef attributeDef;
+ private final String qualifiedName;
+
+ public AtlasAttribute(AtlasStructType structType, AtlasStructDef structDef, AtlasAttributeDef attrDef, AtlasType attributeType) {
+ this.structType = structType;
+ this.structDef = structDef;
+ this.attributeDef = attrDef;
+ this.attributeType = attributeType;
+ this.qualifiedName = getQualifiedAttributeName(structDef, attributeDef.getName());
+ }
+
+ public AtlasStructType getStructType() {
+ return structType;
+ }
+
+ public String getQualifiedName() {
+ return qualifiedName;
+ }
+
+ public AtlasStructDef getStructDef() {
+ return structDef;
+ }
+
+ public AtlasType getAttributeType() {
+ return attributeType;
+ }
+
+ public AtlasAttributeDef getAttributeDef() {
+ return attributeDef;
+ }
+
+ public String getQualifiedAttributeName() {
+ return qualifiedName;
+ }
+
+ public static String getQualifiedAttributeName(AtlasStructDef structDef, String attrName) {
+ final String typeName = structDef.getName();
+ return attrName.contains(".") ? attrName : String.format("%s.%s", typeName, attrName);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java
----------------------------------------------------------------------
diff --git a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java
index 53b109c..f9040f3 100755
--- a/intg/src/test/java/org/apache/atlas/TestUtilsV2.java
+++ b/intg/src/test/java/org/apache/atlas/TestUtilsV2.java
@@ -21,6 +21,7 @@ package org.apache.atlas;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
import org.apache.atlas.model.instance.AtlasStruct;
import org.apache.atlas.model.typedef.AtlasClassificationDef;
import org.apache.atlas.model.typedef.AtlasEntityDef;
@@ -80,13 +81,19 @@ public final class TestUtilsV2 {
AtlasEntityDef deptTypeDef =
AtlasTypeUtil.createClassTypeDef(DEPARTMENT_TYPE, "Department"+_description, ImmutableSet.<String>of(),
- AtlasTypeUtil.createRequiredAttrDef("name", "string"),
- new AtlasAttributeDef("employees", String.format("array<%s>", "Person"), true,
+ AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
+ new AtlasAttributeDef("employees", String.format("array<%s>", "Employee"), true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1, false, false,
- Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()));
+ new ArrayList<AtlasStructDef.AtlasConstraintDef>()));
+
+ deptTypeDef.getAttribute("employees").addConstraint(
+ new AtlasStructDef.AtlasConstraintDef(
+ AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_MAPPED_FROM_REF, new HashMap<String, Object>() {{
+ put(AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_REF_ATTRIBUTE, "department");
+ }}));
AtlasEntityDef personTypeDef = AtlasTypeUtil.createClassTypeDef("Person", "Person"+_description, ImmutableSet.<String>of(),
- AtlasTypeUtil.createRequiredAttrDef("name", "string"),
+ AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createOptionalAttrDef("address", "Address"),
AtlasTypeUtil.createOptionalAttrDef("birthday", "date"),
AtlasTypeUtil.createOptionalAttrDef("hasPets", "boolean"),
@@ -103,20 +110,25 @@ public final class TestUtilsV2 {
new AtlasAttributeDef("department", "Department", false,
AtlasAttributeDef.Cardinality.SINGLE, 1, 1,
false, false,
- Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
- new AtlasAttributeDef("manager", "Employee", true,
+ new ArrayList<AtlasStructDef.AtlasConstraintDef>()),
+ new AtlasAttributeDef("manager", "Manager", true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
- new AtlasAttributeDef("mentor", "Employee", true,
+ new AtlasAttributeDef("mentor", EMPLOYEE_TYPE, true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
AtlasTypeUtil.createOptionalAttrDef("shares", "long"),
AtlasTypeUtil.createOptionalAttrDef("salary", "double")
-
);
+ employeeTypeDef.getAttribute("department").addConstraint(
+ new AtlasStructDef.AtlasConstraintDef(
+ AtlasStructDef.AtlasConstraintDef.CONSTRAINT_TYPE_FOREIGN_KEY, new HashMap<String, Object>() {{
+ put(AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_ON_DELETE, AtlasStructDef.AtlasConstraintDef.CONSTRAINT_PARAM_VAL_CASCADE);
+ }}));
+
AtlasEntityDef managerTypeDef = AtlasTypeUtil.createClassTypeDef("Manager", "Manager"+_description, ImmutableSet.of("Employee"),
new AtlasAttributeDef("subordinates", String.format("array<%s>", "Employee"), false, AtlasAttributeDef.Cardinality.SET,
1, 10, false, false,
@@ -149,7 +161,7 @@ public final class TestUtilsV2 {
AtlasEntityDef deptTypeDef =
AtlasTypeUtil.createClassTypeDef(DEPARTMENT_TYPE, "Department"+_description,
ImmutableSet.<String>of(),
- AtlasTypeUtil.createRequiredAttrDef("name", "string"),
+ AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createOptionalAttrDef("dep-code", "string"),
new AtlasAttributeDef("employees", String.format("array<%s>", "Employee"), true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1, false, false,
@@ -157,7 +169,7 @@ public final class TestUtilsV2 {
AtlasEntityDef personTypeDef = AtlasTypeUtil.createClassTypeDef("Person", "Person"+_description,
ImmutableSet.<String>of(),
- AtlasTypeUtil.createRequiredAttrDef("name", "string"),
+ AtlasTypeUtil.createUniqueRequiredAttrDef("name", "string"),
AtlasTypeUtil.createOptionalAttrDef("email", "string"),
AtlasTypeUtil.createOptionalAttrDef("address", "Address"),
AtlasTypeUtil.createOptionalAttrDef("birthday", "date"),
@@ -178,11 +190,11 @@ public final class TestUtilsV2 {
AtlasAttributeDef.Cardinality.SINGLE, 1, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
- new AtlasAttributeDef("manager", "Employee", true,
+ new AtlasAttributeDef("manager", "Manager", true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
- new AtlasAttributeDef("mentor", "Employee", true,
+ new AtlasAttributeDef("mentor", EMPLOYEE_TYPE, true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
@@ -241,7 +253,7 @@ public final class TestUtilsV2 {
AtlasAttributeDef.Cardinality.SINGLE, 1, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
- new AtlasAttributeDef("manager", "Person", true,
+ new AtlasAttributeDef("manager", "Manager", true,
AtlasAttributeDef.Cardinality.SINGLE, 0, 1,
false, false,
Collections.<AtlasStructDef.AtlasConstraintDef>emptyList()),
@@ -269,24 +281,24 @@ public final class TestUtilsV2 {
public static final String DEPARTMENT_TYPE = "Department";
public static final String PERSON_TYPE = "Person";
+ public static final String EMPLOYEE_TYPE = "Employee";
public static AtlasEntity createDeptEg1() {
AtlasEntity hrDept = new AtlasEntity(DEPARTMENT_TYPE);
- AtlasEntity john = new AtlasEntity(PERSON_TYPE);
+ AtlasEntity john = new AtlasEntity(EMPLOYEE_TYPE);
-// AtlasEntity jane = new AtlasEntity("Manager", "SecurityClearance");
AtlasEntity jane = new AtlasEntity("Manager");
AtlasEntity johnAddr = new AtlasEntity("Address");
AtlasEntity janeAddr = new AtlasEntity("Address");
AtlasEntity julius = new AtlasEntity("Manager");
AtlasEntity juliusAddr = new AtlasEntity("Address");
- AtlasEntity max = new AtlasEntity("Person");
+ AtlasEntity max = new AtlasEntity(EMPLOYEE_TYPE);
AtlasEntity maxAddr = new AtlasEntity("Address");
-
+ AtlasObjectId deptId = new AtlasObjectId(hrDept.getTypeName(), hrDept.getGuid());
hrDept.setAttribute("name", "hr");
john.setAttribute("name", "John");
- john.setAttribute("department", hrDept);
+ john.setAttribute("department", deptId);
johnAddr.setAttribute("street", "Stewart Drive");
johnAddr.setAttribute("city", "Sunnyvale");
john.setAttribute("address", johnAddr);
@@ -303,26 +315,32 @@ public final class TestUtilsV2 {
john.setAttribute("approximationOfPi", new BigDecimal("3.141592653589793238462643383279502884197169399375105820974944592307816406286"));
jane.setAttribute("name", "Jane");
- jane.setAttribute("department", hrDept);
+ jane.setAttribute("department", deptId);
janeAddr.setAttribute("street", "Great America Parkway");
janeAddr.setAttribute("city", "Santa Clara");
jane.setAttribute("address", janeAddr);
janeAddr.setAttribute("street", "Great America Parkway");
julius.setAttribute("name", "Julius");
- julius.setAttribute("department", hrDept);
+ julius.setAttribute("department", deptId);
juliusAddr.setAttribute("street", "Madison Ave");
juliusAddr.setAttribute("city", "Newtonville");
julius.setAttribute("address", juliusAddr);
julius.setAttribute("subordinates", ImmutableList.of());
+ AtlasObjectId janeId = new AtlasObjectId(jane.getTypeName(), jane.getGuid());
+
+ //TODO - Change to MANAGER_TYPE for JULIUS
+ AtlasObjectId maxId = new AtlasObjectId(EMPLOYEE_TYPE, max.getGuid());
+ AtlasObjectId juliusId = new AtlasObjectId(EMPLOYEE_TYPE, julius.getGuid());
+
max.setAttribute("name", "Max");
- max.setAttribute("department", hrDept);
+ max.setAttribute("department", deptId);
maxAddr.setAttribute("street", "Ripley St");
maxAddr.setAttribute("city", "Newton");
max.setAttribute("address", maxAddr);
- max.setAttribute("manager", jane);
- max.setAttribute("mentor", julius);
+ max.setAttribute("manager", janeId);
+ max.setAttribute("mentor", juliusId);
max.setAttribute("birthday",new Date(1979, 3, 15));
max.setAttribute("hasPets", true);
max.setAttribute("age", 36);
@@ -334,15 +352,15 @@ public final class TestUtilsV2 {
max.setAttribute("numberOfStarsEstimate", new BigInteger("1000000000000000000000000000000"));
max.setAttribute("approximationOfPi", new BigDecimal("3.1415926535897932"));
- john.setAttribute("manager", jane);
- john.setAttribute("mentor", max);
+ john.setAttribute("manager", janeId);
+ john.setAttribute("mentor", maxId);
hrDept.setAttribute("employees", ImmutableList.of(john, jane, julius, max));
jane.setAttribute("subordinates", ImmutableList.of(john, max));
- Map<String, Integer> secClearanceLevelMap = new HashMap<>();
- secClearanceLevelMap.put("level", 1);
- jane.setAttribute("SecurityClearance", secClearanceLevelMap);
+// Map<String, Integer> secClearanceLevelMap = new HashMap<>();
+// secClearanceLevelMap.put("level", 1);
+// jane.setAttribute("SecurityClearance", secClearanceLevelMap);
return hrDept;
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
----------------------------------------------------------------------
diff --git a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
index 9429c07..d171dcf 100644
--- a/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
+++ b/intg/src/test/java/org/apache/atlas/type/TestAtlasTypeRegistry.java
@@ -355,17 +355,17 @@ public class TestAtlasTypeRegistry {
} catch (AtlasBaseException excp) {
}
- Map<String, AtlasAttributeDef> attributeDefs = null;
+ Map<String, AtlasStructType.AtlasAttribute> attributes = null;
if (type != null) {
if (type instanceof AtlasEntityType) {
- attributeDefs = ((AtlasEntityType) type).getAllAttributeDefs();
+ attributes = ((AtlasEntityType) type).getAllAttributes();
} else if (type instanceof AtlasClassificationType) {
- attributeDefs = ((AtlasClassificationType) type).getAllAttributeDefs();
+ attributes = ((AtlasClassificationType) type).getAllAttributes();
}
}
- assertNotNull(attributeDefs);
- assertEquals(attributeDefs.keySet(), attributeNames);
+ assertNotNull(attributes);
+ assertEquals(attributes.keySet(), attributeNames);
}
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/release-log.txt
----------------------------------------------------------------------
diff --git a/release-log.txt b/release-log.txt
index 92594cf..e9587c3 100644
--- a/release-log.txt
+++ b/release-log.txt
@@ -9,7 +9,11 @@ ATLAS-1060 Add composite indexes for exact match performance improvements for al
ATLAS-1127 Modify creation and modification timestamps to Date instead of Long(sumasai)
ALL CHANGES:
+ATLAS-1467 instance create/full-Update implementation (sumasai via mneethiraj)
+ATLAS-1463 option to exclude specific entity attributes in audit records (sarath.kum4r@gmail.com via mneethiraj)
ATLAS-1386 Avoid uunnecessary type cache lookups (jnhagelb)
+ATLAS-1000 added build instructions to README.txt (mneethiraj)
+ATLAS-1471 avoid unnecessary overhead in debug log calls (mneethiraj)
ATLAS-1464 option to include only specified attributes in notification message (sarath.kum4r@gmail.com via mneethiraj)
ATLAS-1460 v2 search API updated to return name/description/owner and classification names in result (vimalsharma via mneethiraj)
ATLAS-1434 fixed unit test to use correct type names; updated error message per review comments (ashutoshm via mneethiraj)
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java b/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
index 54dda50..c4d5020 100755
--- a/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
+++ b/repository/src/main/java/org/apache/atlas/RepositoryMetadataModule.java
@@ -24,6 +24,7 @@ import com.google.inject.matcher.Matchers;
import com.google.inject.multibindings.Multibinder;
import org.aopalliance.intercept.MethodInterceptor;
+import org.apache.atlas.discovery.AtlasDiscoveryService;
import org.apache.atlas.discovery.AtlasLineageService;
import org.apache.atlas.discovery.DataSetLineageService;
import org.apache.atlas.discovery.DiscoveryService;
@@ -34,7 +35,6 @@ import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService;
import org.apache.atlas.listener.EntityChangeListener;
import org.apache.atlas.listener.TypeDefChangeListener;
import org.apache.atlas.listener.TypesChangeListener;
-import org.apache.atlas.discovery.AtlasDiscoveryService;
import org.apache.atlas.repository.MetadataRepository;
import org.apache.atlas.repository.audit.EntityAuditListener;
import org.apache.atlas.repository.audit.EntityAuditRepository;
@@ -42,8 +42,17 @@ import org.apache.atlas.repository.graph.DeleteHandler;
import org.apache.atlas.repository.graph.GraphBackedMetadataRepository;
import org.apache.atlas.repository.graph.GraphBackedSearchIndexer;
import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.repository.store.graph.EntityGraphDiscovery;
+import org.apache.atlas.repository.store.graph.EntityResolver;
+import org.apache.atlas.repository.store.graph.v1.ArrayVertexMapper;
+import org.apache.atlas.repository.store.graph.v1.AtlasEntityGraphDiscoveryV1;
import org.apache.atlas.repository.store.graph.v1.AtlasEntityStoreV1;
import org.apache.atlas.repository.store.graph.v1.AtlasTypeDefGraphStoreV1;
+import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1;
+import org.apache.atlas.repository.store.graph.v1.EntityGraphMapper;
+import org.apache.atlas.repository.store.graph.v1.IDBasedEntityResolver;
+import org.apache.atlas.repository.store.graph.v1.MapVertexMapper;
+import org.apache.atlas.repository.store.graph.v1.UniqAttrBasedEntityResolver;
import org.apache.atlas.repository.typestore.GraphBackedTypeStore;
import org.apache.atlas.repository.typestore.ITypeStore;
import org.apache.atlas.service.Service;
@@ -106,8 +115,21 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
bind(DeleteHandler.class).to(AtlasRepositoryConfiguration.getDeleteHandlerImpl()).asEagerSingleton();
+ bind(DeleteHandlerV1.class).to(AtlasRepositoryConfiguration.getDeleteHandlerV1Impl()).asEagerSingleton();
+
bind(TypeCache.class).to(AtlasRepositoryConfiguration.getTypeCache()).asEagerSingleton();
+ bind(EntityGraphMapper.class);
+
+ bind(MapVertexMapper.class).asEagerSingleton();
+
+ bind(ArrayVertexMapper.class).asEagerSingleton();
+
+ Multibinder<EntityResolver> entityRefResolver =
+ Multibinder.newSetBinder(binder(), EntityResolver.class);
+ entityRefResolver.addBinding().to(IDBasedEntityResolver.class);
+ entityRefResolver.addBinding().to(UniqAttrBasedEntityResolver.class);
+
//Add EntityAuditListener as EntityChangeListener
Multibinder<EntityChangeListener> entityChangeListenerBinder =
Multibinder.newSetBinder(binder(), EntityChangeListener.class);
@@ -116,6 +138,8 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
MethodInterceptor interceptor = new GraphTransactionInterceptor();
requestInjection(interceptor);
bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), interceptor);
+
+ bind(EntityGraphDiscovery.class).to(AtlasEntityGraphDiscoveryV1.class);
}
protected Configuration getConfiguration() {
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
index 2be9a2d..2b4561d 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/EntityDiscoveryService.java
@@ -228,7 +228,7 @@ public class EntityDiscoveryService implements AtlasDiscoveryService {
String state = vertex.getProperty(Constants.STATE_PROPERTY_KEY, String.class);
if (state != null) {
- Status status = (state.equalsIgnoreCase("ACTIVE") ? Status.STATUS_ACTIVE : Status.STATUS_DELETED);
+ Status status = (state.equalsIgnoreCase("ACTIVE") ? Status.ACTIVE : Status.DELETED);
ret.setStatus(status);
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/discovery/EntityLineageService.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/discovery/EntityLineageService.java b/repository/src/main/java/org/apache/atlas/discovery/EntityLineageService.java
index 45e2dd2..6b7d7d3 100644
--- a/repository/src/main/java/org/apache/atlas/discovery/EntityLineageService.java
+++ b/repository/src/main/java/org/apache/atlas/discovery/EntityLineageService.java
@@ -184,7 +184,7 @@ public class EntityLineageService implements AtlasLineageService {
ret.setDisplayText(vertex.getProperty(Constants.QUALIFIED_NAME, String.class));
String state = vertex.getProperty(Constants.STATE_PROPERTY_KEY, String.class);
- Status status = (state.equalsIgnoreCase("ACTIVE") ? Status.STATUS_ACTIVE : Status.STATUS_DELETED);
+ Status status = (state.equalsIgnoreCase("ACTIVE") ? Status.ACTIVE : Status.DELETED);
ret.setStatus(status);
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
index 5259249..889236c 100755
--- a/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
+++ b/repository/src/main/java/org/apache/atlas/repository/graph/GraphHelper.java
@@ -967,7 +967,7 @@ public final class GraphHelper {
instanceVertex.setListProperty(actualPropertyName, value);
}
- public static List<String> getListProperty(AtlasVertex instanceVertex, String propertyName) throws AtlasException {
+ public static List<String> getListProperty(AtlasVertex instanceVertex, String propertyName) {
String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
return instanceVertex.getListProperty(actualPropertyName);
}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasEntityStore.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasEntityStore.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasEntityStore.java
index f17b816..c42f95f 100644
--- a/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasEntityStore.java
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/AtlasEntityStore.java
@@ -25,6 +25,7 @@ import org.apache.atlas.model.instance.AtlasEntity;
import org.apache.atlas.model.instance.AtlasEntityWithAssociations;
import org.apache.atlas.model.instance.EntityMutations;
import org.apache.atlas.model.instance.EntityMutationResponse;
+import org.apache.atlas.type.AtlasTypeRegistry;
import java.util.List;
@@ -36,14 +37,14 @@ public interface AtlasEntityStore {
/**
* Initialization
*/
- void init() throws AtlasBaseException;
+ void init(AtlasTypeRegistry typeRegistry, EntityGraphDiscovery graphDiscovery) throws AtlasBaseException;
/**
* Create or update an entity if it already exists.
* @param entity
* @return
*/
- EntityMutationResponse createOrUpdate(AtlasEntity entity);
+ EntityMutationResponse createOrUpdate(AtlasEntity entity) throws AtlasBaseException;
/**
@@ -175,4 +176,5 @@ public interface AtlasEntityStore {
* @throws AtlasBaseException
*/
AtlasEntity.AtlasEntities searchEntities(SearchFilter searchFilter) throws AtlasBaseException;
-}
\ No newline at end of file
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscovery.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscovery.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscovery.java
new file mode 100644
index 0000000..38fca03
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscovery.java
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph;
+
+
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.instance.AtlasEntity;
+
+import java.util.List;
+
+public interface EntityGraphDiscovery {
+
+
+ void init() throws AtlasBaseException;
+
+ /*
+ * Return list of resolved and unresolved references.
+ * Resolved references already exist in the ATLAS repository and have an assigned unique GUID
+ * Unresolved attribute references result in an error if they are not composite (managed by a parent entity)
+ */
+ EntityGraphDiscoveryContext discoverEntities(List<AtlasEntity> entities) throws AtlasBaseException;
+
+ void cleanUp() throws AtlasBaseException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscoveryContext.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscoveryContext.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscoveryContext.java
new file mode 100644
index 0000000..2d748da
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityGraphDiscoveryContext.java
@@ -0,0 +1,170 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph;
+
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasEntityType;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+public final class EntityGraphDiscoveryContext {
+
+ /**
+ * Keeps track of all the entities that need to be created/updated including its child entities *
+ */
+ private Set<AtlasEntity> rootEntities = new LinkedHashSet<>();
+
+ //Key is a transient id/guid
+ /**
+ * These references have been resolved using a unique identifier like guid or a qualified name etc in Atlas repository
+ */
+ private Map<String, AtlasVertex> repositoryResolvedReferences = new LinkedHashMap<>();
+
+ /**
+ * Unresolved entity references
+ */
+ private List<AtlasEntity> unresolvedEntityReferences = new ArrayList<>();
+
+ /**
+ * Unresolved entity id references
+ */
+ private Set<AtlasObjectId> unresolvedIdReferences = new HashSet<>();
+
+ public void addRepositoryResolvedReference(AtlasObjectId id, AtlasVertex vertex) {
+ repositoryResolvedReferences.put(id.getGuid(), vertex);
+ }
+
+ public void addUnResolvedEntityReference(AtlasEntity entity) {
+ this.unresolvedEntityReferences.add(entity);
+ }
+
+ public void addUnResolvedIdReference(AtlasEntityType entityType, String id) {
+ this.unresolvedIdReferences.add(new AtlasObjectId(entityType.getTypeName(), id));
+ }
+
+ public Set<AtlasObjectId> getUnresolvedIdReferences() {
+ return unresolvedIdReferences;
+ }
+
+ public boolean isResolved(String guid) {
+ return repositoryResolvedReferences.containsKey(guid);
+ }
+
+ public AtlasVertex getResolvedReference(AtlasObjectId ref) {
+ return repositoryResolvedReferences.get(ref.getGuid());
+ }
+
+ public Map<String, AtlasVertex> getRepositoryResolvedReferences() {
+ return repositoryResolvedReferences;
+ }
+
+ public AtlasVertex getResolvedReference(String id) {
+ return repositoryResolvedReferences.get(id);
+ }
+
+ public List<AtlasEntity> getUnResolvedEntityReferences() {
+ return unresolvedEntityReferences;
+ }
+
+ public void addRootEntity(AtlasEntity rootEntity) {
+ this.rootEntities.add(rootEntity);
+ }
+
+ public Collection<AtlasEntity> getRootEntities() {
+ return rootEntities;
+ }
+
+ public boolean removeUnResolvedEntityReference(final AtlasEntity entity) {
+ return unresolvedEntityReferences.remove(entity);
+ }
+
+ public boolean removeUnResolvedEntityReferences(final List<AtlasEntity> entities) {
+ return unresolvedEntityReferences.removeAll(entities);
+ }
+
+ public boolean removeUnResolvedIdReferences(final List<AtlasObjectId> entities) {
+ return unresolvedIdReferences.removeAll(entities);
+ }
+
+ public boolean removeUnResolvedIdReference(final AtlasObjectId entity) {
+ return unresolvedIdReferences.remove(entity);
+ }
+
+ public boolean hasUnresolvedReferences() {
+ return unresolvedEntityReferences.size() > 0 || unresolvedIdReferences.size() > 0;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) {
+ return false;
+ } else if (obj == this) {
+ return true;
+ } else if (obj.getClass() != getClass()) {
+ return false;
+ } else {
+ EntityGraphDiscoveryContext ctx = (EntityGraphDiscoveryContext) obj;
+ return Objects.equals(rootEntities, ctx.getRootEntities()) &&
+ Objects.equals(repositoryResolvedReferences, ctx.getRepositoryResolvedReferences()) &&
+ Objects.equals(unresolvedEntityReferences, ctx.getUnResolvedEntityReferences()) &&
+ Objects.equals(unresolvedIdReferences, ctx.getUnresolvedIdReferences());
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rootEntities, repositoryResolvedReferences, unresolvedEntityReferences, unresolvedIdReferences);
+ }
+
+ public StringBuilder toString(StringBuilder sb) {
+ if (sb == null) {
+ sb = new StringBuilder();
+ }
+
+ sb.append("EntityGraphDiscoveryCtx{");
+ sb.append("rootEntities='").append(rootEntities).append('\'');
+ sb.append(", repositoryResolvedReferences=").append(repositoryResolvedReferences);
+ sb.append(", unresolvedEntityReferences='").append(unresolvedEntityReferences).append('\'');
+ sb.append(", unresolvedIdReferences='").append(unresolvedIdReferences).append('\'');
+ sb.append('}');
+
+ return sb;
+ }
+
+ @Override
+ public String toString() {
+ return toString(new StringBuilder()).toString();
+ }
+
+ public void cleanUp() {
+ rootEntities.clear();
+ unresolvedEntityReferences.clear();
+ repositoryResolvedReferences.clear();
+ unresolvedIdReferences.clear();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityResolver.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityResolver.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityResolver.java
new file mode 100644
index 0000000..35ddc7d
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/EntityResolver.java
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph;
+
+import org.apache.atlas.exception.AtlasBaseException;
+
+
+public interface EntityResolver {
+
+ void init(EntityGraphDiscoveryContext entities) throws AtlasBaseException;
+
+ EntityGraphDiscoveryContext resolveEntityReferences() throws AtlasBaseException;
+
+ void cleanUp() throws AtlasBaseException;
+}
http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/2f1cb57a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/ArrayVertexMapper.java
----------------------------------------------------------------------
diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/ArrayVertexMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/ArrayVertexMapper.java
new file mode 100644
index 0000000..528430c
--- /dev/null
+++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/ArrayVertexMapper.java
@@ -0,0 +1,179 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.store.graph.v1;
+
+import com.google.common.base.Optional;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.apache.atlas.aspect.Monitored;
+import org.apache.atlas.exception.AtlasBaseException;
+import org.apache.atlas.model.typedef.AtlasStructDef;
+import org.apache.atlas.repository.graph.GraphHelper;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.type.AtlasArrayType;
+import org.apache.atlas.type.AtlasStructType;
+import org.apache.atlas.type.AtlasType;
+import org.apache.commons.collections.CollectionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.apache.atlas.repository.graph.GraphHelper.string;
+
+@Singleton
+public class ArrayVertexMapper implements InstanceGraphMapper<List> {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ArrayVertexMapper.class);
+
+ protected final DeleteHandlerV1 deleteHandler;
+
+ protected StructVertexMapper structVertexMapper;
+
+ @Inject
+ public ArrayVertexMapper(DeleteHandlerV1 deleteHandler) {
+ this.deleteHandler = deleteHandler;
+ }
+
+ void init(StructVertexMapper structVertexMapper) {
+ this.structVertexMapper = structVertexMapper;
+ }
+
+ @Override
+ public List toGraph(GraphMutationContext ctx) throws AtlasBaseException {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Mapping instance to vertex {} for array attribute {}", string(ctx.getReferringVertex()), ctx.getAttrType().getTypeName());
+ }
+
+ List newElements = (List) ctx.getValue();
+ boolean newAttributeEmpty = (newElements == null || newElements.isEmpty());
+
+ AtlasArrayType arrType = (AtlasArrayType) ctx.getAttrType();
+ AtlasType elementType = arrType.getElementType();
+ List<Object> currentElements = getArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexPropertyKey());
+
+ List<Object> newElementsCreated = new ArrayList<>();
+
+ if (!newAttributeEmpty) {
+ for (int index = 0; index < newElements.size(); index++) {
+
+ LOG.debug("Adding/updating element at position {}, current element {}, new element {}", index,
+ (currentElements != null && index < currentElements.size()) ? currentElements.get(index) : null, newElements.get(index));
+
+ Optional<AtlasEdge> existingEdge = getEdgeAt(currentElements, index, arrType.getElementType());
+
+ GraphMutationContext arrCtx = new GraphMutationContext.Builder(ctx.getAttribute(),
+ arrType.getElementType(), newElements.get(index))
+ .referringVertex(ctx.getReferringVertex())
+ .edge(existingEdge)
+ .vertexProperty(ctx.getVertexPropertyKey()).build();
+
+ Object newEntry = structVertexMapper.mapCollectionElementsToVertex(arrCtx);
+ newElementsCreated.add(newEntry);
+ }
+ }
+
+ if (AtlasGraphUtilsV1.isReference(elementType)) {
+ List<AtlasEdge> additionalEdges = removeUnusedArrayEntries(ctx.getParentType(), ctx.getAttributeDef(), (List) currentElements, (List) newElementsCreated, elementType);
+ newElementsCreated.addAll(additionalEdges);
+ }
+
+ // for dereference on way out
+ setArrayElementsProperty(elementType, ctx.getReferringVertex(), ctx.getVertexPropertyKey(), newElementsCreated);
+ return newElementsCreated;
+ }
+
+ @Override
+ public void cleanUp() throws AtlasBaseException {
+
+ }
+
+ //Removes unused edges from the old collection, compared to the new collection
+ private List<AtlasEdge> removeUnusedArrayEntries(
+ AtlasStructType entityType,
+ AtlasStructDef.AtlasAttributeDef attributeDef,
+ List<AtlasEdge> currentEntries,
+ List<AtlasEdge> newEntries,
+ AtlasType entryType) throws AtlasBaseException {
+ if (currentEntries != null && !currentEntries.isEmpty()) {
+ LOG.debug("Removing unused entries from the old collection");
+ if (AtlasGraphUtilsV1.isReference(entryType)) {
+
+ Collection<AtlasEdge> edgesToRemove = CollectionUtils.subtract(currentEntries, newEntries);
+
+ LOG.debug("Removing unused entries from the old collection - {}", edgesToRemove);
+
+ if (!edgesToRemove.isEmpty()) {
+ //Remove the edges for (current edges - new edges)
+ List<AtlasEdge> additionalElements = new ArrayList<>();
+
+ for (AtlasEdge edge : edgesToRemove) {
+ boolean deleteChildReferences = StructVertexMapper.shouldManageChildReferences(entityType, attributeDef.getName());
+ boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(),
+ deleteChildReferences, true);
+ if (!deleted) {
+ additionalElements.add(edge);
+ }
+ }
+
+ return additionalElements;
+ }
+ }
+ }
+ return Collections.emptyList();
+ }
+
+ public static List<Object> getArrayElementsProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName) {
+ String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
+ if (AtlasGraphUtilsV1.isReference(elementType)) {
+ return (List)instanceVertex.getListProperty(actualPropertyName, AtlasEdge.class);
+ }
+ else {
+ return (List)instanceVertex.getListProperty(actualPropertyName);
+ }
+ }
+
+ private Optional<AtlasEdge> getEdgeAt(List<Object> currentElements, int index, AtlasType elemType) {
+ Optional<AtlasEdge> existingEdge = Optional.absent();
+ if ( AtlasGraphUtilsV1.isReference(elemType) ) {
+ Object currentElement = (currentElements != null && index < currentElements.size()) ?
+ currentElements.get(index) : null;
+
+ if ( currentElement != null) {
+ existingEdge = Optional.of((AtlasEdge) currentElement);
+ }
+ }
+
+ return existingEdge;
+ }
+
+ private void setArrayElementsProperty(AtlasType elementType, AtlasVertex instanceVertex, String propertyName, List<Object> values) {
+ String actualPropertyName = GraphHelper.encodePropertyKey(propertyName);
+ if (AtlasGraphUtilsV1.isReference(elementType)) {
+ GraphHelper.setListPropertyFromElementIds(instanceVertex, actualPropertyName, (List) values);
+ }
+ else {
+ GraphHelper.setProperty(instanceVertex, actualPropertyName, values);
+ }
+ }
+}