Repository: atlas Updated Branches: refs/heads/branch-1.0 2bebba809 -> 7869c9a5f
ATLAS-2774: enhancement to support parameterized delete-type (hard or soft) per API call (cherry picked from commit d003ddb33b16a0a67e6b7f7eae29c1638a4d0971) Project: http://git-wip-us.apache.org/repos/asf/atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/atlas/commit/7869c9a5 Tree: http://git-wip-us.apache.org/repos/asf/atlas/tree/7869c9a5 Diff: http://git-wip-us.apache.org/repos/asf/atlas/diff/7869c9a5 Branch: refs/heads/branch-1.0 Commit: 7869c9a5fe884397b883f30236ae01aa710d8c31 Parents: 2bebba8 Author: Madhan Neethiraj <mad...@apache.org> Authored: Tue Nov 13 17:11:48 2018 -0800 Committer: Madhan Neethiraj <mad...@apache.org> Committed: Wed Nov 14 18:07:39 2018 -0800 ---------------------------------------------------------------------- .../org/apache/atlas/AtlasConfiguration.java | 2 + .../java/org/apache/atlas/store/DeleteType.java | 44 ++++ .../store/graph/v1/DeleteHandlerDelegate.java | 86 ++++++++ .../store/graph/v1/SoftDeleteHandlerV1.java | 4 - .../store/graph/v2/AtlasEntityStoreV2.java | 10 +- .../graph/v2/AtlasRelationshipStoreV2.java | 20 +- .../store/graph/v2/BulkImporterImpl.java | 2 +- .../store/graph/v2/EntityGraphMapper.java | 31 ++- .../test/java/org/apache/atlas/TestModules.java | 25 --- .../repository/impexp/ExportImportTestBase.java | 12 -- .../repository/impexp/ExportServiceTest.java | 12 -- .../impexp/ExportSkipLineageTest.java | 7 +- .../store/graph/v1/SoftReferenceTest.java | 12 +- .../store/graph/v2/AtlasEntityStoreV2Test.java | 2 +- .../store/graph/v2/AtlasEntityTestBase.java | 6 +- .../AtlasRelationshipStoreHardDeleteV2Test.java | 13 +- .../AtlasRelationshipStoreSoftDeleteV2Test.java | 11 +- .../graph/v2/AtlasRelationshipStoreV2Test.java | 15 +- .../InverseReferenceUpdateHardDeleteV2Test.java | 11 +- .../InverseReferenceUpdateSoftDeleteV2Test.java | 11 +- .../graph/v2/InverseReferenceUpdateV2Test.java | 10 + .../java/org/apache/atlas/RequestContext.java | 44 ++-- .../apache/atlas/web/filters/AuditFilter.java | 20 ++ .../web/adapters/TestEntityRESTDelete.java | 207 +++++++++++++++++++ 24 files changed, 479 insertions(+), 138 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java index 1b3ce1e..c5357f5 100644 --- a/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java +++ b/intg/src/main/java/org/apache/atlas/AtlasConfiguration.java @@ -33,6 +33,8 @@ public enum AtlasConfiguration { QUERY_PARAM_MAX_LENGTH("atlas.query.param.max.length", 4*1024), + REST_API_ENABLE_DELETE_TYPE_OVERRIDE("atlas.rest.enable.delete.type.override", false), + NOTIFICATION_HOOK_TOPIC_NAME("atlas.notification.hook.topic.name", "ATLAS_HOOK"), NOTIFICATION_ENTITIES_TOPIC_NAME("atlas.notification.entities.topic.name", "ATLAS_ENTITIES"), http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/intg/src/main/java/org/apache/atlas/store/DeleteType.java ---------------------------------------------------------------------- diff --git a/intg/src/main/java/org/apache/atlas/store/DeleteType.java b/intg/src/main/java/org/apache/atlas/store/DeleteType.java new file mode 100644 index 0000000..de5e5e4 --- /dev/null +++ b/intg/src/main/java/org/apache/atlas/store/DeleteType.java @@ -0,0 +1,44 @@ +/** + * 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.store; + +import org.apache.commons.lang.StringUtils; + +public enum DeleteType { + DEFAULT, + SOFT, + HARD; + + public static DeleteType from(String s) { + if(StringUtils.isEmpty(s)) { + return DEFAULT; + } + + switch (s.toLowerCase()) { + case "soft": + return SOFT; + + case "hard": + return HARD; + + default: + return DEFAULT; + } + } +} http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerDelegate.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerDelegate.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerDelegate.java new file mode 100644 index 0000000..512eb46 --- /dev/null +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/DeleteHandlerDelegate.java @@ -0,0 +1,86 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.atlas.repository.store.graph.v1; + +import org.apache.atlas.RequestContext; +import org.apache.atlas.store.DeleteType; +import org.apache.atlas.type.AtlasTypeRegistry; +import org.apache.atlas.util.AtlasRepositoryConfiguration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +@Component +public class DeleteHandlerDelegate { + private static final Logger LOG = LoggerFactory.getLogger(DeleteHandlerDelegate.class); + + private final SoftDeleteHandlerV1 softDeleteHandler; + private final HardDeleteHandlerV1 hardDeleteHandler; + private final DeleteHandlerV1 defaultHandler; + + @Inject + public DeleteHandlerDelegate(AtlasTypeRegistry typeRegistry) { + this.softDeleteHandler = new SoftDeleteHandlerV1(typeRegistry); + this.hardDeleteHandler = new HardDeleteHandlerV1(typeRegistry); + this.defaultHandler = getDefaultConfiguredHandler(typeRegistry); + } + + public DeleteHandlerV1 getHandler() { + return getHandler(RequestContext.get().getDeleteType()); + } + + public DeleteHandlerV1 getHandler(DeleteType deleteType) { + if (deleteType == null) { + deleteType = DeleteType.DEFAULT; + } + + switch (deleteType) { + case SOFT: + return softDeleteHandler; + + case HARD: + return hardDeleteHandler; + + default: + return defaultHandler; + } + } + + private DeleteHandlerV1 getDefaultConfiguredHandler(AtlasTypeRegistry typeRegistry) { + DeleteHandlerV1 ret = null; + + try { + Class handlerFromProperties = AtlasRepositoryConfiguration.getDeleteHandlerV1Impl(); + + LOG.info("Default delete handler set to: {}", handlerFromProperties.getName()); + + ret = (DeleteHandlerV1) handlerFromProperties.getConstructor(AtlasTypeRegistry.class).newInstance(typeRegistry); + } catch (Exception ex) { + LOG.error("Error instantiating default delete handler. Defaulting to: {}", softDeleteHandler.getClass().getName(), ex); + + ret = softDeleteHandler; + } + + return ret; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1.java index 0bcf0d6..e614a4e 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v1/SoftDeleteHandlerV1.java @@ -19,14 +19,12 @@ package org.apache.atlas.repository.store.graph.v1; import org.apache.atlas.RequestContext; -import org.apache.atlas.annotation.ConditionalOnAtlasProperty; import org.apache.atlas.model.instance.AtlasEntity.Status; 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.repository.store.graph.v2.AtlasGraphUtilsV2; import org.apache.atlas.type.AtlasTypeRegistry; -import org.springframework.stereotype.Component; import javax.inject.Inject; @@ -35,8 +33,6 @@ import static org.apache.atlas.repository.Constants.MODIFICATION_TIMESTAMP_PROPE import static org.apache.atlas.repository.Constants.MODIFIED_BY_KEY; import static org.apache.atlas.repository.Constants.STATE_PROPERTY_KEY; -@Component -@ConditionalOnAtlasProperty(property = "atlas.DeleteHandlerV1.impl", isDefault = true) public class SoftDeleteHandlerV1 extends DeleteHandlerV1 { @Inject http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java index 7333696..ee8de1f 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2.java @@ -33,7 +33,7 @@ import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.EntityGraphDiscovery; import org.apache.atlas.repository.store.graph.EntityGraphDiscoveryContext; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.type.AtlasClassificationType; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasStructType.AtlasAttribute; @@ -62,16 +62,16 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore { private static final Logger PERF_LOG = AtlasPerfTracer.getPerfLogger("store.EntityStore"); - private final DeleteHandlerV1 deleteHandler; + private final DeleteHandlerDelegate deleteDelegate; private final AtlasTypeRegistry typeRegistry; private final AtlasEntityChangeNotifier entityChangeNotifier; private final EntityGraphMapper entityGraphMapper; private final EntityGraphRetriever entityRetriever; @Inject - public AtlasEntityStoreV2(DeleteHandlerV1 deleteHandler, AtlasTypeRegistry typeRegistry, + public AtlasEntityStoreV2(DeleteHandlerDelegate deleteDelegate, AtlasTypeRegistry typeRegistry, AtlasEntityChangeNotifier entityChangeNotifier, EntityGraphMapper entityGraphMapper) { - this.deleteHandler = deleteHandler; + this.deleteDelegate = deleteDelegate; this.typeRegistry = typeRegistry; this.entityChangeNotifier = entityChangeNotifier; this.entityGraphMapper = entityGraphMapper; @@ -802,7 +802,7 @@ public class AtlasEntityStoreV2 implements AtlasEntityStore { EntityMutationResponse response = new EntityMutationResponse(); RequestContext req = RequestContext.get(); - deleteHandler.deleteEntities(deletionCandidates); // this will update req with list of deleted/updated entities + deleteDelegate.getHandler().deleteEntities(deletionCandidates); // this will update req with list of deleted/updated entities for (AtlasObjectId entity : req.getDeletedEntities()) { response.addEntity(DELETE, entity); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2.java index 21617dc..6bc36b3 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2.java @@ -41,7 +41,7 @@ import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasEdgeDirection; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasRelationshipType; import org.apache.atlas.type.AtlasStructType.AtlasAttribute; @@ -95,15 +95,15 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { private final AtlasTypeRegistry typeRegistry; private final EntityGraphRetriever entityRetriever; - private final DeleteHandlerV1 deleteHandler; + private final DeleteHandlerDelegate deleteDelegate; private final GraphHelper graphHelper = GraphHelper.getInstance(); private final AtlasEntityChangeNotifier entityChangeNotifier; @Inject - public AtlasRelationshipStoreV2(AtlasTypeRegistry typeRegistry, DeleteHandlerV1 deleteHandler, AtlasEntityChangeNotifier entityChangeNotifier) { + public AtlasRelationshipStoreV2(AtlasTypeRegistry typeRegistry, DeleteHandlerDelegate deleteDelegate, AtlasEntityChangeNotifier entityChangeNotifier) { this.typeRegistry = typeRegistry; this.entityRetriever = new EntityGraphRetriever(typeRegistry); - this.deleteHandler = deleteHandler; + this.deleteDelegate = deleteDelegate; this.entityChangeNotifier = entityChangeNotifier; } @@ -277,7 +277,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { AtlasAuthorizationUtils.verifyAccess(new AtlasRelationshipAccessRequest(typeRegistry,AtlasPrivilege.RELATIONSHIP_REMOVE, relationShipType, end1Entity, end2Entity )); - deleteHandler.deleteRelationships(Collections.singleton(edge), forceDelete); + deleteDelegate.getHandler().deleteRelationships(Collections.singleton(edge), forceDelete); // notify entities for added/removed classification propagation entityChangeNotifier.notifyPropagatedEntities(); @@ -426,7 +426,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { for (AtlasVertex classificationVertex : addedBlockedClassifications) { List<AtlasVertex> removePropagationFromVertices = graphHelper.getPropagatedEntityVertices(classificationVertex); - deleteHandler.removeTagPropagation(classificationVertex, removePropagationFromVertices); + deleteDelegate.getHandler().removeTagPropagation(classificationVertex, removePropagationFromVertices); } // add propagated tag for removed entry @@ -435,7 +435,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { for (AtlasVertex classificationVertex : removedBlockedClassifications) { List<AtlasVertex> addPropagationToVertices = graphHelper.getPropagatedEntityVertices(classificationVertex); - deleteHandler.addTagPropagation(classificationVertex, addPropagationToVertices); + deleteDelegate.getHandler().addTagPropagation(classificationVertex, addPropagationToVertices); } } } @@ -527,11 +527,11 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { } for (AtlasVertex classificationVertex : addPropagationsMap.keySet()) { - deleteHandler.addTagPropagation(classificationVertex, addPropagationsMap.get(classificationVertex)); + deleteDelegate.getHandler().addTagPropagation(classificationVertex, addPropagationsMap.get(classificationVertex)); } for (AtlasVertex classificationVertex : removePropagationsMap.keySet()) { - deleteHandler.removeTagPropagation(classificationVertex, removePropagationsMap.get(classificationVertex)); + deleteDelegate.getHandler().removeTagPropagation(classificationVertex, removePropagationsMap.get(classificationVertex)); } } else { // update blocked propagated classifications only if there is no change is tag propagation (don't update both) @@ -758,7 +758,7 @@ public class AtlasRelationshipStoreV2 implements AtlasRelationshipStore { handleBlockedClassifications(ret, relationship.getBlockedPropagatedClassifications()); // propagate tags - deleteHandler.addTagPropagation(ret, tagPropagation); + deleteDelegate.getHandler().addTagPropagation(ret, tagPropagation); } return ret; http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java index a3d31b6..dc8bd19 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/BulkImporterImpl.java @@ -100,7 +100,7 @@ public class BulkImporterImpl implements BulkImporter { throw abe; } } finally { - RequestContext.clear(); + RequestContext.get().clearCache(); } } http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java ---------------------------------------------------------------------- diff --git a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java index e8c8c0c..f5a5982 100644 --- a/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java +++ b/repository/src/main/java/org/apache/atlas/repository/store/graph/v2/EntityGraphMapper.java @@ -26,7 +26,6 @@ import org.apache.atlas.model.TimeBoundary; import org.apache.atlas.model.TypeCategory; import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; import org.apache.atlas.model.instance.AtlasEntityHeader; import org.apache.atlas.model.instance.AtlasObjectId; import org.apache.atlas.model.instance.AtlasRelatedObjectId; @@ -43,7 +42,7 @@ import org.apache.atlas.repository.graphdb.AtlasEdge; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.graphdb.AtlasVertex; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.type.AtlasArrayType; import org.apache.atlas.type.AtlasBuiltInTypes; import org.apache.atlas.type.AtlasClassificationType; @@ -93,7 +92,7 @@ public class EntityGraphMapper { private final GraphHelper graphHelper = GraphHelper.getInstance(); private final AtlasGraph graph; - private final DeleteHandlerV1 deleteHandler; + private final DeleteHandlerDelegate deleteDelegate; private final AtlasTypeRegistry typeRegistry; private final AtlasRelationshipStore relationshipStore; private final AtlasEntityChangeNotifier entityChangeNotifier; @@ -101,10 +100,10 @@ public class EntityGraphMapper { private final EntityGraphRetriever entityRetriever; @Inject - public EntityGraphMapper(DeleteHandlerV1 deleteHandler, AtlasTypeRegistry typeRegistry, AtlasGraph atlasGraph, + public EntityGraphMapper(DeleteHandlerDelegate deleteDelegate, AtlasTypeRegistry typeRegistry, AtlasGraph atlasGraph, AtlasRelationshipStore relationshipStore, AtlasEntityChangeNotifier entityChangeNotifier, AtlasInstanceConverter instanceConverter) { - this.deleteHandler = deleteHandler; + this.deleteDelegate = deleteDelegate; this.typeRegistry = typeRegistry; this.graph = atlasGraph; this.relationshipStore = relationshipStore; @@ -394,7 +393,7 @@ public class EntityGraphMapper { AtlasEdge newEdge = mapStructValue(ctx, context); if (currentEdge != null && !currentEdge.equals(newEdge)) { - deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true, ctx.getReferringVertex()); + deleteDelegate.getHandler().deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), false, true, ctx.getReferringVertex()); } return newEdge; @@ -466,7 +465,7 @@ public class EntityGraphMapper { } //delete old reference - deleteHandler.deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(), + deleteDelegate.getHandler().deleteEdgeReference(currentEdge, ctx.getAttrType().getTypeCategory(), ctx.getAttribute().isOwnedRef(), true, ctx.getAttribute().getRelationshipEdgeDirection(), ctx.getReferringVertex()); } @@ -527,7 +526,7 @@ public class EntityGraphMapper { if (inverseEdge != null) { if (!inverseEdge.equals(newEdge)) { // Disconnect old reference - deleteHandler.deleteEdgeReference(inverseEdge, inverseAttribute.getAttributeType().getTypeCategory(), + deleteDelegate.getHandler().deleteEdgeReference(inverseEdge, inverseAttribute.getAttributeType().getTypeCategory(), inverseAttribute.isOwnedRef(), true, inverseVertex); } else { @@ -1178,7 +1177,7 @@ public class EntityGraphMapper { AtlasEdge currentEdge = (AtlasEdge) currentMap.get(currentKey); if (!newMap.values().contains(currentEdge)) { - boolean deleted = deleteHandler.deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true, vertex); + boolean deleted = deleteDelegate.getHandler().deleteEdgeReference(currentEdge, mapType.getValueType().getTypeCategory(), attribute.isOwnedRef(), true, vertex); if (!deleted) { additionalMap.put(currentKey, currentEdge); @@ -1308,7 +1307,7 @@ public class EntityGraphMapper { List<AtlasEdge> additionalElements = new ArrayList<>(); for (AtlasEdge edge : edgesToRemove) { - boolean deleted = deleteHandler.deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(), + boolean deleted = deleteDelegate.getHandler().deleteEdgeReference(edge, entryType.getTypeCategory(), attribute.isOwnedRef(), true, attribute.getRelationshipEdgeDirection(), entityVertex); if (!deleted) { @@ -1447,7 +1446,7 @@ public class EntityGraphMapper { LOG.debug("Propagating tag: [{}][{}] to {}", classificationName, entityTypeName, getTypeNames(entitiesToPropagateTo)); } - List<AtlasVertex> entitiesPropagatedTo = deleteHandler.addTagPropagation(classificationVertex, entitiesToPropagateTo); + List<AtlasVertex> entitiesPropagatedTo = deleteDelegate.getHandler().addTagPropagation(classificationVertex, entitiesToPropagateTo); if (entitiesPropagatedTo != null) { for (AtlasVertex entityPropagatedTo : entitiesPropagatedTo) { @@ -1506,7 +1505,7 @@ public class EntityGraphMapper { throw new AtlasBaseException(AtlasErrorCode.INSTANCE_GUID_NOT_FOUND, entityGuid); } - deleteHandler.deletePropagatedClassification(entityVertex, classificationName, associatedEntityGuid); + deleteDelegate.getHandler().deletePropagatedClassification(entityVertex, classificationName, associatedEntityGuid); } public void deleteClassification(String entityGuid, String classificationName) throws AtlasBaseException { @@ -1535,7 +1534,7 @@ public class EntityGraphMapper { // remove classification from propagated entities if propagation is turned on if (isPropagationEnabled(classificationVertex)) { - List<AtlasVertex> propagatedEntityVertices = deleteHandler.removeTagPropagation(classificationVertex); + List<AtlasVertex> propagatedEntityVertices = deleteDelegate.getHandler().removeTagPropagation(classificationVertex); // add propagated entities and deleted classification details to removeClassifications map if (CollectionUtils.isNotEmpty(propagatedEntityVertices)) { @@ -1572,7 +1571,7 @@ public class EntityGraphMapper { AtlasEdge edge = getClassificationEdge(entityVertex, classificationVertex); - deleteHandler.deleteEdgeReference(edge, CLASSIFICATION, false, true, entityVertex); + deleteDelegate.getHandler().deleteEdgeReference(edge, CLASSIFICATION, false, true, entityVertex); traitNames.remove(classificationName); @@ -1701,7 +1700,7 @@ public class EntityGraphMapper { } } - List<AtlasVertex> entitiesPropagatedTo = deleteHandler.addTagPropagation(classificationVertex, entitiesToPropagateTo); + List<AtlasVertex> entitiesPropagatedTo = deleteDelegate.getHandler().addTagPropagation(classificationVertex, entitiesToPropagateTo); if (entitiesPropagatedTo != null) { for (AtlasVertex entityPropagatedTo : entitiesPropagatedTo) { @@ -1710,7 +1709,7 @@ public class EntityGraphMapper { } } } else { - List<AtlasVertex> impactedVertices = deleteHandler.removeTagPropagation(classificationVertex); + List<AtlasVertex> impactedVertices = deleteDelegate.getHandler().removeTagPropagation(classificationVertex); if (CollectionUtils.isNotEmpty(impactedVertices)) { if (removedPropagations == null) { http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/TestModules.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/TestModules.java b/repository/src/test/java/org/apache/atlas/TestModules.java index d3d30d5..94b08a1 100644 --- a/repository/src/test/java/org/apache/atlas/TestModules.java +++ b/repository/src/test/java/org/apache/atlas/TestModules.java @@ -59,10 +59,7 @@ import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2; import org.apache.atlas.repository.store.graph.v2.AtlasRelationshipStoreV2; import org.apache.atlas.repository.store.graph.v2.AtlasTypeDefGraphStoreV2; import org.apache.atlas.repository.store.graph.v2.BulkImporterImpl; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper; -import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.service.Service; import org.apache.atlas.store.AtlasTypeDefStore; @@ -125,8 +122,6 @@ public class TestModules { bindAuditRepository(binder()); - bindDeleteHandler(binder()); - bind(AtlasGraph.class).toProvider(AtlasGraphProvider.class); // allow for dynamic binding of graph service @@ -186,10 +181,6 @@ public class TestModules { bindInterceptor(Matchers.any(), Matchers.annotatedWith(GraphTransaction.class), graphTransactionInterceptor); } - protected void bindDeleteHandler(Binder binder) { - binder.bind(DeleteHandlerV1.class).to(AtlasRepositoryConfiguration.getDeleteHandlerV1Impl()).asEagerSingleton(); - } - protected void bindAuditRepository(Binder binder) { Class<? extends EntityAuditRepository> auditRepoImpl = AtlasRepositoryConfiguration.getAuditRepositoryImpl(); @@ -205,20 +196,4 @@ public class TestModules { } } } - - public static class SoftDeleteModule extends TestOnlyModule { - @Override - protected void bindDeleteHandler(Binder binder) { - bind(DeleteHandlerV1.class).to(SoftDeleteHandlerV1.class).asEagerSingleton(); - bind(AtlasEntityChangeNotifier.class).toProvider(MockNotifier.class); - } - } - - public static class HardDeleteModule extends TestOnlyModule { - @Override - protected void bindDeleteHandler(Binder binder) { - bind(DeleteHandlerV1.class).to(HardDeleteHandlerV1.class).asEagerSingleton(); - bind(AtlasEntityChangeNotifier.class).toProvider(MockNotifier.class); - } - } } http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportTestBase.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportTestBase.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportTestBase.java index 4b253ff..925b2a0 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportTestBase.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportImportTestBase.java @@ -18,14 +18,9 @@ package org.apache.atlas.repository.impexp; -import org.apache.atlas.ApplicationProperties; -import org.apache.atlas.AtlasConstants; -import org.apache.atlas.AtlasException; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.impexp.ExportImportAuditEntry; import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasTypeRegistry; @@ -39,11 +34,9 @@ import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.create import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadBaseModel; import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadEntity; import static org.apache.atlas.repository.impexp.ZipFileResourceTestUtils.loadHiveModel; -import static org.mockito.Mockito.mock; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; public class ExportImportTestBase { protected static final String ENTITIES_SUB_DIR = "stocksDB-Entities"; @@ -53,7 +46,6 @@ public class ExportImportTestBase { protected static final String TABLE_VIEW_GUID = "56415119-7cb0-40dd-ace8-1e50efd54991"; protected static final String COLUMN_GUID_HIGH = "f87a5320-1529-4369-8d63-b637ebdf2c1c"; - protected DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class); protected void basicSetup(AtlasTypeDefStore typeDefStore, AtlasTypeRegistry typeRegistry) throws IOException, AtlasBaseException { loadBaseModel(typeDefStore, typeRegistry); @@ -90,10 +82,6 @@ public class ExportImportTestBase { assertTrue(result.size() > 0); } - private String getCurrentCluster() throws AtlasException { - return ApplicationProperties.get().getString(AtlasConstants.CLUSTER_NAME_KEY, "default"); - } - protected void pauseForIndexCreation() { try { Thread.sleep(5000); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java index 936586b..db8c6c8 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportServiceTest.java @@ -30,12 +30,8 @@ import org.apache.atlas.model.instance.EntityMutationResponse; import org.apache.atlas.model.typedef.AtlasTypesDef; import org.apache.atlas.repository.graph.AtlasGraphProvider; import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer; -import org.apache.atlas.repository.store.graph.v2.AtlasEntityChangeNotifier; import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2; import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasType; @@ -60,11 +56,9 @@ import java.util.List; import java.util.Map; import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr; -import static org.mockito.Mockito.mock; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; @Guice(modules = TestModules.TestOnlyModule.class) public class ExportServiceTest extends ExportImportTestBase { @@ -77,9 +71,6 @@ public class ExportServiceTest extends ExportImportTestBase { private AtlasTypeDefStore typeDefStore; @Inject - private EntityGraphMapper graphMapper; - - @Inject ExportService exportService; @Inject @@ -88,9 +79,6 @@ public class ExportServiceTest extends ExportImportTestBase { @Inject private AtlasEntityStoreV2 entityStore; - private DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class);; - private AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class); - @BeforeTest public void setupTest() throws IOException, AtlasBaseException { RequestContext.clear(); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/impexp/ExportSkipLineageTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportSkipLineageTest.java b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportSkipLineageTest.java index 3393b82..28773d5 100644 --- a/repository/src/test/java/org/apache/atlas/repository/impexp/ExportSkipLineageTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/impexp/ExportSkipLineageTest.java @@ -25,8 +25,7 @@ import org.apache.atlas.TestUtilsV2; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.impexp.AtlasExportRequest; import org.apache.atlas.model.instance.AtlasEntity; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.repository.store.graph.v2.AtlasEntityChangeNotifier; import org.apache.atlas.repository.store.graph.v2.AtlasEntityStoreV2; import org.apache.atlas.repository.store.graph.v2.EntityGraphMapper; @@ -65,7 +64,7 @@ public class ExportSkipLineageTest extends ExportImportTestBase { @Inject ExportService exportService; - private DeleteHandlerV1 deleteHandler = mock(SoftDeleteHandlerV1.class); + private DeleteHandlerDelegate deleteDelegate = mock(DeleteHandlerDelegate.class); private AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class); private AtlasEntityStoreV2 entityStore; @@ -74,7 +73,7 @@ public class ExportSkipLineageTest extends ExportImportTestBase { loadBaseModel(typeDefStore, typeRegistry); loadHiveModel(typeDefStore, typeRegistry); - entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper); + entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper); createEntities(entityStore, ENTITIES_SUB_DIR, new String[]{"db", "table-columns", "table-view", "table-table-lineage"}); final String[] entityGuids = {DB_GUID, TABLE_GUID, TABLE_TABLE_GUID, TABLE_VIEW_GUID}; verifyCreatedEntities(entityStore, entityGuids, 4); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftReferenceTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftReferenceTest.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftReferenceTest.java index a860764..2ffc972 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftReferenceTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v1/SoftReferenceTest.java @@ -18,7 +18,9 @@ package org.apache.atlas.repository.store.graph.v1; +import org.apache.atlas.RequestContext; import org.apache.atlas.TestModules; +import org.apache.atlas.TestUtilsV2; import org.apache.atlas.exception.AtlasBaseException; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasObjectId; @@ -32,10 +34,12 @@ import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.v2.AtlasEntityStream; import org.apache.atlas.repository.store.graph.v2.AtlasGraphUtilsV2; import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.utils.TestResourceFileUtils; +import org.testng.annotations.BeforeMethod; import org.testng.annotations.Guice; import org.testng.annotations.Test; @@ -50,7 +54,7 @@ import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; -@Guice(modules = TestModules.SoftDeleteModule.class) +@Guice(modules = TestModules.TestOnlyModule.class) public class SoftReferenceTest { private static final String TYPE_RDBMS_DB = "rdbms_db"; private static final String RDBMS_DB_FILE = "rdbms-db"; @@ -75,6 +79,12 @@ public class SoftReferenceTest { private String dbGuid; private String storageGuid; + @BeforeMethod + public void init() throws Exception { + RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); + RequestContext.get().setDeleteType(DeleteType.SOFT); + } + @Test public void typeCreationFromFile() throws IOException, AtlasBaseException { String typesDefJson = TestResourceFileUtils.getJson(TYPESDEF_FILE_NAME); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2Test.java index 4fd2820..ca46ffd 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityStoreV2Test.java @@ -109,7 +109,7 @@ public class AtlasEntityStoreV2Test extends AtlasEntityTestBase { } @BeforeTest public void init() throws Exception { - entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper); + entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper); RequestContext.clear(); RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityTestBase.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityTestBase.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityTestBase.java index ba05510..368951d 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityTestBase.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasEntityTestBase.java @@ -38,7 +38,7 @@ import org.apache.atlas.repository.graph.GraphBackedSearchIndexer; import org.apache.atlas.repository.graphdb.AtlasGraph; import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer; import org.apache.atlas.repository.store.graph.AtlasEntityStore; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.store.AtlasTypeDefStore; import org.apache.atlas.type.AtlasArrayType; @@ -78,7 +78,7 @@ public class AtlasEntityTestBase { AtlasEntityStore entityStore; @Inject - DeleteHandlerV1 deleteHandler; + DeleteHandlerDelegate deleteDelegate; @Inject private EntityGraphMapper graphMapper; @@ -107,7 +107,7 @@ public class AtlasEntityTestBase { @BeforeTest public void init() throws Exception { - entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper); + entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper); RequestContext.clear(); RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreHardDeleteV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreHardDeleteV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreHardDeleteV2Test.java index 8955be7..623235f 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreHardDeleteV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreHardDeleteV2Test.java @@ -18,11 +18,11 @@ package org.apache.atlas.repository.store.graph.v2; import com.google.common.collect.ImmutableList; -import org.apache.atlas.TestModules; +import org.apache.atlas.RequestContext; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1; -import org.testng.annotations.Guice; +import org.apache.atlas.store.DeleteType; +import org.testng.annotations.BeforeTest; import java.util.List; @@ -32,11 +32,14 @@ import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; /** - * Inverse reference update test with {@link HardDeleteHandlerV1} + * Inverse reference update test with HardDeleteHandlerV1 */ -@Guice(modules = TestModules.HardDeleteModule.class) public class AtlasRelationshipStoreHardDeleteV2Test extends AtlasRelationshipStoreV2Test { + public AtlasRelationshipStoreHardDeleteV2Test() { + super(DeleteType.HARD); + } + @Override protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception { // Max should have been removed from the subordinates list, leaving only John. http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java index 82b75da..b169988 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java @@ -18,11 +18,9 @@ package org.apache.atlas.repository.store.graph.v2; import com.google.common.collect.ImmutableList; -import org.apache.atlas.TestModules; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; -import org.testng.annotations.Guice; +import org.apache.atlas.store.DeleteType; import java.util.List; @@ -32,11 +30,14 @@ import static org.testng.Assert.assertNotNull; /** - * Inverse reference update test with {@link SoftDeleteHandlerV1} + * Inverse reference update test with SoftDeleteHandlerV1 */ -@Guice(modules = TestModules.SoftDeleteModule.class) public class AtlasRelationshipStoreSoftDeleteV2Test extends AtlasRelationshipStoreV2Test { + public AtlasRelationshipStoreSoftDeleteV2Test() { + super(DeleteType.SOFT); + } + @Override protected void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception { // Max is still in the subordinates list, as the edge still exists with state DELETED http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java index cd1d727..a40cf85 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java @@ -35,9 +35,10 @@ import org.apache.atlas.repository.graph.GraphBackedSearchIndexer; import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer; import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.repository.store.graph.AtlasRelationshipStore; -import org.apache.atlas.repository.store.graph.v1.DeleteHandlerV1; +import org.apache.atlas.repository.store.graph.v1.DeleteHandlerDelegate; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.commons.collections.CollectionUtils; @@ -77,7 +78,7 @@ public abstract class AtlasRelationshipStoreV2Test { AtlasTypeDefStore typeDefStore; @Inject - DeleteHandlerV1 deleteHandler; + DeleteHandlerDelegate deleteDelegate; @Inject EntityGraphMapper graphMapper; @@ -88,9 +89,14 @@ public abstract class AtlasRelationshipStoreV2Test { AtlasEntityStore entityStore; AtlasRelationshipStore relationshipStore; AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class); + private final DeleteType deleteType; protected Map<String, AtlasObjectId> employeeNameIdMap = new HashMap<>(); + protected AtlasRelationshipStoreV2Test(DeleteType delteType) { + this.deleteType = delteType; + } + @BeforeClass public void setUp() throws Exception { new GraphBackedSearchIndexer(typeRegistry); @@ -118,11 +124,12 @@ public abstract class AtlasRelationshipStoreV2Test { @BeforeTest public void init() throws Exception { - entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper); - relationshipStore = new AtlasRelationshipStoreV2(typeRegistry, deleteHandler, entityNotifier); + entityStore = new AtlasEntityStoreV2(deleteDelegate, typeRegistry, mockChangeNotifier, graphMapper); + relationshipStore = new AtlasRelationshipStoreV2(typeRegistry, deleteDelegate, entityNotifier); RequestContext.clear(); RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); + RequestContext.get().setDeleteType(deleteType); } @AfterClass http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java index 5d45908..ed72d5f 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java @@ -18,12 +18,10 @@ package org.apache.atlas.repository.store.graph.v2; import com.google.common.collect.ImmutableList; -import org.apache.atlas.TestModules; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.repository.store.graph.v1.HardDeleteHandlerV1; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.type.AtlasTypeUtil; -import org.testng.annotations.Guice; import java.util.Map; @@ -31,11 +29,14 @@ import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; /** - * Inverse reference update test with {@link HardDeleteHandlerV1} + * Inverse reference update test with HardDeleteHandlerV1 */ -@Guice(modules = TestModules.HardDeleteModule.class) public class InverseReferenceUpdateHardDeleteV2Test extends InverseReferenceUpdateV2Test { + public InverseReferenceUpdateHardDeleteV2Test() { + super(DeleteType.HARD); + } + @Override protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception { http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java index 76d6b7d..92d1ddc 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java @@ -18,12 +18,10 @@ package org.apache.atlas.repository.store.graph.v2; import com.google.common.collect.ImmutableList; -import org.apache.atlas.TestModules; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasObjectId; -import org.apache.atlas.repository.store.graph.v1.SoftDeleteHandlerV1; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.type.AtlasTypeUtil; -import org.testng.annotations.Guice; import java.util.Map; @@ -32,11 +30,14 @@ import static org.testng.Assert.assertTrue; /** - * Inverse reference update test with {@link SoftDeleteHandlerV1} + * Inverse reference update test with SoftDeleteHandlerV1 */ -@Guice(modules = TestModules.SoftDeleteModule.class) public class InverseReferenceUpdateSoftDeleteV2Test extends InverseReferenceUpdateV2Test { + public InverseReferenceUpdateSoftDeleteV2Test() { + super(DeleteType.SOFT); + } + @Override protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception { http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java index ea647ec..6364fd4 100644 --- a/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java +++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java @@ -20,6 +20,7 @@ package org.apache.atlas.repository.store.graph.v2; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import org.apache.atlas.RequestContext; +import org.apache.atlas.TestModules; import org.apache.atlas.TestUtilsV2; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo; @@ -33,12 +34,14 @@ import org.apache.atlas.repository.store.bootstrap.AtlasTypeDefStoreInitializer; import org.apache.atlas.repository.store.graph.AtlasEntityStore; import org.apache.atlas.runner.LocalSolrRunner; import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.type.AtlasEntityType; import org.apache.atlas.type.AtlasTypeRegistry; import org.apache.atlas.type.AtlasTypeUtil; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Guice; import org.testng.annotations.Test; import javax.inject.Inject; @@ -58,6 +61,7 @@ import static org.apache.atlas.TestUtilsV2.NAME; * Test automatic inverse reference updating in V1 (V2?) code path. * */ +@Guice(modules = TestModules.TestOnlyModule.class) public abstract class InverseReferenceUpdateV2Test { @Inject AtlasTypeRegistry typeRegistry; @@ -69,9 +73,14 @@ public abstract class InverseReferenceUpdateV2Test { AtlasEntityStore entityStore; private AtlasEntitiesWithExtInfo deptEntity; + private final DeleteType deleteType; protected Map<String, AtlasObjectId> nameIdMap = new HashMap<>(); + protected InverseReferenceUpdateV2Test(DeleteType deleteType) { + this.deleteType = deleteType; + } + @BeforeClass public void setUp() throws Exception { RequestContext.clear(); @@ -110,6 +119,7 @@ public abstract class InverseReferenceUpdateV2Test { public void init() throws Exception { RequestContext.clear(); RequestContext.get().setUser(TestUtilsV2.TEST_USER, null); + RequestContext.get().setDeleteType(deleteType); } @Test http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/server-api/src/main/java/org/apache/atlas/RequestContext.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/RequestContext.java b/server-api/src/main/java/org/apache/atlas/RequestContext.java index 9a9bba6..b49591d 100644 --- a/server-api/src/main/java/org/apache/atlas/RequestContext.java +++ b/server-api/src/main/java/org/apache/atlas/RequestContext.java @@ -22,6 +22,7 @@ import org.apache.atlas.model.instance.AtlasClassification; import org.apache.atlas.model.instance.AtlasEntity; import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo; import org.apache.atlas.model.instance.AtlasObjectId; +import org.apache.atlas.store.DeleteType; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -34,20 +35,21 @@ public class RequestContext { private static final ThreadLocal<RequestContext> CURRENT_CONTEXT = new ThreadLocal<>(); private static final Set<RequestContext> ACTIVE_REQUESTS = new HashSet<>(); + private final long requestTime = System.currentTimeMillis(); private final Map<String, AtlasObjectId> updatedEntities = new HashMap<>(); private final Map<String, AtlasObjectId> deletedEntities = new HashMap<>(); private final Map<String, AtlasEntity> entityCache = new HashMap<>(); private final Map<String, AtlasEntityWithExtInfo> entityExtInfoCache = new HashMap<>(); private final Map<String, List<AtlasClassification>> addedPropagations = new HashMap<>(); private final Map<String, List<AtlasClassification>> removedPropagations = new HashMap<>(); - private final long requestTime = System.currentTimeMillis(); private List<EntityGuidPair> entityGuidInRequest = null; private String user; private Set<String> userGroups; - private String clientIPAddress; - private int maxAttempts = 1; - private int attemptCount = 1; + private String clientIPAddress; + private DeleteType deleteType = DeleteType.DEFAULT; + private int maxAttempts = 1; + private int attemptCount = 1; private RequestContext() { @@ -74,16 +76,7 @@ public class RequestContext { RequestContext instance = CURRENT_CONTEXT.get(); if (instance != null) { - instance.updatedEntities.clear(); - instance.deletedEntities.clear(); - instance.entityCache.clear(); - instance.entityExtInfoCache.clear(); - instance.addedPropagations.clear(); - instance.removedPropagations.clear(); - - if (instance.entityGuidInRequest != null) { - instance.entityGuidInRequest.clear(); - } + instance.clearCache(); synchronized (ACTIVE_REQUESTS) { ACTIVE_REQUESTS.remove(instance); @@ -93,6 +86,19 @@ public class RequestContext { CURRENT_CONTEXT.remove(); } + public void clearCache() { + this.updatedEntities.clear(); + this.deletedEntities.clear(); + this.entityCache.clear(); + this.entityExtInfoCache.clear(); + this.addedPropagations.clear(); + this.removedPropagations.clear(); + + if (this.entityGuidInRequest != null) { + this.entityGuidInRequest.clear(); + } + } + public static String getCurrentUser() { RequestContext context = CURRENT_CONTEXT.get(); return context != null ? context.getUser() : null; @@ -111,6 +117,10 @@ public class RequestContext { this.userGroups = userGroups; } + public DeleteType getDeleteType() { return deleteType; } + + public void setDeleteType(DeleteType deleteType) { this.deleteType = (deleteType == null) ? DeleteType.DEFAULT : deleteType; } + public String getClientIPAddress() { return clientIPAddress; } @@ -162,12 +172,6 @@ public class RequestContext { } } - public static RequestContext createContext() { - clear(); - - return get(); - } - public static int getActiveRequestsCount() { return ACTIVE_REQUESTS.size(); } http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java ---------------------------------------------------------------------- diff --git a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java index adf3cf2..54f7330 100755 --- a/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java +++ b/webapp/src/main/java/org/apache/atlas/web/filters/AuditFilter.java @@ -22,10 +22,12 @@ import org.apache.atlas.AtlasClient; import org.apache.atlas.AtlasException; import org.apache.atlas.RequestContext; import org.apache.atlas.authorize.AtlasAuthorizationUtils; +import org.apache.atlas.store.DeleteType; import org.apache.atlas.util.AtlasRepositoryConfiguration; import org.apache.atlas.web.util.DateTimeHelper; import org.apache.atlas.web.util.Servlets; import org.apache.commons.configuration.Configuration; +import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; @@ -43,6 +45,8 @@ import java.util.Date; import java.util.Set; import java.util.UUID; +import static org.apache.atlas.AtlasConfiguration.REST_API_ENABLE_DELETE_TYPE_OVERRIDE; + /** * This records audit information as part of the filter after processing the request * and also introduces a UUID into request and response for tracing requests in logs. @@ -52,9 +56,15 @@ public class AuditFilter implements Filter { private static final Logger LOG = LoggerFactory.getLogger(AuditFilter.class); private static final Logger AUDIT_LOG = LoggerFactory.getLogger("AUDIT"); + private boolean deleteTypeOverrideEnabled = false; + @Override public void init(FilterConfig filterConfig) throws ServletException { LOG.info("AuditFilter initialization started"); + + deleteTypeOverrideEnabled = REST_API_ENABLE_DELETE_TYPE_OVERRIDE.getBoolean(); + + LOG.info("REST_API_ENABLE_DELETE_TYPE_OVERRIDE={}", deleteTypeOverrideEnabled); } @Override @@ -69,6 +79,7 @@ public class AuditFilter implements Filter { final String oldName = currentThread.getName(); final String user = AtlasAuthorizationUtils.getCurrentUserName(); final Set<String> userGroups = AtlasAuthorizationUtils.getCurrentUserGroups(); + final String deleteType = httpRequest.getParameter("deleteType"); try { currentThread.setName(formatName(oldName, requestId)); @@ -77,6 +88,15 @@ public class AuditFilter implements Filter { RequestContext requestContext = RequestContext.get(); requestContext.setUser(user, userGroups); requestContext.setClientIPAddress(AtlasAuthorizationUtils.getRequestIpAddress(httpRequest)); + + if (StringUtils.isNotEmpty(deleteType)) { + if (deleteTypeOverrideEnabled) { + requestContext.setDeleteType(DeleteType.from(deleteType)); + } else { + LOG.warn("Override of deleteType is not enabled. Ignoring parameter deleteType={}, in request from user={}", deleteType, user); + } + } + filterChain.doFilter(request, response); } finally { long timeTaken = System.currentTimeMillis() - startTime; http://git-wip-us.apache.org/repos/asf/atlas/blob/7869c9a5/webapp/src/test/java/org/apache/atlas/web/adapters/TestEntityRESTDelete.java ---------------------------------------------------------------------- diff --git a/webapp/src/test/java/org/apache/atlas/web/adapters/TestEntityRESTDelete.java b/webapp/src/test/java/org/apache/atlas/web/adapters/TestEntityRESTDelete.java new file mode 100644 index 0000000..02e78f4 --- /dev/null +++ b/webapp/src/test/java/org/apache/atlas/web/adapters/TestEntityRESTDelete.java @@ -0,0 +1,207 @@ +/** + * 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 + * <p> + * http://www.apache.org/licenses/LICENSE-2.0 + * <p> + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.atlas.web.adapters; + +import org.apache.atlas.RequestContext; +import org.apache.atlas.TestModules; +import org.apache.atlas.TestUtilsV2; +import org.apache.atlas.exception.AtlasBaseException; +import org.apache.atlas.model.instance.AtlasEntity; +import org.apache.atlas.model.instance.AtlasEntityHeader; +import org.apache.atlas.model.instance.EntityMutationResponse; +import org.apache.atlas.model.instance.EntityMutations; +import org.apache.atlas.model.typedef.AtlasTypesDef; +import org.apache.atlas.store.AtlasTypeDefStore; +import org.apache.atlas.store.DeleteType; +import org.apache.atlas.web.rest.EntityREST; +import org.mockito.Mockito; +import org.testng.Assert; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Guice; +import org.testng.annotations.Test; + +import javax.inject.Inject; +import javax.servlet.http.HttpServletRequest; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static org.testng.Assert.assertNotNull; +import static org.testng.AssertJUnit.assertTrue; +import static org.testng.FileAssert.fail; + +@Guice(modules = {TestModules.TestOnlyModule.class}) +public class TestEntityRESTDelete { + + @Inject + private AtlasTypeDefStore typeStore; + + @Inject + private EntityREST entityREST; + + private List<AtlasEntity> dbEntities = new ArrayList<>(); + + @BeforeClass + public void setUp() throws Exception { + AtlasTypesDef typesDef = TestUtilsV2.defineHiveTypes(); + typeStore.createTypesDef(typesDef); + } + + @AfterMethod + public void cleanup() { + RequestContext.clear(); + } + + private void assertSoftDelete(String guid) throws AtlasBaseException { + AtlasEntity.AtlasEntityWithExtInfo entity = entityREST.getById(guid, false); + assertTrue(entity != null && entity.getEntity().getStatus() == AtlasEntity.Status.DELETED); + } + + private void assertHardDelete(String guid) { + try { + entityREST.getById(guid, false); + fail("Entity should have been deleted. Exception should have been thrown."); + } catch (AtlasBaseException e) { + assertTrue(true); + } + } + + private void createEntities() throws Exception { + dbEntities.clear(); + + for (int i = 1; i <= 2; i++) { + AtlasEntity dbEntity = TestUtilsV2.createDBEntity(); + + final EntityMutationResponse response = entityREST.createOrUpdate(new AtlasEntity.AtlasEntitiesWithExtInfo(dbEntity)); + + assertNotNull(response); + List<AtlasEntityHeader> entitiesMutated = response.getEntitiesByOperation(EntityMutations.EntityOperation.CREATE); + + assertNotNull(entitiesMutated); + Assert.assertEquals(entitiesMutated.size(), 1); + assertNotNull(entitiesMutated.get(0)); + dbEntity.setGuid(entitiesMutated.get(0).getGuid()); + + dbEntities.add(dbEntity); + } + } + + @Test + public void deleteByGuidTestSoft() throws Exception { + RequestContext.get().setDeleteType(DeleteType.SOFT); + + createEntities(); + + EntityMutationResponse response = entityREST.deleteByGuid(dbEntities.get(0).getGuid()); + + assertNotNull(response); + assertNotNull(response.getDeletedEntities()); + assertSoftDelete(dbEntities.get(0).getGuid()); + } + + @Test + public void deleteByGuidTestHard() throws Exception { + RequestContext.get().setDeleteType(DeleteType.HARD); + + createEntities(); + EntityMutationResponse response = entityREST.deleteByGuid(dbEntities.get(0).getGuid()); + + assertNotNull(response); + assertNotNull(response.getDeletedEntities()); + assertHardDelete(dbEntities.get(0).getGuid()); + } + + + @Test + public void deleteByGuidsSoft() throws Exception { + RequestContext.get().setDeleteType(DeleteType.SOFT); + + createEntities(); + List<String> guids = new ArrayList<>(); + guids.add(dbEntities.get(0).getGuid()); + guids.add(dbEntities.get(1).getGuid()); + + EntityMutationResponse response = entityREST.deleteByGuids(guids); + + assertNotNull(response); + assertNotNull(response.getDeletedEntities()); + + for (String guid : guids) { + assertSoftDelete(guid); + } + } + + @Test + public void deleteByGuidsHard() throws Exception { + RequestContext.get().setDeleteType(DeleteType.HARD); + + createEntities(); + List<String> guids = new ArrayList<>(); + guids.add(dbEntities.get(0).getGuid()); + guids.add(dbEntities.get(1).getGuid()); + EntityMutationResponse response = entityREST.deleteByGuids(guids); + + assertNotNull(response); + assertNotNull(response.getDeletedEntities()); + + for (String guid : guids) { + assertHardDelete(guid); + } + } + + @Test + public void testUpdateGetDeleteEntityByUniqueAttributeSoft() throws Exception { + RequestContext.get().setDeleteType(DeleteType.SOFT); + + createEntities(); + entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, + (String) dbEntities.get(0).getAttribute(TestUtilsV2.NAME))); + + assertSoftDelete(dbEntities.get(0).getGuid()); + } + + @Test + public void testUpdateGetDeleteEntityByUniqueAttributeHard() throws Exception { + RequestContext.get().setDeleteType(DeleteType.HARD); + + createEntities(); + + entityREST.deleteByUniqueAttribute(TestUtilsV2.DATABASE_TYPE, toHttpServletRequest(TestUtilsV2.NAME, + (String) dbEntities.get(0).getAttribute(TestUtilsV2.NAME))); + + assertHardDelete(dbEntities.get(0).getGuid()); + } + + private HttpServletRequest toHttpServletRequest(String attrName, String attrValue) { + HttpServletRequest request = Mockito.mock(HttpServletRequest.class); + Map<String, String[]> paramsMap = toParametersMap(EntityREST.PREFIX_ATTR + attrName, attrValue); + + Mockito.when(request.getParameterMap()).thenReturn(paramsMap); + + return request; + } + + private Map<String, String[]> toParametersMap(final String name, final String value) { + return new HashMap<String, String[]>() {{ + put(name, new String[]{value}); + }}; + } +} \ No newline at end of file