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 c628451c2c..e9985354ed 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 @@ -61,10 +61,7 @@ public class AtlasEntityHeader extends AtlasStruct implements Serializable { private String displayText = null; private List classificationNames = null; private List classifications = null; - private List appendClassifications = null; - - - private List updateClassifications = null; + private List addOrUpdateClassifications = null; private List removeClassifications = null; private List meaningNames = null; private List meanings = null; @@ -106,20 +103,12 @@ public AtlasEntityHeader(String typeName, Map attributes) { setLabels(null); } - public List getAppendClassifications() { - return appendClassifications; - } - - public void setAppendClassifications(List appendClassifications) { - this.appendClassifications = appendClassifications; - } - - public List getUpdateClassifications() { - return updateClassifications; + public List getAddOrUpdateClassifications() { + return addOrUpdateClassifications; } - public void setUpdateClassifications(List updateClassifications) { - this.updateClassifications = updateClassifications; + public void setAddOrUpdateClassifications(List addOrUpdateClassifications) { + this.addOrUpdateClassifications = addOrUpdateClassifications; } public List getRemoveClassifications() { diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociator.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociator.java index b0e85782df..a7d9f34d06 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociator.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/ClassificationAssociator.java @@ -54,7 +54,6 @@ import java.util.Optional; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import static org.apache.atlas.AtlasConfiguration.ENTITY_CHANGE_NOTIFY_IGNORE_RELATIONSHIP_ATTRIBUTES; @@ -245,39 +244,44 @@ public void setClassifications(Map map, boolean overr private Map> validateAndTransfer(AtlasEntityHeader incomingEntityHeader, AtlasEntityHeader entityToBeChanged) throws AtlasBaseException { Map> operationListMap = new HashMap<>(); - Set requiredClassificationKeys = Stream.concat( - Optional.ofNullable(incomingEntityHeader.getRemoveClassifications()).orElse(Collections.emptyList()).stream(), - Optional.ofNullable(incomingEntityHeader.getUpdateClassifications()).orElse(Collections.emptyList()).stream() - ).filter(classification -> classification.getEntityGuid().equals(entityToBeChanged.getGuid())) - .map(this::generateClassificationComparisonKey) - .collect(Collectors.toSet()); + Set preExistingClassificationKeys = new HashSet<>(); + List filteredRemoveClassifications = new ArrayList<>(); - Set preExistingClassificationKeys = Optional.ofNullable(entityToBeChanged.getClassifications()) - .orElse(Collections.emptyList()) - .stream() - .filter(classification -> classification.getEntityGuid().equals(entityToBeChanged.getGuid())) - .map(this::generateClassificationComparisonKey) - .collect(Collectors.toSet()); + ListOps listOps = new ListOps<>(); - Set diff = requiredClassificationKeys.stream() - .filter(key -> !preExistingClassificationKeys.contains(key)) - .collect(Collectors.toSet()); + for (AtlasClassification classification : Optional.ofNullable(entityToBeChanged.getClassifications()).orElse(Collections.emptyList())) { + if (entityToBeChanged.getGuid().equals(classification.getEntityGuid())) { + String key = generateClassificationComparisonKey(classification); + preExistingClassificationKeys.add(key); // Track pre-existing keys + } + } - if (!diff.isEmpty()) { - String firstTypeName = diff.iterator().next().split("\\|")[1]; - throw new AtlasBaseException(AtlasErrorCode.CLASSIFICATION_NOT_ASSOCIATED_WITH_ENTITY, firstTypeName); + for (AtlasClassification classification : Optional.ofNullable(incomingEntityHeader.getRemoveClassifications()).orElse(Collections.emptyList())) { + if (entityToBeChanged.getGuid().equals(classification.getEntityGuid())) { + String key = generateClassificationComparisonKey(classification); + // If the classification doesn't exist in pre-existing keys, log it + if (!preExistingClassificationKeys.contains(key)) { + String typeName = key.split("\\|")[1]; + LOG.info("Classification {} is not associated with entity {}", typeName, entityToBeChanged.getGuid()); + } else { + filteredRemoveClassifications.add(classification); + } + } } - List filteredClassifications = Optional.ofNullable(incomingEntityHeader.getAppendClassifications()) + List filteredClassifications = Optional.ofNullable(incomingEntityHeader.getAddOrUpdateClassifications()) .orElse(Collections.emptyList()) .stream() .filter(classification -> classification.getEntityGuid().equals(entityToBeChanged.getGuid())) - .filter(appendClassification -> !preExistingClassificationKeys.contains(generateClassificationComparisonKey(appendClassification))) .collect(Collectors.toList()); - bucket(PROCESS_DELETE, operationListMap, incomingEntityHeader.getRemoveClassifications()); - bucket(PROCESS_UPDATE, operationListMap, incomingEntityHeader.getUpdateClassifications()); - bucket(PROCESS_ADD, operationListMap, filteredClassifications); + List incomingClassifications = listOps.filter(incomingEntityHeader.getGuid(), filteredClassifications); + List entityClassifications = listOps.filter(entityToBeChanged.getGuid(), entityToBeChanged.getClassifications()); + + bucket(PROCESS_DELETE, operationListMap, filteredRemoveClassifications); + bucket(PROCESS_UPDATE, operationListMap, listOps.intersect(incomingClassifications, entityClassifications)); + bucket(PROCESS_ADD, operationListMap, listOps.subtract(incomingClassifications, entityClassifications)); + return operationListMap; }