You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by ap...@apache.org on 2018/05/25 03:52:40 UTC
[02/20] atlas git commit: ATLAS-2490: updates to make usage of v1/v2
in class names consistent
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..82b75da
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreSoftDeleteV2Test.java
@@ -0,0 +1,117 @@
+/**
+ * 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.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 java.util.List;
+
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+
+/**
+ * Inverse reference update test with {@link SoftDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.SoftDeleteModule.class)
+public class AtlasRelationshipStoreSoftDeleteV2Test extends AtlasRelationshipStoreV2Test {
+
+ @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
+ verifyRelationshipAttributeList(jane, "subordinates", ImmutableList.of(employeeNameIdMap.get("John"), employeeNameIdMap.get("Max")));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2,
+ AtlasEntity a3, AtlasEntity b) {
+
+ verifyRelationshipAttributeValue(a1, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeValue(a2, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeList(b, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2), getAtlasObjectId(a3)));
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+ verifyRelationshipAttributeValue(a1, "b", b.getGuid());
+ }
+
+ @Override
+ protected void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity max, AtlasEntity julius, AtlasEntity mike, AtlasEntity john) throws Exception {
+ AtlasObjectId johnId = employeeNameIdMap.get("John");
+ AtlasObjectId mikeId = employeeNameIdMap.get("Mike");
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId maxId = employeeNameIdMap.get("Max");
+
+ // Max's updated friends: [Julius, John, Mike(soft deleted)]
+ List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+ assertNotNull(maxFriendsIds);
+ assertEquals(maxFriendsIds.size(), 3);
+ assertObjectIdsContains(maxFriendsIds, johnId);
+ assertObjectIdsContains(maxFriendsIds, juliusId);
+ assertObjectIdsContains(maxFriendsIds, mikeId);
+
+ // Julius's updated friends: [Max]
+ List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+ assertNotNull(juliusFriendsIds);
+ assertEquals(juliusFriendsIds.size(), 1);
+ assertObjectIdsContains(juliusFriendsIds, maxId);
+
+ // Mike's updated friends: [John, Max(soft deleted)]
+ List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+ assertNotNull(mikeFriendsIds);
+ assertEquals(mikeFriendsIds.size(), 2);
+ assertObjectIdsContains(mikeFriendsIds, johnId);
+ assertObjectIdsContains(mikeFriendsIds, maxId);
+
+ // John's updated friends: [Max, Mike]
+ List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+ assertNotNull(johnFriendsIds);
+ assertEquals(johnFriendsIds.size(), 2);
+ assertObjectIdsContains(johnFriendsIds, maxId);
+ assertObjectIdsContains(johnFriendsIds, mikeId);
+ }
+
+ protected void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity julius, AtlasEntity jane, AtlasEntity mike) throws Exception {
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId mikeId = employeeNameIdMap.get("Mike");
+
+ // Julius sibling updated to Mike
+ AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+ assertNotNull(juliusSiblingId);
+ assertObjectIdEquals(juliusSiblingId, mikeId);
+
+ // Mike's sibling is Julius
+ AtlasObjectId mikeSiblingId = toAtlasObjectId(mike.getRelationshipAttribute("sibling"));
+ assertNotNull(mikeSiblingId);
+ assertObjectIdEquals(mikeSiblingId, juliusId);
+
+ // Jane's sibling is still Julius (soft delete)
+ AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+ assertNotNull(janeSiblingId);
+ assertObjectIdEquals(janeSiblingId, juliusId);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..cd1d727
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/AtlasRelationshipStoreV2Test.java
@@ -0,0 +1,633 @@
+/**
+ * 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.v2;
+
+import com.google.common.collect.ImmutableList;
+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.AtlasEntity.AtlasEntitiesWithExtInfo;
+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;
+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.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.runner.LocalSolrRunner;
+import org.apache.atlas.store.AtlasTypeDefStore;
+import org.apache.atlas.type.AtlasEntityType;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.commons.collections.CollectionUtils;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Guice;
+import org.testng.annotations.Test;
+
+import javax.inject.Inject;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.atlas.TestRelationshipUtilsV2.EMPLOYEE_TYPE;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeInstances;
+import static org.apache.atlas.TestRelationshipUtilsV2.getDepartmentEmployeeTypes;
+import static org.apache.atlas.TestRelationshipUtilsV2.getInverseReferenceTestTypes;
+import static org.apache.atlas.TestUtilsV2.NAME;
+import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr;
+import static org.apache.atlas.type.AtlasTypeUtil.getAtlasObjectId;
+import static org.mockito.Mockito.mock;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+@Guice(modules = TestModules.TestOnlyModule.class)
+public abstract class AtlasRelationshipStoreV2Test {
+
+ @Inject
+ AtlasTypeRegistry typeRegistry;
+
+ @Inject
+ AtlasTypeDefStore typeDefStore;
+
+ @Inject
+ DeleteHandlerV1 deleteHandler;
+
+ @Inject
+ EntityGraphMapper graphMapper;
+
+ @Inject
+ AtlasEntityChangeNotifier entityNotifier;
+
+ AtlasEntityStore entityStore;
+ AtlasRelationshipStore relationshipStore;
+ AtlasEntityChangeNotifier mockChangeNotifier = mock(AtlasEntityChangeNotifier.class);
+
+ protected Map<String, AtlasObjectId> employeeNameIdMap = new HashMap<>();
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ new GraphBackedSearchIndexer(typeRegistry);
+
+ // create employee relationship types
+ AtlasTypesDef employeeTypes = getDepartmentEmployeeTypes();
+ typeDefStore.createTypesDef(employeeTypes);
+
+ AtlasEntitiesWithExtInfo employeeInstances = getDepartmentEmployeeInstances();
+ EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(employeeInstances), false);
+
+ for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
+ employeeNameIdMap.put((String) entityHeader.getAttribute(NAME), getAtlasObjectId(entityHeader));
+ }
+
+ init();
+ AtlasTypesDef typesDef = getInverseReferenceTestTypes();
+
+ AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+
+ if (!typesToCreate.isEmpty()) {
+ typeDefStore.createTypesDef(typesToCreate);
+ }
+ }
+
+ @BeforeTest
+ public void init() throws Exception {
+ entityStore = new AtlasEntityStoreV2(deleteHandler, typeRegistry, mockChangeNotifier, graphMapper);
+ relationshipStore = new AtlasRelationshipStoreV2(typeRegistry, deleteHandler, entityNotifier);
+
+ RequestContext.clear();
+ RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
+ }
+
+ @AfterClass
+ public void clear() throws Exception {
+ AtlasGraphProvider.cleanup();
+
+ if (useLocalSolr()) {
+ LocalSolrRunner.stop();
+ }
+ }
+
+ @Test
+ public void testDepartmentEmployeeEntitiesUsingRelationship() throws Exception {
+ AtlasObjectId hrId = employeeNameIdMap.get("hr");
+ AtlasObjectId maxId = employeeNameIdMap.get("Max");
+ AtlasObjectId johnId = employeeNameIdMap.get("John");
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId janeId = employeeNameIdMap.get("Jane");
+ AtlasObjectId mikeId = employeeNameIdMap.get("Mike");
+
+ AtlasEntity hrDept = getEntityFromStore(hrId.getGuid());
+ AtlasEntity max = getEntityFromStore(maxId.getGuid());
+ AtlasEntity john = getEntityFromStore(johnId.getGuid());
+ AtlasEntity julius = getEntityFromStore(juliusId.getGuid());
+ AtlasEntity jane = getEntityFromStore(janeId.getGuid());
+ AtlasEntity mike = getEntityFromStore(mikeId.getGuid());
+
+ // Department relationship attributes
+ List<AtlasObjectId> deptEmployees = toAtlasObjectIds(hrDept.getRelationshipAttribute("employees"));
+ assertNotNull(deptEmployees);
+ assertEquals(deptEmployees.size(), 5);
+ assertObjectIdsContains(deptEmployees, maxId);
+ assertObjectIdsContains(deptEmployees, johnId);
+ assertObjectIdsContains(deptEmployees, juliusId);
+ assertObjectIdsContains(deptEmployees, janeId);
+ assertObjectIdsContains(deptEmployees, mikeId);
+
+ // Max employee validation
+ AtlasObjectId maxDepartmentId = toAtlasObjectId(max.getRelationshipAttribute("department"));
+ assertNotNull(maxDepartmentId);
+ assertObjectIdEquals(maxDepartmentId, hrId);
+
+ AtlasObjectId maxManagerId = toAtlasObjectId(max.getRelationshipAttribute("manager"));
+ assertNotNull(maxManagerId);
+ assertObjectIdEquals(maxManagerId, janeId);
+
+ List<AtlasObjectId> maxMentorsId = toAtlasObjectIds(max.getRelationshipAttribute("mentors"));
+ assertNotNull(maxMentorsId);
+ assertEquals(maxMentorsId.size(), 1);
+ assertObjectIdEquals(maxMentorsId.get(0), juliusId);
+
+ List<AtlasObjectId> maxMenteesId = toAtlasObjectIds(max.getRelationshipAttribute("mentees"));
+ assertNotNull(maxMenteesId);
+ assertEquals(maxMenteesId.size(), 1);
+ assertObjectIdEquals(maxMenteesId.get(0), johnId);
+
+ List<AtlasObjectId> maxFriendsIds = toAtlasObjectIds(max.getRelationshipAttribute("friends"));
+ assertNotNull(maxFriendsIds);
+ assertEquals(maxFriendsIds.size(), 2);
+ assertObjectIdsContains(maxFriendsIds, mikeId);
+ assertObjectIdsContains(maxFriendsIds, johnId);
+
+ // John Employee validation
+ AtlasObjectId johnDepartmentId = toAtlasObjectId(john.getRelationshipAttribute("department"));
+ assertNotNull(johnDepartmentId);
+ assertObjectIdEquals(johnDepartmentId, hrId);
+
+ AtlasObjectId johnManagerId = toAtlasObjectId(john.getRelationshipAttribute("manager"));
+ assertNotNull(johnManagerId);
+ assertObjectIdEquals(johnManagerId, janeId);
+
+ List<AtlasObjectId> johnMentorIds = toAtlasObjectIds(john.getRelationshipAttribute("mentors"));
+ assertNotNull(johnMentorIds);
+ assertEquals(johnMentorIds.size(), 2);
+ assertObjectIdsContains(johnMentorIds, maxId);
+ assertObjectIdsContains(johnMentorIds, juliusId);
+
+ List<AtlasObjectId> johnMenteesId = toAtlasObjectIds(john.getRelationshipAttribute("mentees"));
+ assertEmpty(johnMenteesId);
+
+ List<AtlasObjectId> johnFriendsIds = toAtlasObjectIds(john.getRelationshipAttribute("friends"));
+ assertNotNull(johnFriendsIds);
+ assertEquals(johnFriendsIds.size(), 2);
+ assertObjectIdsContains(johnFriendsIds, mikeId);
+ assertObjectIdsContains(johnFriendsIds, maxId);
+
+ // Mike Employee validation
+ AtlasObjectId mikeDepartmentId = toAtlasObjectId(mike.getRelationshipAttribute("department"));
+ assertNotNull(mikeDepartmentId);
+ assertObjectIdEquals(mikeDepartmentId, hrId);
+
+ AtlasObjectId mikeManagerId = toAtlasObjectId(mike.getRelationshipAttribute("manager"));
+ assertNotNull(mikeManagerId);
+ assertObjectIdEquals(mikeManagerId, juliusId);
+
+ List<AtlasObjectId> mikeMentorIds = toAtlasObjectIds(mike.getRelationshipAttribute("mentors"));
+ assertEmpty(mikeMentorIds);
+
+ List<AtlasObjectId> mikeMenteesId = toAtlasObjectIds(mike.getRelationshipAttribute("mentees"));
+ assertEmpty(mikeMenteesId);
+
+ List<AtlasObjectId> mikeFriendsIds = toAtlasObjectIds(mike.getRelationshipAttribute("friends"));
+ assertNotNull(mikeFriendsIds);
+ assertEquals(mikeFriendsIds.size(), 2);
+ assertObjectIdsContains(mikeFriendsIds, maxId);
+ assertObjectIdsContains(mikeFriendsIds, johnId);
+
+ // Jane Manager validation
+ AtlasObjectId janeDepartmentId = toAtlasObjectId(jane.getRelationshipAttribute("department"));
+ assertNotNull(janeDepartmentId);
+ assertObjectIdEquals(janeDepartmentId, hrId);
+
+ AtlasObjectId janeManagerId = toAtlasObjectId(jane.getRelationshipAttribute("manager"));
+ assertNull(janeManagerId);
+
+ List<AtlasObjectId> janeMentorIds = toAtlasObjectIds(jane.getRelationshipAttribute("mentors"));
+ assertEmpty(janeMentorIds);
+
+ List<AtlasObjectId> janeMenteesId = toAtlasObjectIds(jane.getRelationshipAttribute("mentees"));
+ assertEmpty(janeMenteesId);
+
+ List<AtlasObjectId> janeSubordinateIds = toAtlasObjectIds(jane.getRelationshipAttribute("subordinates"));
+ assertNotNull(janeSubordinateIds);
+ assertEquals(janeSubordinateIds.size(), 2);
+ assertObjectIdsContains(janeSubordinateIds, maxId);
+ assertObjectIdsContains(janeSubordinateIds, johnId);
+
+ List<AtlasObjectId> janeFriendsIds = toAtlasObjectIds(jane.getRelationshipAttribute("friends"));
+ assertEmpty(janeFriendsIds);
+
+ AtlasObjectId janeSiblingId = toAtlasObjectId(jane.getRelationshipAttribute("sibling"));
+ assertNotNull(janeSiblingId);
+ assertObjectIdEquals(janeSiblingId, juliusId);
+
+ // Julius Manager validation
+ AtlasObjectId juliusDepartmentId = toAtlasObjectId(julius.getRelationshipAttribute("department"));
+ assertNotNull(juliusDepartmentId);
+ assertObjectIdEquals(juliusDepartmentId, hrId);
+
+ AtlasObjectId juliusManagerId = toAtlasObjectId(julius.getRelationshipAttribute("manager"));
+ assertNull(juliusManagerId);
+
+ List<AtlasObjectId> juliusMentorIds = toAtlasObjectIds(julius.getRelationshipAttribute("mentors"));
+ assertEmpty(juliusMentorIds);
+
+ List<AtlasObjectId> juliusMenteesId = toAtlasObjectIds(julius.getRelationshipAttribute("mentees"));
+ assertNotNull(juliusMenteesId);
+ assertEquals(juliusMenteesId.size(), 2);
+ assertObjectIdsContains(juliusMenteesId, maxId);
+ assertObjectIdsContains(juliusMenteesId, johnId);
+
+ List<AtlasObjectId> juliusSubordinateIds = toAtlasObjectIds(julius.getRelationshipAttribute("subordinates"));
+ assertNotNull(juliusSubordinateIds);
+ assertEquals(juliusSubordinateIds.size(), 1);
+ assertObjectIdsContains(juliusSubordinateIds, mikeId);
+
+ List<AtlasObjectId> juliusFriendsIds = toAtlasObjectIds(julius.getRelationshipAttribute("friends"));
+ assertEmpty(juliusFriendsIds);
+
+ AtlasObjectId juliusSiblingId = toAtlasObjectId(julius.getRelationshipAttribute("sibling"));
+ assertNotNull(juliusSiblingId);
+ assertObjectIdEquals(juliusSiblingId, janeId);
+ }
+
+ // Seeing intermittent failures with janus profile, disabling it until its fixed.
+ @Test(enabled = false)
+ public void testRelationshipAttributeUpdate_NonComposite_OneToMany() throws Exception {
+ AtlasObjectId maxId = employeeNameIdMap.get("Max");
+ AtlasObjectId juliusId = employeeNameIdMap.get("Julius");
+ AtlasObjectId janeId = employeeNameIdMap.get("Jane");
+ AtlasObjectId mikeId = employeeNameIdMap.get("Mike");
+ AtlasObjectId johnId = employeeNameIdMap.get("John");
+
+ // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
+ // This should also update Julius to add Max to the inverse Manager.subordinates reference.
+ AtlasEntity maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+ maxEntityForUpdate.setRelationshipAttribute("manager", juliusId);
+
+ AtlasEntityType employeeType = typeRegistry.getEntityTypeByName(EMPLOYEE_TYPE);
+ Map<String, Object> uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
+ EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+ List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+ assertEquals(partialUpdatedEntities.size(), 3);
+ // 3 entities should have been updated:
+ // * Max to change the Employee.manager reference
+ // * Julius to add Max to Manager.subordinates
+ // * Jane to remove Max from Manager.subordinates
+
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeId.getGuid()));
+
+ // Max's manager updated as Julius
+ AtlasEntity maxEntity = updatedEntities.getEntity(maxId.getGuid());
+ verifyRelationshipAttributeValue(maxEntity, "manager", juliusId.getGuid());
+
+ // Max added to the subordinate list of Julius, existing subordinate is Mike
+ AtlasEntity juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+ verifyRelationshipAttributeList(juliusEntity, "subordinates", ImmutableList.of(maxId, mikeId));
+
+ // Max removed from the subordinate list of Julius
+ AtlasEntity janeEntity = updatedEntities.getEntity(janeId.getGuid());
+
+ // Jane's subordinates list includes John and Max for soft delete
+ // Jane's subordinates list includes only John for hard delete
+ verifyRelationshipAttributeUpdate_NonComposite_OneToMany(janeEntity);
+
+ // Remove Mike from Max's friends list
+ // Max's current friends: [Mike, John]
+ // Max's updated friends: [Julius, John]
+ maxEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+ maxEntityForUpdate.setRelationshipAttribute("friends", ImmutableList.of(johnId, juliusId));
+
+ init();
+ updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+
+ partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+ assertEquals(partialUpdatedEntities.size(), 3);
+ // 3 entities should have been updated:
+ // * Max added Julius and removed Mike from Employee.friends
+ // * Mike removed Max from Employee.friends
+ // * Julius added Max in Employee.friends
+
+ updatedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), mikeId.getGuid(), johnId.getGuid(), juliusId.getGuid()));
+
+ maxEntity = updatedEntities.getEntity(maxId.getGuid());
+ juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+ AtlasEntity mikeEntity = updatedEntities.getEntity(mikeId.getGuid());
+ AtlasEntity johnEntity = updatedEntities.getEntity(johnId.getGuid());
+
+ verifyRelationshipAttributeUpdate_ManyToMany_Friends(maxEntity, juliusEntity, mikeEntity, johnEntity);
+
+ // Remove Julius from Jane's sibling and add Mike as new sibling
+ AtlasEntity juliusEntityForUpdate = new AtlasEntity(EMPLOYEE_TYPE);
+ juliusEntityForUpdate.setRelationshipAttribute("sibling", mikeId);
+
+ init();
+ updateResponse = entityStore.updateByUniqueAttributes(employeeType, Collections.<String, Object>singletonMap("name", "Julius") , new AtlasEntityWithExtInfo(juliusEntityForUpdate));
+ partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+ assertEquals(partialUpdatedEntities.size(), 3);
+
+ updatedEntities = entityStore.getByIds(ImmutableList.of(juliusId.getGuid(), janeId.getGuid(), mikeId.getGuid()));
+
+ juliusEntity = updatedEntities.getEntity(juliusId.getGuid());
+ janeEntity = updatedEntities.getEntity(janeId.getGuid());
+ mikeEntity = updatedEntities.getEntity(mikeId.getGuid());
+
+ verifyRelationshipAttributeUpdate_OneToOne_Sibling(juliusEntity, janeEntity, mikeEntity);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_ManyToOne() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, "a3_name");
+
+ AtlasEntity b = new AtlasEntity("B");
+ b.setAttribute(NAME, "b_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(a3);
+ entitiesWithExtInfo.addEntity(b);
+ entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity bPartialUpdate = new AtlasEntity("B");
+ bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ init();
+ EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(bPartialUpdate));
+ // Verify 3 entities were updated:
+ // * set b.manyA reference to a1 and a2
+ // * set inverse a1.oneB reference to b
+ // * set inverse a2.oneB reference to b
+ assertEquals(response.getPartialUpdatedEntities().size(), 3);
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+ AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeValue(a1Entity, "oneB", b.getGuid());
+
+ AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeValue(a2Entity, "oneB", b.getGuid());
+
+ AtlasEntity bEntity = updatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeList(bEntity, "manyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+
+ bPartialUpdate.setRelationshipAttribute("manyA", ImmutableList.of(getAtlasObjectId(a3)));
+ init();
+ response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(bPartialUpdate));
+ // Verify 4 entities were updated:
+ // * set b.manyA reference to a3
+ // * set inverse a3.oneB reference to b
+ // * disconnect inverse a1.oneB reference to b
+ // * disconnect inverse a2.oneB reference to b
+ assertEquals(response.getPartialUpdatedEntities().size(), 4);
+ init();
+
+ updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
+ a1Entity = updatedEntities.getEntity(a1.getGuid());
+ a2Entity = updatedEntities.getEntity(a2.getGuid());
+ bEntity = updatedEntities.getEntity(b.getGuid());
+
+ AtlasEntity a3Entity = updatedEntities.getEntity(a3.getGuid());
+ verifyRelationshipAttributeValue(a3Entity, "oneB", b.getGuid());
+
+ verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(a1Entity, a2Entity, a3Entity, bEntity);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_OneToOne() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity b = new AtlasEntity("B");
+ b.setAttribute(NAME, "b_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(b);
+
+ EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity partialUpdateB = new AtlasEntity("B");
+ partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a1));
+
+ init();
+ AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+
+ response = entityStore.updateByUniqueAttributes(bType, Collections.singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+ List<AtlasEntityHeader> partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+ // Verify 2 entities were updated:
+ // * set b.a reference to a1
+ // * set inverse a1.b reference to b
+ assertEquals(partialUpdatedEntitiesHeader.size(), 2);
+ AtlasEntitiesWithExtInfo partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
+
+ AtlasEntity a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeValue(a1Entity, "b", b.getGuid());
+
+ AtlasEntity bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeValue(bEntity, "a", a1.getGuid());
+
+ init();
+
+ // Update b.a to reference a2.
+ partialUpdateB.setRelationshipAttribute("a", getAtlasObjectId(a2));
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(partialUpdateB));
+ partialUpdatedEntitiesHeader = response.getPartialUpdatedEntities();
+ // Verify 3 entities were updated:
+ // * set b.a reference to a2
+ // * set a2.b reference to b
+ // * disconnect a1.b reference
+ assertEquals(partialUpdatedEntitiesHeader.size(), 3);
+ partialUpdatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+
+ bEntity = partialUpdatedEntities.getEntity(b.getGuid());
+ verifyRelationshipAttributeValue(bEntity, "a", a2.getGuid());
+
+ AtlasEntity a2Entity = partialUpdatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeValue(a2Entity, "b", b.getGuid());
+
+ a1Entity = partialUpdatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeUpdate_NonComposite_OneToOne(a1Entity, bEntity);
+ }
+
+ @Test
+ public void testRelationshipAttributeUpdate_NonComposite_ManyToMany() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, "a1_name");
+
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, "a2_name");
+
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, "a3_name");
+
+ AtlasEntity b1 = new AtlasEntity("B");
+ b1.setAttribute(NAME, "b1_name");
+
+ AtlasEntity b2 = new AtlasEntity("B");
+ b2.setAttribute(NAME, "b2_name");
+
+ AtlasEntitiesWithExtInfo entitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ entitiesWithExtInfo.addEntity(a1);
+ entitiesWithExtInfo.addEntity(a2);
+ entitiesWithExtInfo.addEntity(a3);
+ entitiesWithExtInfo.addEntity(b1);
+ entitiesWithExtInfo.addEntity(b2);
+ entityStore.createOrUpdate(new AtlasEntityStream(entitiesWithExtInfo) , false);
+
+ AtlasEntity b1PartialUpdate = new AtlasEntity("B");
+ b1PartialUpdate.setRelationshipAttribute("manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ init();
+ EntityMutationResponse response = entityStore.updateByUniqueAttributes(typeRegistry.getEntityTypeByName("B"),
+ Collections.singletonMap(NAME, b1.getAttribute(NAME)),
+ new AtlasEntityWithExtInfo(b1PartialUpdate));
+
+ List<AtlasEntityHeader> updatedEntityHeaders = response.getPartialUpdatedEntities();
+ assertEquals(updatedEntityHeaders.size(), 3);
+
+ AtlasEntitiesWithExtInfo updatedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
+
+ AtlasEntity b1Entity = updatedEntities.getEntity(b1.getGuid());
+ verifyRelationshipAttributeList(b1Entity, "manyToManyA", ImmutableList.of(getAtlasObjectId(a1), getAtlasObjectId(a2)));
+
+ AtlasEntity a1Entity = updatedEntities.getEntity(a1.getGuid());
+ verifyRelationshipAttributeList(a1Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+
+ AtlasEntity a2Entity = updatedEntities.getEntity(a2.getGuid());
+ verifyRelationshipAttributeList(a2Entity, "manyB", ImmutableList.of(getAtlasObjectId(b1)));
+ }
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_OneToMany(AtlasEntity entity) throws Exception;
+
+ protected abstract void verifyRelationshipAttributeUpdate_NonComposite_ManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
+
+ protected abstract void verifyRelationshipAttributeUpdate_ManyToMany_Friends(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3, AtlasEntity e4) throws Exception;
+
+ protected abstract void verifyRelationshipAttributeUpdate_OneToOne_Sibling(AtlasEntity e1, AtlasEntity e2, AtlasEntity e3) throws Exception;
+
+ protected static void assertObjectIdsContains(List<AtlasObjectId> objectIds, AtlasObjectId objectId) {
+ assertTrue(CollectionUtils.isNotEmpty(objectIds));
+ assertTrue(objectIds.contains(objectId));
+ }
+
+ protected static void assertObjectIdEquals(AtlasObjectId objId1, AtlasObjectId objId2) {
+ assertTrue(objId1.equals(objId2));
+ }
+
+ private static void assertEmpty(List collection) {
+ assertTrue(collection != null && collection.isEmpty());
+ }
+
+ protected static List<AtlasObjectId> toAtlasObjectIds(Object object) {
+ List<AtlasObjectId> ret = new ArrayList<>();
+
+ if (object instanceof List) {
+ List<?> objectIds = (List) object;
+
+ if (CollectionUtils.isNotEmpty(objectIds)) {
+ for (Object obj : objectIds) {
+ if (obj instanceof AtlasRelatedObjectId) {
+ AtlasRelatedObjectId relatedObjectId = (AtlasRelatedObjectId) obj;
+ ret.add(new AtlasObjectId(relatedObjectId.getGuid(), relatedObjectId.getTypeName(), relatedObjectId.getUniqueAttributes()));
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ protected static AtlasObjectId toAtlasObjectId(Object object) {
+ if (object instanceof AtlasRelatedObjectId) {
+ AtlasRelatedObjectId relatedObjectId = (AtlasRelatedObjectId) object;
+ return new AtlasObjectId(relatedObjectId.getGuid(), relatedObjectId.getTypeName(), relatedObjectId.getUniqueAttributes());
+ }
+
+ return null;
+ }
+
+ private AtlasEntity getEntityFromStore(String guid) throws AtlasBaseException {
+ AtlasEntityWithExtInfo entity = guid != null ? entityStore.getById(guid) : null;
+
+ return entity != null ? entity.getEntity() : null;
+ }
+
+ protected static void verifyRelationshipAttributeList(AtlasEntity entity, String relationshipAttrName, List<AtlasObjectId> expectedValues) {
+ Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+ assertTrue(refValue instanceof List);
+
+ List<AtlasObjectId> refList = toAtlasObjectIds(refValue);
+ assertEquals(refList.size(), expectedValues.size());
+
+ if (expectedValues.size() > 0) {
+ assertTrue(refList.containsAll(expectedValues));
+ }
+ }
+
+ protected static void verifyRelationshipAttributeValue(AtlasEntity entity, String relationshipAttrName, String expectedGuid) {
+ Object refValue = entity.getRelationshipAttribute(relationshipAttrName);
+ if (expectedGuid == null) {
+ assertNull(refValue);
+ }
+ else {
+ assertTrue(refValue instanceof AtlasObjectId);
+ AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
+ assertEquals(referencedObjectId.getGuid(), expectedGuid);
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..5d45908
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateHardDeleteV2Test.java
@@ -0,0 +1,76 @@
+/**
+ * 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.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.type.AtlasTypeUtil;
+import org.testng.annotations.Guice;
+
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+/**
+ * Inverse reference update test with {@link HardDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.HardDeleteModule.class)
+public class InverseReferenceUpdateHardDeleteV2Test extends InverseReferenceUpdateV2Test {
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception {
+
+ // Max should have been removed from the subordinates list, leaving only John.
+ verifyReferenceList(jane, "subordinates", ImmutableList.of(nameIdMap.get("John")));
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b) {
+
+ verifyReferenceValue(a1, "oneB", null);
+
+ verifyReferenceValue(a2, "oneB", null);
+
+ verifyReferenceList(b, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a3)));
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+
+ verifyReferenceValue(a1, "b", null);
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1,
+ AtlasEntity b2, AtlasEntity b3) {
+
+ Object value = a1.getAttribute("mapToB");
+ assertTrue(value instanceof Map);
+ Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+ assertEquals(refMap.size(), 1);
+ AtlasObjectId referencedEntityId = refMap.get("b3");
+ assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b3));
+ verifyReferenceValue(b1, "mappedFromA", null);
+ verifyReferenceValue(b2, "mappedFromA", null);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..76d6b7d
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateSoftDeleteV2Test.java
@@ -0,0 +1,79 @@
+/**
+ * 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.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.type.AtlasTypeUtil;
+import org.testng.annotations.Guice;
+
+import java.util.Map;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+
+/**
+ * Inverse reference update test with {@link SoftDeleteHandlerV1}
+ */
+@Guice(modules = TestModules.SoftDeleteModule.class)
+public class InverseReferenceUpdateSoftDeleteV2Test extends InverseReferenceUpdateV2Test {
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane)
+ throws Exception {
+
+ // Max is still in the subordinates list, as the edge still exists with state DELETED
+ verifyReferenceList(jane, "subordinates", ImmutableList.of(nameIdMap.get("John"), nameIdMap.get("Max")));
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1,
+ AtlasEntity a2, AtlasEntity a3, AtlasEntity b) {
+
+ verifyReferenceValue(a1, "oneB", b.getGuid());
+
+ verifyReferenceValue(a2, "oneB", b.getGuid());
+
+ verifyReferenceList(b, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2), AtlasTypeUtil.getAtlasObjectId(a3)));
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b) {
+
+ verifyReferenceValue(a1, "b", b.getGuid());
+ }
+
+ @Override
+ protected void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1,
+ AtlasEntity b2, AtlasEntity b3) {
+
+ Object value = a1.getAttribute("mapToB");
+ assertTrue(value instanceof Map);
+ Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+ assertEquals(refMap.size(), 3);
+ AtlasObjectId referencedEntityId = refMap.get("b3");
+ assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b3));
+ verifyReferenceValue(b1, "mappedFromA", a1.getGuid());
+ verifyReferenceValue(b2, "mappedFromA", a1.getGuid());
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..ea647ec
--- /dev/null
+++ b/repository/src/test/java/org/apache/atlas/repository/store/graph/v2/InverseReferenceUpdateV2Test.java
@@ -0,0 +1,380 @@
+/**
+ * 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.v2;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import org.apache.atlas.RequestContext;
+import org.apache.atlas.TestUtilsV2;
+import org.apache.atlas.model.instance.AtlasEntity;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntitiesWithExtInfo;
+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.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.AtlasEntityStore;
+import org.apache.atlas.runner.LocalSolrRunner;
+import org.apache.atlas.store.AtlasTypeDefStore;
+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.Test;
+
+import javax.inject.Inject;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.atlas.graph.GraphSandboxUtil.useLocalSolr;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import static org.apache.atlas.TestUtilsV2.NAME;
+
+/**
+ * Test automatic inverse reference updating in V1 (V2?) code path.
+ *
+ */
+public abstract class InverseReferenceUpdateV2Test {
+ @Inject
+ AtlasTypeRegistry typeRegistry;
+
+ @Inject
+ AtlasTypeDefStore typeDefStore;
+
+ @Inject
+ AtlasEntityStore entityStore;
+
+ private AtlasEntitiesWithExtInfo deptEntity;
+
+ protected Map<String, AtlasObjectId> nameIdMap = new HashMap<>();
+
+ @BeforeClass
+ public void setUp() throws Exception {
+ RequestContext.clear();
+ RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
+
+ AtlasTypesDef[] testTypesDefs = new AtlasTypesDef[] { TestUtilsV2.defineDeptEmployeeTypes(),
+ TestUtilsV2.defineInverseReferenceTestTypes()
+ };
+
+ for (AtlasTypesDef typesDef : testTypesDefs) {
+ AtlasTypesDef typesToCreate = AtlasTypeDefStoreInitializer.getTypesToCreate(typesDef, typeRegistry);
+
+ if (!typesToCreate.isEmpty()) {
+ typeDefStore.createTypesDef(typesToCreate);
+ }
+ }
+
+ deptEntity = TestUtilsV2.createDeptEg2();
+ init();
+ EntityMutationResponse response = entityStore.createOrUpdate(new AtlasEntityStream(deptEntity), false);
+ for (AtlasEntityHeader entityHeader : response.getCreatedEntities()) {
+ nameIdMap.put((String)entityHeader.getAttribute(NAME), AtlasTypeUtil.getAtlasObjectId(entityHeader));
+ }
+ }
+
+ @AfterClass
+ public void clear() throws Exception {
+ AtlasGraphProvider.cleanup();
+
+ if (useLocalSolr()) {
+ LocalSolrRunner.stop();
+ }
+ }
+
+ @BeforeMethod
+ public void init() throws Exception {
+ RequestContext.clear();
+ RequestContext.get().setUser(TestUtilsV2.TEST_USER, null);
+ }
+
+ @Test
+ public void testInverseReferenceAutoUpdate_NonComposite_OneToMany() throws Exception {
+ AtlasObjectId juliusId = nameIdMap.get("Julius");
+
+ // Change Max's Employee.manager reference to Julius and apply the change as a partial update.
+ // This should also update Julius to add Max to the inverse Manager.subordinates reference.
+ AtlasEntity maxEntityForUpdate = new AtlasEntity(TestUtilsV2.EMPLOYEE_TYPE);
+ maxEntityForUpdate.setAttribute("manager", juliusId);
+ AtlasEntityType employeeType = typeRegistry.getEntityTypeByName(TestUtilsV2.EMPLOYEE_TYPE);
+ Map<String, Object> uniqAttributes = Collections.<String, Object>singletonMap("name", "Max");
+ EntityMutationResponse updateResponse = entityStore.updateByUniqueAttributes(employeeType, uniqAttributes , new AtlasEntityWithExtInfo(maxEntityForUpdate));
+ List<AtlasEntityHeader> partialUpdatedEntities = updateResponse.getPartialUpdatedEntities();
+ // 3 entities should have been updated:
+ // * Max to change the Employee.manager reference
+ // * Julius to add Max to Manager.subordinates
+ // * Jane to remove Max from Manager.subordinates
+ assertEquals(partialUpdatedEntities.size(), 3);
+
+ AtlasObjectId maxId = nameIdMap.get("Max");
+ String janeGuid = nameIdMap.get("Jane").getGuid();
+ AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(maxId.getGuid(), juliusId.getGuid(), janeGuid));
+ AtlasEntity storedEntity = storedEntities.getEntity(maxId.getGuid());
+ verifyReferenceValue(storedEntity, "manager", juliusId.getGuid());
+ storedEntity = storedEntities.getEntity(juliusId.getGuid());
+ verifyReferenceList(storedEntity, "subordinates", ImmutableList.of(maxId));
+ storedEntity = storedEntities.getEntity(janeGuid);
+ verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(storedEntity);
+ }
+
+ protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToMany(AtlasEntity jane) throws Exception;
+
+ @Test
+ public void testInverseReferenceAutoUpdate_NonCompositeManyToOne() throws Exception {
+ AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b = new AtlasEntity("B");
+
+ b.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ atlasEntitiesWithExtInfo.addEntity(a1);
+ atlasEntitiesWithExtInfo.addEntity(a2);
+ atlasEntitiesWithExtInfo.addEntity(a3);
+ atlasEntitiesWithExtInfo.addEntity(b);
+ AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+ EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+ AtlasEntity bForPartialUpdate = new AtlasEntity("B");
+ bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+ init();
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+ List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 3 entities were updated:
+ // * set b.manyA reference to a1 and a2
+ // * set inverse a1.oneB reference to b
+ // * set inverse a2.oneB reference to b
+ assertEquals(partialUpdatedEntities.size(), 3);
+ AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+ AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+ verifyReferenceValue(storedEntity, "oneB", b.getGuid());
+
+ storedEntity = storedEntities.getEntity(a2.getGuid());
+ verifyReferenceValue(storedEntity, "oneB", b.getGuid());
+
+ storedEntity = storedEntities.getEntity(b.getGuid());
+ verifyReferenceList(storedEntity, "manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+
+ bForPartialUpdate.setAttribute("manyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a3)));
+ init();
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+ partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 4 entities were updated:
+ // * set b.manyA reference to a3
+ // * set inverse a3.oneB reference to b
+ // * disconnect inverse a1.oneB reference to b
+ // * disconnect inverse a2.oneB reference to b
+ assertEquals(partialUpdatedEntities.size(), 4);
+
+ init();
+ storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), a3.getGuid(), b.getGuid()));
+ verifyReferenceValue(storedEntities.getEntity(a3.getGuid()), "oneB", b.getGuid());
+
+ verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(a2.getGuid()),
+ storedEntities.getEntity(a3.getGuid()), storedEntities.getEntity(b.getGuid()));
+ }
+
+ protected abstract void verify_testInverseReferenceAutoUpdate_NonCompositeManyToOne(AtlasEntity a1, AtlasEntity a2, AtlasEntity a3, AtlasEntity b);
+
+ @Test
+ public void testInverseReferenceAutoUpdate_NonComposite_OneToOne() throws Exception {
+ AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b = new AtlasEntity("B");
+ b.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ atlasEntitiesWithExtInfo.addEntity(a1);
+ atlasEntitiesWithExtInfo.addEntity(a2);
+ atlasEntitiesWithExtInfo.addEntity(b);
+ AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+ EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+ AtlasEntity bForPartialUpdate = new AtlasEntity("B");
+ bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a1));
+ init();
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+ List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 2 entities were updated:
+ // * set b.a reference to a1
+ // * set inverse a1.b reference to b
+ assertEquals(partialUpdatedEntities.size(), 2);
+ AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b.getGuid()));
+ AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+ verifyReferenceValue(storedEntity, "b", b.getGuid());
+ storedEntity = storedEntities.getEntity(b.getGuid());
+ verifyReferenceValue(storedEntity, "a", a1.getGuid());
+
+ // Update b.a to reference a2.
+ bForPartialUpdate.setAttribute("a", AtlasTypeUtil.getAtlasObjectId(a2));
+ init();
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b.getAttribute(NAME)), new AtlasEntityWithExtInfo(bForPartialUpdate));
+ partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 3 entities were updated:
+ // * set b.a reference to a2
+ // * set a2.b reference to b
+ // * disconnect a1.b reference
+ assertEquals(partialUpdatedEntities.size(), 3);
+ storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b.getGuid()));
+ storedEntity = storedEntities.getEntity(a2.getGuid());
+ verifyReferenceValue(storedEntity, "b", b.getGuid());
+ storedEntity = storedEntities.getEntity(b.getGuid());
+ verifyReferenceValue(storedEntity, "a", a2.getGuid());
+ storedEntity = storedEntities.getEntity(a1.getGuid());
+ Object refValue = storedEntity.getAttribute("b");
+ verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b.getGuid()));
+ }
+
+ protected abstract void verify_testInverseReferenceAutoUpdate_NonComposite_OneToOne(AtlasEntity a1, AtlasEntity b);
+
+ @Test
+ public void testInverseReferenceAutoUpdate_NonComposite_ManyToMany() throws Exception {
+ AtlasEntityType bType = typeRegistry.getEntityTypeByName("B");
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity a2 = new AtlasEntity("A");
+ a2.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity a3 = new AtlasEntity("A");
+ a3.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b1 = new AtlasEntity("B");
+ b1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b2 = new AtlasEntity("B");
+ b2.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ atlasEntitiesWithExtInfo.addEntity(a1);
+ atlasEntitiesWithExtInfo.addEntity(a2);
+ atlasEntitiesWithExtInfo.addEntity(a3);
+ atlasEntitiesWithExtInfo.addEntity(b1);
+ atlasEntitiesWithExtInfo.addEntity(b2);
+ AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+ EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+ AtlasEntity b1ForPartialUpdate = new AtlasEntity("B");
+ b1ForPartialUpdate.setAttribute("manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+ init();
+ response = entityStore.updateByUniqueAttributes(bType, Collections.<String, Object>singletonMap(NAME, b1.getAttribute(NAME)), new AtlasEntityWithExtInfo(b1ForPartialUpdate));
+ List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+ assertEquals(partialUpdatedEntities.size(), 3);
+ AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), a2.getGuid(), b1.getGuid()));
+ AtlasEntity storedEntity = storedEntities.getEntity(b1.getGuid());
+ verifyReferenceList(storedEntity, "manyToManyA", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(a1), AtlasTypeUtil.getAtlasObjectId(a2)));
+ storedEntity = storedEntities.getEntity(a1.getGuid());
+ verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
+ storedEntity = storedEntities.getEntity(a2.getGuid());
+ verifyReferenceList(storedEntity, "manyB", ImmutableList.of(AtlasTypeUtil.getAtlasObjectId(b1)));
+ }
+
+ @Test
+ public void testInverseReferenceAutoUpdate_Map() throws Exception {
+ AtlasEntity a1 = new AtlasEntity("A");
+ a1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b1 = new AtlasEntity("B");
+ b1.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b2 = new AtlasEntity("B");
+ b2.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntity b3 = new AtlasEntity("B");
+ b3.setAttribute(NAME, TestUtilsV2.randomString());
+ AtlasEntitiesWithExtInfo atlasEntitiesWithExtInfo = new AtlasEntitiesWithExtInfo();
+ atlasEntitiesWithExtInfo.addEntity(a1);
+ atlasEntitiesWithExtInfo.addEntity(b1);
+ atlasEntitiesWithExtInfo.addEntity(b2);
+ atlasEntitiesWithExtInfo.addEntity(b3);
+ AtlasEntityStream entityStream = new AtlasEntityStream(atlasEntitiesWithExtInfo);
+ EntityMutationResponse response = entityStore.createOrUpdate(entityStream , false);
+
+ AtlasEntityType aType = typeRegistry.getEntityTypeByName("A");
+ AtlasEntity aForPartialUpdate = new AtlasEntity("A");
+ aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b1", AtlasTypeUtil.getAtlasObjectId(b1), "b2", AtlasTypeUtil.getAtlasObjectId(b2)));
+ init();
+ response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
+ List<AtlasEntityHeader> partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 3 entities were updated:
+ // * set a1.mapToB to "b1"->b1, "b2"->b2
+ // * set b1.mappedFromA to a1
+ // * set b2.mappedFromA to a1
+ assertEquals(partialUpdatedEntities.size(), 3);
+ AtlasEntitiesWithExtInfo storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid()));
+ AtlasEntity storedEntity = storedEntities.getEntity(a1.getGuid());
+ Object value = storedEntity.getAttribute("mapToB");
+ assertTrue(value instanceof Map);
+ Map<String, AtlasObjectId> refMap = (Map<String, AtlasObjectId>) value;
+ assertEquals(refMap.size(), 2);
+ AtlasObjectId referencedEntityId = refMap.get("b1");
+ assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b1));
+ referencedEntityId = refMap.get("b2");
+ assertEquals(referencedEntityId, AtlasTypeUtil.getAtlasObjectId(b2));
+ storedEntity = storedEntities.getEntity(b1.getGuid());
+ verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());
+ storedEntity = storedEntities.getEntity(b2.getGuid());
+ verifyReferenceValue(storedEntity, "mappedFromA", a1.getGuid());
+
+ aForPartialUpdate.setAttribute("mapToB", ImmutableMap.<String, AtlasObjectId>of("b3", AtlasTypeUtil.getAtlasObjectId(b3)));
+ init();
+ response = entityStore.updateByUniqueAttributes(aType, Collections.<String, Object>singletonMap(NAME, a1.getAttribute(NAME)), new AtlasEntityWithExtInfo(aForPartialUpdate));
+ partialUpdatedEntities = response.getPartialUpdatedEntities();
+ // Verify 4 entities were updated:
+ // * set a1.mapToB to "b3"->b3
+ // * set b3.mappedFromA to a1
+ // * disconnect b1.mappedFromA
+ // * disconnect b2.mappedFromA
+ assertEquals(partialUpdatedEntities.size(), 4);
+ storedEntities = entityStore.getByIds(ImmutableList.of(a1.getGuid(), b2.getGuid(), b1.getGuid(), b3.getGuid()));
+ AtlasEntity storedB3 = storedEntities.getEntity(b3.getGuid());
+ verifyReferenceValue(storedB3, "mappedFromA", a1.getGuid());
+ verify_testInverseReferenceAutoUpdate_Map(storedEntities.getEntity(a1.getGuid()), storedEntities.getEntity(b1.getGuid()), storedEntities.getEntity(b2.getGuid()), storedB3);
+ }
+
+ protected abstract void verify_testInverseReferenceAutoUpdate_Map(AtlasEntity a1, AtlasEntity b1, AtlasEntity b2, AtlasEntity b3);
+
+ protected void verifyReferenceValue(AtlasEntity entity, String refName, String expectedGuid) {
+ Object refValue = entity.getAttribute(refName);
+ if (expectedGuid == null) {
+ assertNull(refValue);
+ }
+ else {
+ assertTrue(refValue instanceof AtlasObjectId);
+ AtlasObjectId referencedObjectId = (AtlasObjectId) refValue;
+ assertEquals(referencedObjectId.getGuid(), expectedGuid);
+ }
+ }
+
+ protected void verifyReferenceList(AtlasEntity entity, String refName, List<AtlasObjectId> expectedValues) {
+ Object refValue = entity.getAttribute(refName);
+ assertTrue(refValue instanceof List);
+ List<AtlasObjectId> refList = (List<AtlasObjectId>) refValue;
+ assertEquals(refList.size(), expectedValues.size());
+ if (expectedValues.size() > 0) {
+ assertTrue(refList.containsAll(expectedValues));
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/repository/src/test/java/org/apache/atlas/repository/tagpropagation/ClassificationPropagationTest.java
----------------------------------------------------------------------
diff --git a/repository/src/test/java/org/apache/atlas/repository/tagpropagation/ClassificationPropagationTest.java b/repository/src/test/java/org/apache/atlas/repository/tagpropagation/ClassificationPropagationTest.java
index 151211e..8ceeedb 100644
--- a/repository/src/test/java/org/apache/atlas/repository/tagpropagation/ClassificationPropagationTest.java
+++ b/repository/src/test/java/org/apache/atlas/repository/tagpropagation/ClassificationPropagationTest.java
@@ -17,7 +17,7 @@
*/
package org.apache.atlas.repository.tagpropagation;
-import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.RequestContext;
import org.apache.atlas.TestModules;
import org.apache.atlas.discovery.AtlasLineageService;
import org.apache.atlas.exception.AtlasBaseException;
@@ -104,7 +104,7 @@ public class ClassificationPropagationTest {
@BeforeClass
public void setup() {
- RequestContextV1.clear();
+ RequestContext.clear();
loadModelFilesAndImportTestData();
}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/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
new file mode 100644
index 0000000..b4ff98a
--- /dev/null
+++ b/server-api/src/main/java/org/apache/atlas/RequestContext.java
@@ -0,0 +1,186 @@
+/**
+ * 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;
+
+import org.apache.atlas.model.instance.AtlasClassification;
+import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
+import org.apache.atlas.model.instance.AtlasObjectId;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+public class RequestContext {
+ private static final Logger LOG = LoggerFactory.getLogger(RequestContext.class);
+
+ private static final ThreadLocal<RequestContext> CURRENT_CONTEXT = new ThreadLocal<>();
+
+ private final Map<String, AtlasObjectId> updatedEntities = new HashMap<>();
+ private final Map<String, AtlasObjectId> deletedEntities = new HashMap<>();
+ private final Map<String, AtlasEntityWithExtInfo> entityCacheV2 = 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 String user;
+ private Set<String> userGroups;
+ private String clientIPAddress;
+
+
+ private RequestContext() {
+ }
+
+ //To handle gets from background threads where createContext() is not called
+ //createContext called for every request in the filter
+ public static RequestContext get() {
+ RequestContext ret = CURRENT_CONTEXT.get();
+
+ if (ret == null) {
+ ret = new RequestContext();
+ CURRENT_CONTEXT.set(ret);
+ }
+
+ return ret;
+ }
+
+ public static void clear() {
+ RequestContext instance = CURRENT_CONTEXT.get();
+
+ if (instance != null) {
+ instance.updatedEntities.clear();
+ instance.deletedEntities.clear();
+ instance.entityCacheV2.clear();
+ instance.addedPropagations.clear();
+ instance.removedPropagations.clear();
+ }
+
+ CURRENT_CONTEXT.remove();
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public Set<String> getUserGroups() {
+ return userGroups;
+ }
+
+ public void setUser(String user, Set<String> userGroups) {
+ this.user = user;
+ this.userGroups = userGroups;
+ }
+
+ public String getClientIPAddress() {
+ return clientIPAddress;
+ }
+
+ public void setClientIPAddress(String clientIPAddress) {
+ this.clientIPAddress = clientIPAddress;
+ }
+
+ public void recordEntityUpdate(AtlasObjectId entity) {
+ if (entity != null && entity.getGuid() != null) {
+ updatedEntities.put(entity.getGuid(), entity);
+ }
+ }
+
+ public void recordEntityDelete(AtlasObjectId entity) {
+ if (entity != null && entity.getGuid() != null) {
+ deletedEntities.put(entity.getGuid(), entity);
+ }
+ }
+
+ public void recordAddedPropagation(String guid, AtlasClassification classification) {
+ if (StringUtils.isNotEmpty(guid) && classification != null) {
+ List<AtlasClassification> classifications = addedPropagations.get(guid);
+
+ if (classifications == null) {
+ classifications = new ArrayList<>();
+ }
+
+ classifications.add(classification);
+
+ addedPropagations.put(guid, classifications);
+ }
+ }
+
+ public void recordRemovedPropagation(String guid, AtlasClassification classification) {
+ if (StringUtils.isNotEmpty(guid) && classification != null) {
+ List<AtlasClassification> classifications = removedPropagations.get(guid);
+
+ if (classifications == null) {
+ classifications = new ArrayList<>();
+ }
+
+ classifications.add(classification);
+
+ removedPropagations.put(guid, classifications);
+ }
+ }
+
+ public Map<String, List<AtlasClassification>> getAddedPropagations() {
+ return addedPropagations;
+ }
+
+ public Map<String, List<AtlasClassification>> getRemovedPropagations() {
+ return removedPropagations;
+ }
+
+ /**
+ * Adds the specified instance to the cache
+ *
+ */
+ public void cache(AtlasEntityWithExtInfo entity) {
+ if (entity != null && entity.getEntity() != null && entity.getEntity().getGuid() != null) {
+ entityCacheV2.put(entity.getEntity().getGuid(), entity);
+ }
+ }
+
+ public Collection<AtlasObjectId> getUpdatedEntities() {
+ return updatedEntities.values();
+ }
+
+ public Collection<AtlasObjectId> getDeletedEntities() {
+ return deletedEntities.values();
+ }
+
+ /**
+ * Checks if an instance with the given guid is in the cache for this request. Either returns the instance
+ * or null if it is not in the cache.
+ *
+ * @param guid the guid to find
+ * @return Either the instance or null if it is not in the cache.
+ */
+ public AtlasEntityWithExtInfo getInstanceV2(String guid) {
+ return entityCacheV2.get(guid);
+ }
+
+ public long getRequestTime() {
+ return requestTime;
+ }
+
+ public boolean isUpdatedEntity(String guid) {
+ return updatedEntities.containsKey(guid);
+ }
+
+ public boolean isDeletedEntity(String guid) {
+ return deletedEntities.containsKey(guid);
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
----------------------------------------------------------------------
diff --git a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java b/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
deleted file mode 100644
index 0fc15e8..0000000
--- a/server-api/src/main/java/org/apache/atlas/RequestContextV1.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/**
- * 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;
-
-import org.apache.atlas.model.instance.AtlasClassification;
-import org.apache.atlas.model.instance.AtlasEntity.AtlasEntityWithExtInfo;
-import org.apache.atlas.model.instance.AtlasObjectId;
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.*;
-
-public class RequestContextV1 {
- private static final Logger LOG = LoggerFactory.getLogger(RequestContextV1.class);
-
- private static final ThreadLocal<RequestContextV1> CURRENT_CONTEXT = new ThreadLocal<>();
-
- private final Map<String, AtlasObjectId> updatedEntities = new HashMap<>();
- private final Map<String, AtlasObjectId> deletedEntities = new HashMap<>();
- private final Map<String, AtlasEntityWithExtInfo> entityCacheV2 = 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 String user;
- private Set<String> userGroups;
- private String clientIPAddress;
-
-
- private RequestContextV1() {
- }
-
- //To handle gets from background threads where createContext() is not called
- //createContext called for every request in the filter
- public static RequestContextV1 get() {
- RequestContextV1 ret = CURRENT_CONTEXT.get();
-
- if (ret == null) {
- ret = new RequestContextV1();
- CURRENT_CONTEXT.set(ret);
- }
-
- return ret;
- }
-
- public static void clear() {
- RequestContextV1 instance = CURRENT_CONTEXT.get();
-
- if (instance != null) {
- instance.updatedEntities.clear();
- instance.deletedEntities.clear();
- instance.entityCacheV2.clear();
- instance.addedPropagations.clear();
- instance.removedPropagations.clear();
- }
-
- CURRENT_CONTEXT.remove();
- }
-
- public String getUser() {
- return user;
- }
-
- public Set<String> getUserGroups() {
- return userGroups;
- }
-
- public void setUser(String user, Set<String> userGroups) {
- this.user = user;
- this.userGroups = userGroups;
- }
-
- public String getClientIPAddress() {
- return clientIPAddress;
- }
-
- public void setClientIPAddress(String clientIPAddress) {
- this.clientIPAddress = clientIPAddress;
- }
-
- public void recordEntityUpdate(AtlasObjectId entity) {
- if (entity != null && entity.getGuid() != null) {
- updatedEntities.put(entity.getGuid(), entity);
- }
- }
-
- public void recordEntityDelete(AtlasObjectId entity) {
- if (entity != null && entity.getGuid() != null) {
- deletedEntities.put(entity.getGuid(), entity);
- }
- }
-
- public void recordAddedPropagation(String guid, AtlasClassification classification) {
- if (StringUtils.isNotEmpty(guid) && classification != null) {
- List<AtlasClassification> classifications = addedPropagations.get(guid);
-
- if (classifications == null) {
- classifications = new ArrayList<>();
- }
-
- classifications.add(classification);
-
- addedPropagations.put(guid, classifications);
- }
- }
-
- public void recordRemovedPropagation(String guid, AtlasClassification classification) {
- if (StringUtils.isNotEmpty(guid) && classification != null) {
- List<AtlasClassification> classifications = removedPropagations.get(guid);
-
- if (classifications == null) {
- classifications = new ArrayList<>();
- }
-
- classifications.add(classification);
-
- removedPropagations.put(guid, classifications);
- }
- }
-
- public Map<String, List<AtlasClassification>> getAddedPropagations() {
- return addedPropagations;
- }
-
- public Map<String, List<AtlasClassification>> getRemovedPropagations() {
- return removedPropagations;
- }
-
- /**
- * Adds the specified instance to the cache
- *
- */
- public void cache(AtlasEntityWithExtInfo entity) {
- if (entity != null && entity.getEntity() != null && entity.getEntity().getGuid() != null) {
- entityCacheV2.put(entity.getEntity().getGuid(), entity);
- }
- }
-
- public Collection<AtlasObjectId> getUpdatedEntities() {
- return updatedEntities.values();
- }
-
- public Collection<AtlasObjectId> getDeletedEntities() {
- return deletedEntities.values();
- }
-
- /**
- * Checks if an instance with the given guid is in the cache for this request. Either returns the instance
- * or null if it is not in the cache.
- *
- * @param guid the guid to find
- * @return Either the instance or null if it is not in the cache.
- */
- public AtlasEntityWithExtInfo getInstanceV2(String guid) {
- return entityCacheV2.get(guid);
- }
-
- public long getRequestTime() {
- return requestTime;
- }
-
- public boolean isUpdatedEntity(String guid) {
- return updatedEntities.containsKey(guid);
- }
-
- public boolean isDeletedEntity(String guid) {
- return deletedEntities.containsKey(guid);
- }
-}
http://git-wip-us.apache.org/repos/asf/atlas/blob/3d5b4880/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java
----------------------------------------------------------------------
diff --git a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java
index 017de99..c70011f 100644
--- a/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java
+++ b/webapp/src/main/java/org/apache/atlas/notification/EntityNotificationListenerV2.java
@@ -18,7 +18,7 @@
package org.apache.atlas.notification;
import org.apache.atlas.AtlasErrorCode;
-import org.apache.atlas.RequestContextV1;
+import org.apache.atlas.RequestContext;
import org.apache.atlas.exception.AtlasBaseException;
import org.apache.atlas.listener.EntityChangeListenerV2;
import org.apache.atlas.model.glossary.AtlasGlossaryTerm;
@@ -48,11 +48,11 @@ import java.util.Set;
import static org.apache.atlas.notification.NotificationInterface.NotificationType.ENTITIES;
import static org.apache.atlas.repository.graph.GraphHelper.isInternalType;
import static org.apache.atlas.model.notification.EntityNotification.EntityNotificationV2.OperationType.*;
-import static org.apache.atlas.repository.store.graph.v1.EntityGraphRetriever.CREATE_TIME;
-import static org.apache.atlas.repository.store.graph.v1.EntityGraphRetriever.DESCRIPTION;
-import static org.apache.atlas.repository.store.graph.v1.EntityGraphRetriever.NAME;
-import static org.apache.atlas.repository.store.graph.v1.EntityGraphRetriever.OWNER;
-import static org.apache.atlas.repository.store.graph.v1.EntityGraphRetriever.QUALIFIED_NAME;
+import static org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever.CREATE_TIME;
+import static org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever.DESCRIPTION;
+import static org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever.NAME;
+import static org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever.OWNER;
+import static org.apache.atlas.repository.store.graph.v2.EntityGraphRetriever.QUALIFIED_NAME;
@Component
public class EntityNotificationListenerV2 implements EntityChangeListenerV2 {
@@ -89,8 +89,8 @@ public class EntityNotificationListenerV2 implements EntityChangeListenerV2 {
@Override
public void onClassificationsUpdated(AtlasEntity entity, List<AtlasClassification> classifications) throws AtlasBaseException {
- Map<String, List<AtlasClassification>> addedPropagations = RequestContextV1.get().getAddedPropagations();
- Map<String, List<AtlasClassification>> removedPropagations = RequestContextV1.get().getRemovedPropagations();
+ Map<String, List<AtlasClassification>> addedPropagations = RequestContext.get().getAddedPropagations();
+ Map<String, List<AtlasClassification>> removedPropagations = RequestContext.get().getRemovedPropagations();
if (addedPropagations.containsKey(entity.getGuid())) {
notifyEntityEvents(Collections.singletonList(entity), CLASSIFICATION_ADD);