| /** |
| * 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.repository.store.graph.v1; |
| |
| |
| import org.apache.atlas.AtlasClient; |
| import org.apache.atlas.TestModules; |
| 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.AtlasObjectId; |
| import org.apache.atlas.repository.Constants; |
| import org.apache.atlas.repository.graph.GraphHelper; |
| import org.apache.atlas.repository.graphdb.AtlasVertex; |
| import org.apache.atlas.services.MetadataService; |
| import org.apache.atlas.typesystem.IReferenceableInstance; |
| import org.apache.atlas.typesystem.IStruct; |
| import org.apache.atlas.typesystem.ITypedReferenceableInstance; |
| import org.apache.atlas.typesystem.ITypedStruct; |
| import org.apache.atlas.typesystem.persistence.Id; |
| import org.testng.Assert; |
| import org.testng.annotations.Guice; |
| |
| import javax.inject.Inject; |
| import java.util.List; |
| import java.util.Map; |
| |
| import static org.apache.atlas.TestUtils.COLUMNS_ATTR_NAME; |
| import static org.apache.atlas.TestUtils.NAME; |
| import static org.testng.Assert.assertEquals; |
| import static org.testng.Assert.assertNotNull; |
| |
| @Guice(modules = TestModules.SoftDeleteModule.class) |
| public class SoftDeleteHandlerV1Test extends AtlasDeleteHandlerV1Test { |
| |
| @Inject |
| MetadataService metadataService; |
| |
| @Override |
| protected void assertDeletedColumn(final AtlasEntity.AtlasEntityWithExtInfo tableInstance) throws AtlasBaseException { |
| final List<AtlasObjectId> columns = (List<AtlasObjectId>) tableInstance.getEntity().getAttribute(COLUMNS_ATTR_NAME); |
| Assert.assertEquals(columns.size(), 3); |
| |
| final AtlasEntity.AtlasEntityWithExtInfo colDeleted = entityStore.getById(columns.get(0).getGuid()); |
| assertEquals(colDeleted.getEntity().getStatus(), AtlasEntity.Status.DELETED); |
| } |
| |
| @Override |
| protected void assertTestDeleteEntities(final AtlasEntity.AtlasEntityWithExtInfo tableInstance) throws Exception { |
| //Assert that the deleted table can be fully constructed back |
| List<IReferenceableInstance> columns = (List<IReferenceableInstance>) tableInstance.getEntity().getAttribute(COLUMNS_ATTR_NAME); |
| assertEquals(columns.size(), 3); |
| assertNotNull(tableInstance.getEntity().getAttribute("database")); |
| } |
| |
| @Override |
| protected void assertTableForTestDeleteReference(final String tableId) throws Exception { |
| |
| ITypedReferenceableInstance table = metadataService.getEntityDefinition(tableId); |
| assertNotNull(table.get(NAME)); |
| assertNotNull(table.get("description")); |
| assertNotNull(table.get("type")); |
| assertNotNull(table.get("tableType")); |
| assertNotNull(table.get("created")); |
| |
| Id dbId = (Id) table.get("database"); |
| assertNotNull(dbId); |
| |
| ITypedReferenceableInstance db = metadataService.getEntityDefinition(dbId.getId()._getId()); |
| assertNotNull(db); |
| assertEquals(db.getId().getState(), Id.EntityState.ACTIVE); |
| |
| } |
| |
| @Override |
| protected void assertColumnForTestDeleteReference(final AtlasEntity.AtlasEntityWithExtInfo tableInstance) throws AtlasBaseException { |
| List<AtlasObjectId> columns = (List<AtlasObjectId>) tableInstance.getEntity().getAttribute(COLUMNS_ATTR_NAME); |
| assertEquals(columns.size(), 1); |
| |
| final AtlasEntity.AtlasEntityWithExtInfo byId = entityStore.getById(columns.get(0).getGuid()); |
| assertEquals(byId.getEntity().getStatus(), AtlasEntity.Status.DELETED); |
| } |
| |
| @Override |
| protected void assertProcessForTestDeleteReference(final AtlasEntityHeader processInstance) throws Exception { |
| // |
| ITypedReferenceableInstance process = metadataService.getEntityDefinition(processInstance.getGuid()); |
| List<ITypedReferenceableInstance> outputs = |
| (List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS); |
| List<ITypedReferenceableInstance> expectedOutputs = |
| (List<ITypedReferenceableInstance>) process.get(AtlasClient.PROCESS_ATTRIBUTE_OUTPUTS); |
| assertEquals(outputs.size(), expectedOutputs.size()); |
| |
| } |
| |
| @Override |
| protected void assertEntityDeleted(final String id) throws Exception { |
| final AtlasEntity.AtlasEntityWithExtInfo byId = entityStore.getById(id); |
| assertEquals(byId.getEntity().getStatus(), AtlasEntity.Status.DELETED); |
| } |
| |
| @Override |
| protected void assertTestUpdateEntity_MultiplicityOneNonCompositeReference(final String janeGuid) throws Exception { |
| // Verify Jane's subordinates reference cardinality is still 2. |
| ITypedReferenceableInstance jane = metadataService.getEntityDefinition(janeGuid); |
| List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates"); |
| Assert.assertEquals(subordinates.size(), 2); |
| } |
| |
| @Override |
| protected void assertJohnForTestDisconnectBidirectionalReferences(final AtlasEntity.AtlasEntityWithExtInfo john, final String janeGuid) throws Exception { |
| AtlasObjectId mgr = (AtlasObjectId) john.getEntity().getAttribute("manager"); |
| assertNotNull(mgr); |
| assertEquals(mgr.getGuid(), janeGuid); |
| |
| |
| final AtlasEntity.AtlasEntityWithExtInfo mgrEntity = entityStore.getById(mgr.getGuid()); |
| assertEquals(mgrEntity.getEntity().getStatus(), AtlasEntity.Status.DELETED); |
| } |
| |
| @Override |
| protected void assertMaxForTestDisconnectBidirectionalReferences(final Map<String, String> nameGuidMap) throws Exception { |
| |
| // Verify that the Department.employees reference to the deleted employee |
| // was disconnected. |
| ITypedReferenceableInstance hrDept = metadataService.getEntityDefinition(nameGuidMap.get("hr")); |
| List<ITypedReferenceableInstance> employees = (List<ITypedReferenceableInstance>) hrDept.get("employees"); |
| Assert.assertEquals(employees.size(), 4); |
| String maxGuid = nameGuidMap.get("Max"); |
| for (ITypedReferenceableInstance employee : employees) { |
| if (employee.getId()._getId().equals(maxGuid)) { |
| assertEquals(employee.getId().getState(), Id.EntityState.DELETED); |
| } |
| } |
| |
| // Verify that the Manager.subordinates still references deleted employee |
| ITypedReferenceableInstance jane = metadataService.getEntityDefinition(nameGuidMap.get("Jane")); |
| List<ITypedReferenceableInstance> subordinates = (List<ITypedReferenceableInstance>) jane.get("subordinates"); |
| assertEquals(subordinates.size(), 2); |
| for (ITypedReferenceableInstance subordinate : subordinates) { |
| if (subordinate.getId()._getId().equals(maxGuid)) { |
| assertEquals(subordinate.getId().getState(), Id.EntityState.DELETED); |
| } |
| } |
| |
| // Verify that max's Person.mentor unidirectional reference to john was disconnected. |
| ITypedReferenceableInstance john = metadataService.getEntityDefinition(nameGuidMap.get("John")); |
| Id mentor = (Id) john.get("mentor"); |
| assertEquals(mentor._getId(), maxGuid); |
| assertEquals(mentor.getState(), Id.EntityState.DELETED); |
| |
| } |
| |
| @Override |
| protected void assertTestDisconnectUnidirectionalArrayReferenceFromClassType(final List<AtlasObjectId> columns, final String columnGuid) throws AtlasBaseException { |
| Assert.assertEquals(columns.size(), 3); |
| for (AtlasObjectId column : columns) { |
| AtlasEntity.AtlasEntityWithExtInfo columnEntity = entityStore.getById(column.getGuid()); |
| if (column.getGuid().equals(columnGuid)) { |
| assertEquals(columnEntity.getEntity().getStatus(), AtlasEntity.Status.DELETED); |
| } else { |
| assertEquals(columnEntity.getEntity().getStatus(), AtlasEntity.Status.ACTIVE); |
| } |
| } |
| } |
| |
| @Override |
| protected void assertTestDisconnectMapReferenceFromClassType(final String mapOwnerGuid) throws Exception { |
| AtlasEntity.AtlasEntityWithExtInfo mapOwnerInstance = entityStore.getById(mapOwnerGuid); |
| Map<String, AtlasObjectId> map = |
| (Map<String, AtlasObjectId>) mapOwnerInstance.getEntity().getAttribute("map"); |
| assertNotNull(map); |
| assertEquals(map.size(), 1); |
| Map<String, AtlasObjectId> biMap = |
| (Map<String, AtlasObjectId>) mapOwnerInstance.getEntity().getAttribute("biMap"); |
| assertNotNull(biMap); |
| assertEquals(biMap.size(), 1); |
| } |
| |
| @Override |
| protected void assertTestDisconnectUnidirectionalArrayReferenceFromStructAndTraitTypes(final String structContainerGuid) throws Exception { |
| // Verify that the unidirectional references from the struct and trait instances |
| // to the deleted entities were not disconnected. |
| ITypedReferenceableInstance structContainerConvertedEntity = |
| metadataService.getEntityDefinition(structContainerGuid); |
| ITypedStruct struct = (ITypedStruct) structContainerConvertedEntity.get("struct"); |
| assertNotNull(struct.get("target")); |
| IStruct trait = structContainerConvertedEntity.getTrait("TestTrait"); |
| assertNotNull(trait); |
| assertNotNull(trait.get("target")); |
| |
| } |
| |
| @Override |
| protected void assertVerticesDeleted(List<AtlasVertex> vertices) { |
| for (AtlasVertex vertex : vertices) { |
| assertEquals(GraphHelper.getSingleValuedProperty(vertex, Constants.STATE_PROPERTY_KEY, String.class), Id.EntityState.DELETED.name()); |
| } |
| } |
| } |