Return-Path: X-Original-To: apmail-atlas-commits-archive@minotaur.apache.org Delivered-To: apmail-atlas-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id AB89A18BC8 for ; Tue, 8 Dec 2015 06:40:24 +0000 (UTC) Received: (qmail 22944 invoked by uid 500); 8 Dec 2015 06:40:24 -0000 Delivered-To: apmail-atlas-commits-archive@atlas.apache.org Received: (qmail 22910 invoked by uid 500); 8 Dec 2015 06:40:24 -0000 Mailing-List: contact commits-help@atlas.incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@atlas.incubator.apache.org Delivered-To: mailing list commits@atlas.incubator.apache.org Received: (qmail 22901 invoked by uid 99); 8 Dec 2015 06:40:24 -0000 Received: from Unknown (HELO spamd4-us-west.apache.org) (209.188.14.142) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Dec 2015 06:40:24 +0000 Received: from localhost (localhost [127.0.0.1]) by spamd4-us-west.apache.org (ASF Mail Server at spamd4-us-west.apache.org) with ESMTP id E5F63C06D6 for ; Tue, 8 Dec 2015 06:40:23 +0000 (UTC) X-Virus-Scanned: Debian amavisd-new at spamd4-us-west.apache.org X-Spam-Flag: NO X-Spam-Score: 1.226 X-Spam-Level: * X-Spam-Status: No, score=1.226 tagged_above=-999 required=6.31 tests=[KAM_ASCII_DIVIDERS=0.8, KAM_LAZY_DOMAIN_SECURITY=1, RCVD_IN_MSPIKE_H3=-0.01, RCVD_IN_MSPIKE_WL=-0.01, RP_MATCHES_RCVD=-0.554] autolearn=disabled Received: from mx1-eu-west.apache.org ([10.40.0.8]) by localhost (spamd4-us-west.apache.org [10.40.0.11]) (amavisd-new, port 10024) with ESMTP id 4Qc_3SKFTnci for ; Tue, 8 Dec 2015 06:40:10 +0000 (UTC) Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by mx1-eu-west.apache.org (ASF Mail Server at mx1-eu-west.apache.org) with SMTP id 11914203A3 for ; Tue, 8 Dec 2015 06:40:07 +0000 (UTC) Received: (qmail 22066 invoked by uid 99); 8 Dec 2015 06:40:07 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 08 Dec 2015 06:40:07 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 2923BE0451; Tue, 8 Dec 2015 06:40:07 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: shwethags@apache.org To: commits@atlas.incubator.apache.org Date: Tue, 08 Dec 2015 06:40:08 -0000 Message-Id: <1ad1c8a9934f4ce3a311ba82609d7cde@git.apache.org> In-Reply-To: <102b383aef5047b5aedb48e443f41bea@git.apache.org> References: <102b383aef5047b5aedb48e443f41bea@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/5] incubator-atlas git commit: ATLAS-47 Entity mutations for complex types (sumasai via shwethags) http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java index b6e62aa..78af443 100755 --- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphBackedMetadataRepositoryTest.java @@ -29,13 +29,13 @@ import org.apache.atlas.RepositoryMetadataModule; import org.apache.atlas.TestUtils; import org.apache.atlas.discovery.graph.GraphBackedDiscoveryService; import org.apache.atlas.repository.Constants; -import org.apache.atlas.repository.EntityNotFoundException; import org.apache.atlas.repository.RepositoryException; import org.apache.atlas.typesystem.IStruct; import org.apache.atlas.typesystem.ITypedReferenceableInstance; import org.apache.atlas.typesystem.ITypedStruct; import org.apache.atlas.typesystem.Referenceable; import org.apache.atlas.typesystem.Struct; +import org.apache.atlas.typesystem.exception.EntityNotFoundException; import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.DataTypes; @@ -131,7 +131,7 @@ public class GraphBackedMetadataRepositoryTest { Assert.assertNotNull(entity); } - @Test(expectedExceptions = RepositoryException.class) + @Test(expectedExceptions = EntityNotFoundException.class) public void testGetEntityDefinitionNonExistent() throws Exception { repositoryService.getEntityDefinition("blah"); Assert.fail(); @@ -342,13 +342,13 @@ public class GraphBackedMetadataRepositoryTest { } Id expected = new Id(guid, tableVertex.getProperty(Constants.VERSION_PROPERTY_KEY), TestUtils.TABLE_TYPE); - Assert.assertEquals(repositoryService.getIdFromVertex(TestUtils.TABLE_TYPE, tableVertex), expected); + Assert.assertEquals(GraphHelper.getIdFromVertex(TestUtils.TABLE_TYPE, tableVertex), expected); } @Test(dependsOnMethods = "testCreateEntity") public void testGetTypeName() throws Exception { Vertex tableVertex = getTableEntityVertex(); - Assert.assertEquals(repositoryService.getTypeName(tableVertex), TestUtils.TABLE_TYPE); + Assert.assertEquals(GraphHelper.getTypeName(tableVertex), TestUtils.TABLE_TYPE); } @Test(dependsOnMethods = "testCreateEntity") @@ -415,6 +415,9 @@ public class GraphBackedMetadataRepositoryTest { public void testBug37860() throws Exception { String dslQuery = "hive_table as t where name = 'bar' " + "database where name = 'foo' and description = 'foo database' select t"; + + TestUtils.dumpGraph(graphProvider.get()); + System.out.println("Executing dslQuery = " + dslQuery); String jsonResults = discoveryService.searchByDSL(dslQuery); Assert.assertNotNull(jsonResults); @@ -446,6 +449,8 @@ public class GraphBackedMetadataRepositoryTest { //but with elasticsearch, doesn't work without sleep. why?? long sleepInterval = 1000; + TestUtils.dumpGraph(graphProvider.get()); + //person in hr department whose name is john Thread.sleep(sleepInterval); String response = discoveryService.searchByFullText("john"); @@ -475,31 +480,36 @@ public class GraphBackedMetadataRepositoryTest { @Test(dependsOnMethods = "testSubmitEntity") public void testUpdateEntity_MultiplicityOneNonCompositeReference() throws Exception { ITypedReferenceableInstance john = repositoryService.getEntityDefinition("Person", "name", "John"); - String johnGuid = john.getId()._getId(); + Id johnGuid = john.getId(); ITypedReferenceableInstance max = repositoryService.getEntityDefinition("Person", "name", "Max"); String maxGuid = max.getId()._getId(); ITypedReferenceableInstance jane = repositoryService.getEntityDefinition("Person", "name", "Jane"); - String janeGuid = jane.getId()._getId(); + Id janeGuid = jane.getId(); // Update max's mentor reference to john. - repositoryService.updateEntity(maxGuid, "mentor", johnGuid); + ClassType personType = typeSystem.getDataType(ClassType.class, "Person"); + ITypedReferenceableInstance instance = personType.createInstance(max.getId()); + instance.set("mentor", johnGuid); + repositoryService.updatePartial(instance); // Verify the update was applied correctly - john should now be max's mentor. max = repositoryService.getEntityDefinition(maxGuid); Object object = max.get("mentor"); Assert.assertTrue(object instanceof ITypedReferenceableInstance); ITypedReferenceableInstance refTarget = (ITypedReferenceableInstance) object; - Assert.assertEquals(refTarget.getId()._getId(), johnGuid); + Assert.assertEquals(refTarget.getId()._getId(), johnGuid._getId()); // Update max's mentor reference to jane. - repositoryService.updateEntity(maxGuid, "mentor", janeGuid); - + instance = personType.createInstance(max.getId()); + instance.set("mentor", janeGuid); + repositoryService.updatePartial(instance); + // Verify the update was applied correctly - jane should now be max's mentor. max = repositoryService.getEntityDefinition(maxGuid); object = max.get("mentor"); Assert.assertTrue(object instanceof ITypedReferenceableInstance); refTarget = (ITypedReferenceableInstance) object; - Assert.assertEquals(refTarget.getId()._getId(), janeGuid); + Assert.assertEquals(refTarget.getId()._getId(), janeGuid._getId()); } private ITypedReferenceableInstance createHiveTableInstance(Referenceable databaseInstance) throws Exception { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/repository/src/test/java/org/apache/atlas/repository/graph/GraphRepoMapperScaleTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/repository/graph/GraphRepoMapperScaleTest.java b/repository/src/test/java/org/apache/atlas/repository/graph/GraphRepoMapperScaleTest.java index 11e8219..c25ccf8 100755 --- a/repository/src/test/java/org/apache/atlas/repository/graph/GraphRepoMapperScaleTest.java +++ b/repository/src/test/java/org/apache/atlas/repository/graph/GraphRepoMapperScaleTest.java @@ -18,15 +18,9 @@ package org.apache.atlas.repository.graph; -import com.google.inject.Inject; -import com.thinkaurelius.titan.core.TitanFactory; import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.TitanIndexQuery; import com.thinkaurelius.titan.core.util.TitanCleanup; -import com.thinkaurelius.titan.diskstorage.BackendException; -import com.thinkaurelius.titan.diskstorage.configuration.ReadConfiguration; -import com.thinkaurelius.titan.diskstorage.configuration.backend.CommonsConfiguration; -import com.thinkaurelius.titan.graphdb.configuration.GraphDatabaseConfiguration; import com.tinkerpop.blueprints.Compare; import com.tinkerpop.blueprints.GraphQuery; import com.tinkerpop.blueprints.Predicate; @@ -42,19 +36,16 @@ import org.apache.atlas.typesystem.types.ClassType; import org.apache.atlas.typesystem.types.IDataType; import org.apache.atlas.typesystem.types.Multiplicity; import org.apache.atlas.typesystem.types.TypeSystem; -import org.apache.commons.io.FileUtils; import org.testng.Assert; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Guice; import org.testng.annotations.Test; -import java.io.File; -import java.io.IOException; +import javax.inject.Inject; import java.util.ArrayList; import java.util.Collection; import java.util.Date; -import java.util.Random; @Test @Guice(modules = RepositoryMetadataModule.class) @@ -63,15 +54,13 @@ public class GraphRepoMapperScaleTest { private static final String DATABASE_NAME = "foo"; private static final String TABLE_NAME = "bar"; - private static final String INDEX_DIR = - System.getProperty("java.io.tmpdir", "/tmp") + "/atlas-test" + new Random().nextLong(); - @Inject GraphProvider graphProvider; @Inject private GraphBackedMetadataRepository repositoryService; + @Inject private GraphBackedSearchIndexer searchIndexer; private TypeSystem typeSystem = TypeSystem.getInstance(); @@ -81,7 +70,7 @@ public class GraphRepoMapperScaleTest { @BeforeClass @GraphTransaction public void setUp() throws Exception { - searchIndexer = new GraphBackedSearchIndexer(graphProvider); + //Make sure we can cleanup the index directory Collection typesAdded = TestUtils.createHiveTypes(typeSystem); searchIndexer.onAdd(typesAdded); } @@ -127,7 +116,6 @@ public class GraphRepoMapperScaleTest { //Elasticsearch requires some time before index is updated Thread.sleep(5000); - searchWithOutIndex(Constants.GUID_PROPERTY_KEY, dbGUID); searchWithOutIndex(Constants.ENTITY_TYPE_PROPERTY_KEY, "column_type"); searchWithOutIndex(Constants.ENTITY_TYPE_PROPERTY_KEY, TestUtils.TABLE_TYPE); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java ---------------------------------------------------------------------- diff --git a/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java b/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java index 9d32332..0352ef3 100644 --- a/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java +++ b/repository/src/test/java/org/apache/atlas/service/DefaultMetadataServiceTest.java @@ -18,29 +18,40 @@ package org.apache.atlas.service; +import com.google.common.collect.ImmutableList; import com.google.inject.Inject; import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.util.TitanCleanup; +import org.apache.atlas.typesystem.exception.TypeNotFoundException; +import org.apache.atlas.typesystem.exception.EntityNotFoundException; +import org.apache.atlas.utils.ParamChecker; import org.apache.atlas.RepositoryMetadataModule; import org.apache.atlas.TestUtils; -import org.apache.atlas.TypeNotFoundException; -import org.apache.atlas.repository.EntityNotFoundException; import org.apache.atlas.repository.graph.GraphProvider; import org.apache.atlas.services.MetadataService; import org.apache.atlas.typesystem.Referenceable; +import org.apache.atlas.typesystem.Struct; import org.apache.atlas.typesystem.TypesDef; import org.apache.atlas.typesystem.json.InstanceSerialization; import org.apache.atlas.typesystem.json.TypesSerialization; -import org.apache.atlas.typesystem.types.EnumType; +import org.apache.atlas.typesystem.persistence.Id; import org.apache.atlas.typesystem.types.EnumValue; +import org.apache.atlas.typesystem.types.TypeSystem; +import org.apache.atlas.typesystem.types.ValueConversionException; import org.apache.commons.lang.RandomStringUtils; import org.codehaus.jettison.json.JSONArray; import org.testng.Assert; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; import org.testng.annotations.Guice; import org.testng.annotations.Test; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Guice(modules = RepositoryMetadataModule.class) public class DefaultMetadataServiceTest { @Inject @@ -48,8 +59,16 @@ public class DefaultMetadataServiceTest { @Inject private GraphProvider graphProvider; + private Referenceable db = createDBEntity(); + + private Id dbId; + + private Referenceable table; + + private Id tableId; + - @BeforeClass + @BeforeTest public void setUp() throws Exception { TypesDef typesDef = TestUtils.defineHiveTypes(); try { @@ -57,10 +76,21 @@ public class DefaultMetadataServiceTest { } catch (TypeNotFoundException e) { metadataService.createType(TypesSerialization.toJson(typesDef)); } + + String dbGUid = createInstance(db); + dbId = new Id(dbGUid, 0, TestUtils.DATABASE_TYPE); + + table = createTableEntity(dbId); + String tableGuid = createInstance(table); + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + table = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + tableId = new Id(tableGuid, 0, TestUtils.TABLE_TYPE); } - @AfterClass - public void shudown() { + @AfterTest + public void shutdown() { + TypeSystem.getInstance().reset(); try { //TODO - Fix failure during shutdown while using BDB graphProvider.get().shutdown(); @@ -82,6 +112,16 @@ public class DefaultMetadataServiceTest { return new JSONArray(response).getString(0); } + private String updateInstance(Referenceable entity) throws Exception { + ParamChecker.notNull(entity, "Entity"); + ParamChecker.notNull(entity.getId(), "Entity"); + String entityjson = InstanceSerialization.toJson(entity, true); + JSONArray entitiesJson = new JSONArray(); + entitiesJson.put(entityjson); + String response = metadataService.updateEntities(entitiesJson.toString()); + return new JSONArray(response).getString(0); + } + private Referenceable createDBEntity() { Referenceable entity = new Referenceable(TestUtils.DATABASE_TYPE); String dbName = RandomStringUtils.randomAlphanumeric(10); @@ -90,6 +130,18 @@ public class DefaultMetadataServiceTest { return entity; } + private Referenceable createTableEntity(Id dbId) { + Referenceable entity = new Referenceable(TestUtils.TABLE_TYPE); + String tableName = RandomStringUtils.randomAlphanumeric(10); + entity.set("name", tableName); + entity.set("description", "random table"); + entity.set("type", "type"); + entity.set("tableType", "MANAGED"); + entity.set("database", dbId); + entity.set("created", new Date()); + return entity; + } + @Test public void testCreateEntityWithUniqueAttribute() throws Exception { //name is the unique attribute @@ -116,30 +168,447 @@ public class DefaultMetadataServiceTest { table.set("description", "random table"); table.set("type", "type"); table.set("tableType", "MANAGED"); - table.set("database", db); + table.set("database", new Id(dbId, 0, TestUtils.DATABASE_TYPE)); + table.set("databaseComposite", db); createInstance(table); //table create should re-use the db instance created earlier String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); - Referenceable actualDb = (Referenceable) tableDefinition.get("database"); + Referenceable actualDb = (Referenceable) tableDefinition.get("databaseComposite"); Assert.assertEquals(actualDb.getId().id, dbId); } @Test - public void testCreateEntityWithEnum() throws Exception { - Referenceable dbEntity = createDBEntity(); - String db = createInstance(dbEntity); + public void testUpdateEntityByUniqueAttribute() throws Exception { + final List colNameList = ImmutableList.of("col1", "col2"); + Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("columnNames", colNameList); + }}); + metadataService.updateEntityByUniqueAttribute(table.getTypeName(), "name", (String) table.get("name"), tableUpdated); - Referenceable table = new Referenceable(TestUtils.TABLE_TYPE); - table.set("name", TestUtils.randomString()); - table.set("description", "random table"); - table.set("type", "type"); - table.set("tableType", "MANAGED"); - table.set("database", dbEntity); - createInstance(table); + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + List actualColumns = (List) tableDefinition.get("columnNames"); + Assert.assertEquals(actualColumns, colNameList); + } + + @Test + public void testUpdateEntityWithMap() throws Exception { + + final Map partsMap = new HashMap<>(); + partsMap.put("part0", new Struct("partition_type", + new HashMap() {{ + put("name", "test"); + }})); + + table.set("partitionsMap", partsMap); + + updateInstance(table); + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertTrue(partsMap.get("part0").equalsContents(((Map)tableDefinition.get("partitionsMap")).get("part0"))); + + //update map - add a map key + partsMap.put("part1", new Struct("partition_type", + new HashMap() {{ + put("name", "test1"); + }})); + table.set("partitionsMap", partsMap); + updateInstance(table); + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertEquals(((Map)tableDefinition.get("partitionsMap")).size(), 2); + Assert.assertTrue(partsMap.get("part1").equalsContents(((Map)tableDefinition.get("partitionsMap")).get("part1"))); + + //update map - remove a key and add another key + partsMap.remove("part0"); + partsMap.put("part2", new Struct("partition_type", + new HashMap() {{ + put("name", "test2"); + }})); + table.set("partitionsMap", partsMap); + + updateInstance(table); + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertEquals(((Map)tableDefinition.get("partitionsMap")).size(), 2); + Assert.assertNull(((Map)tableDefinition.get("partitionsMap")).get("part0")); + Assert.assertTrue(partsMap.get("part2").equalsContents(((Map)tableDefinition.get("partitionsMap")).get("part2"))); + + + //update struct value for existing map key + Struct partition2 = (Struct)partsMap.get("part2"); + partition2.set("name", "test2Updated"); + updateInstance(table); + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertEquals(((Map)tableDefinition.get("partitionsMap")).size(), 2); + Assert.assertNull(((Map)tableDefinition.get("partitionsMap")).get("part0")); + Assert.assertTrue(partsMap.get("part2").equalsContents(((Map)tableDefinition.get("partitionsMap")).get("part2"))); + } + + @Test + public void testUpdateEntityAddAndUpdateArrayAttr() throws Exception { + //Update entity, add new array attribute + //add array of primitives + final List colNameList = ImmutableList.of("col1", "col2"); + Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("columnNames", colNameList); + }}); + metadataService.updateEntityPartialByGuid(tableId._getId(), tableUpdated); + + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + List actualColumns = (List) tableDefinition.get("columnNames"); + Assert.assertEquals(actualColumns, colNameList); + + //update array of primitives + final List updatedColNameList = ImmutableList.of("col2", "col3"); + tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("columnNames", updatedColNameList); + }}); + metadataService.updateEntityPartialByGuid(tableId.getId()._getId(), tableUpdated); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + actualColumns = (List) tableDefinition.get("columnNames"); + Assert.assertEquals(actualColumns, updatedColNameList); + } + + @Test + public void testUpdateEntityArrayOfClass() throws Exception { + //test array of class with id + final List columns = new ArrayList<>(); + Map values = new HashMap<>(); + values.put("name", "col1"); + values.put("type", "type"); + Referenceable ref = new Referenceable("column_type", values); + columns.add(ref); + Referenceable tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("columns", columns); + }}); + metadataService.updateEntityPartialByGuid(tableId._getId(), tableUpdated); + + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + final List arrClsColumns = (List) tableDefinition.get("columns"); + Assert.assertTrue(arrClsColumns.get(0).equalsContents(columns.get(0))); + + //Partial update. Add col5 But also update col1 + Map valuesCol5 = new HashMap<>(); + valuesCol5.put("name", "col5"); + valuesCol5.put("type", "type"); + ref = new Referenceable("column_type", valuesCol5); + //update col1 + arrClsColumns.get(0).set("type", "type1"); + + //add col5 + final List updateColumns = new ArrayList<>(arrClsColumns); + updateColumns.add(ref); + + tableUpdated = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("columns", updateColumns); + }}); + metadataService.updateEntityPartialByGuid(tableId._getId(), tableUpdated); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + List arrColumnsList = (List) tableDefinition.get("columns"); + Assert.assertEquals(arrColumnsList.size(), 2); + Assert.assertTrue(arrColumnsList.get(0).equalsContents(updateColumns.get(0))); + Assert.assertTrue(arrColumnsList.get(1).equalsContents(updateColumns.get(1))); + + //Complete update. Add array elements - col3,4 + Map values1 = new HashMap<>(); + values1.put("name", "col3"); + values1.put("type", "type"); + Referenceable ref1 = new Referenceable("column_type", values1); + columns.add(ref1); + + Map values2 = new HashMap<>(); + values2.put("name", "col4"); + values2.put("type", "type"); + Referenceable ref2 = new Referenceable("column_type", values2); + columns.add(ref2); + + table.set("columns", columns); + updateInstance(table); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + arrColumnsList = (List) tableDefinition.get("columns"); + Assert.assertEquals(arrColumnsList.size(), columns.size()); + Assert.assertTrue(arrColumnsList.get(1).equalsContents(columns.get(1))); + Assert.assertTrue(arrColumnsList.get(2).equalsContents(columns.get(2))); + + + //Remove a class reference/Id and insert another reference + //Also covers isComposite case since columns is a composite + values.clear(); + columns.clear(); + + values.put("name", "col2"); + values.put("type", "type"); + ref = new Referenceable("column_type", values); + columns.add(ref); + table.set("columns", columns); + updateInstance(table); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + arrColumnsList = (List) tableDefinition.get("columns"); + Assert.assertEquals(arrColumnsList.size(), columns.size()); + Assert.assertTrue(arrColumnsList.get(0).equalsContents(columns.get(0))); + + //Update array column to null + table.setNull("columns"); + String newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + Assert.assertNull(tableDefinition.get("columns")); + } + + + @Test + public void testStructs() throws Exception { + Struct serdeInstance = new Struct(TestUtils.SERDE_TYPE); + serdeInstance.set("name", "serde1Name"); + serdeInstance.set("serde", "test"); + serdeInstance.set("description", "testDesc"); + table.set("serde1", serdeInstance); + + String newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + Assert.assertNotNull(tableDefinition.get("serde1")); + Assert.assertTrue(serdeInstance.equalsContents(tableDefinition.get("serde1"))); + + //update struct attribute + serdeInstance.set("serde", "testUpdated"); + updateInstance(table); + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertTrue(serdeInstance.equalsContents(tableDefinition.get("serde1"))); + + //set to null + serdeInstance.setNull("description"); + updateInstance(table); + tableDefinitionJson = + metadataService.getEntityDefinition(tableId._getId()); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + Assert.assertNull(((Struct)tableDefinition.get("serde1")).get("description")); + } + + @Test + public void testClassUpdate() throws Exception { + //Create new db instance + final Referenceable databaseInstance = new Referenceable(TestUtils.DATABASE_TYPE); + databaseInstance.set("name", TestUtils.randomString()); + databaseInstance.set("description", "new database"); + + String dbId = createInstance(databaseInstance); + + /*Update reference property with Id */ + metadataService.updateEntityAttributeByGuid(tableId._getId(), "database", dbId); + + String tableDefinitionJson = + metadataService.getEntityDefinition(tableId._getId()); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertEquals(dbId, (((Id)tableDefinition.get("database"))._getId())); + + /* Update with referenceable - TODO - Fails . Need to fix this */ + /*final String dbName = TestUtils.randomString(); + final Referenceable databaseInstance2 = new Referenceable(TestUtils.DATABASE_TYPE); + databaseInstance2.set("name", dbName); + databaseInstance2.set("description", "new database 2"); + + Referenceable updateTable = new Referenceable(TestUtils.TABLE_TYPE, new HashMap() {{ + put("database", databaseInstance2); + }}); + metadataService.updateEntityAttributeByGuid(tableId._getId(), updateTable); + + tableDefinitionJson = + metadataService.getEntityDefinition(tableId._getId()); + Referenceable tableDefinitionActual = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + String dbDefJson = metadataService.getEntityDefinition(TestUtils.DATABASE_TYPE, "name", dbName); + Referenceable dbDef = InstanceSerialization.fromJsonReferenceable(dbDefJson, true); + + Assert.assertNotEquals(dbId, (((Id) tableDefinitionActual.get("database"))._getId())); + Assert.assertEquals(dbDef.getId()._getId(), (((Id) tableDefinitionActual.get("database"))._getId())); */ + + } + + @Test + public void testArrayOfStructs() throws Exception { + //Add array of structs + TestUtils.dumpGraph(graphProvider.get()); + + final Struct partition1 = new Struct(TestUtils.PARTITION_TYPE); + partition1.set("name", "part1"); + + final Struct partition2 = new Struct(TestUtils.PARTITION_TYPE); + partition2.set("name", "part2"); + + List partitions = new ArrayList(){{ add(partition1); add(partition2); }}; + table.set("partitions", partitions); + + String newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNotNull(tableDefinition.get("partitions")); + List partitionsActual = (List) tableDefinition.get("partitions"); + Assert.assertEquals(partitionsActual.size(), 2); + Assert.assertTrue(partitions.get(0).equalsContents(partitionsActual.get(0))); + + //add a new element to array of struct + final Struct partition3 = new Struct(TestUtils.PARTITION_TYPE); + partition3.set("name", "part3"); + partitions.add(partition3); + table.set("partitions", partitions); + newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNotNull(tableDefinition.get("partitions")); + partitionsActual = (List) tableDefinition.get("partitions"); + Assert.assertEquals(partitionsActual.size(), 3); + Assert.assertTrue(partitions.get(2).equalsContents(partitionsActual.get(2))); + + //remove one of the struct values + partitions.remove(1); + table.set("partitions", partitions); + newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNotNull(tableDefinition.get("partitions")); + partitionsActual = (List) tableDefinition.get("partitions"); + Assert.assertEquals(partitionsActual.size(), 2); + Assert.assertTrue(partitions.get(0).equalsContents(partitionsActual.get(0))); + Assert.assertTrue(partitions.get(1).equalsContents(partitionsActual.get(1))); + + //Update struct value within array of struct + partition1.set("name", "part4"); + newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNotNull(tableDefinition.get("partitions")); + partitionsActual = (List) tableDefinition.get("partitions"); + Assert.assertEquals(partitionsActual.size(), 2); + Assert.assertTrue(partitions.get(0).equalsContents(partitionsActual.get(0))); + + //add a repeated element to array of struct + final Struct partition4 = new Struct(TestUtils.PARTITION_TYPE); + partition4.set("name", "part4"); + partitions.add(partition4); + table.set("partitions", partitions); + newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNotNull(tableDefinition.get("partitions")); + partitionsActual = (List) tableDefinition.get("partitions"); + Assert.assertEquals(partitionsActual.size(), 3); + Assert.assertEquals(partitionsActual.get(2).get("name"), "part4"); + Assert.assertEquals(partitionsActual.get(0).get("name"), "part4"); + Assert.assertTrue(partitions.get(2).equalsContents(partitionsActual.get(2))); + + + // Remove all elements. Should set array attribute to null + partitions.clear(); + newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertNull(tableDefinition.get("partitions")); + } + + + @Test(expectedExceptions = ValueConversionException.class) + public void testUpdateRequiredAttrToNull() throws Exception { + //Update required attribute + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + Assert.assertEquals(tableDefinition.get("description"), "random table"); + table.setNull("description"); + + updateInstance(table); + Assert.fail("Expected exception while updating required attribute to null"); + } + + @Test + public void testUpdateOptionalAttrToNull() throws Exception { + + String tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + + //Update optional Attribute + Assert.assertNotNull(tableDefinition.get("created")); + //Update optional attribute + table.setNull("created"); + + String newtableId = updateInstance(table); + Assert.assertEquals(newtableId, tableId._getId()); + + tableDefinitionJson = + metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); + tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); + Assert.assertNull(tableDefinition.get("created")); + } + + @Test + public void testCreateEntityWithEnum() throws Exception { String tableDefinitionJson = metadataService.getEntityDefinition(TestUtils.TABLE_TYPE, "name", (String) table.get("name")); Referenceable tableDefinition = InstanceSerialization.fromJsonReferenceable(tableDefinitionJson, true); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/repository/src/test/scala/org/apache/atlas/query/GremlinTest.scala ---------------------------------------------------------------------- diff --git a/repository/src/test/scala/org/apache/atlas/query/GremlinTest.scala b/repository/src/test/scala/org/apache/atlas/query/GremlinTest.scala index 1097828..0b57df3 100755 --- a/repository/src/test/scala/org/apache/atlas/query/GremlinTest.scala +++ b/repository/src/test/scala/org/apache/atlas/query/GremlinTest.scala @@ -39,7 +39,6 @@ class GremlinTest extends BaseGremlinTest { gProvider = new TitanGraphProvider(); gp = new DefaultGraphPersistenceStrategy(new GraphBackedMetadataRepository(gProvider)) g = QueryTestsUtils.setupTestGraph(gProvider) - } @AfterClass http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/pom.xml ---------------------------------------------------------------------- diff --git a/server-api/pom.xml b/server-api/pom.xml new file mode 100644 index 0000000..88de030 --- /dev/null +++ b/server-api/pom.xml @@ -0,0 +1,53 @@ + + + + + apache-atlas + org.apache.atlas + 0.6-incubating-SNAPSHOT + + 4.0.0 + + atlas-server-api + + Apache Atlas Server API + Apache Atlas Server related APIs + jar + + + + org.testng + testng + + + + com.google.inject + guice + + + + org.apache.atlas + atlas-typesystem + + + + + \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryException.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryException.java b/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryException.java new file mode 100644 index 0000000..ba69af7 --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryException.java @@ -0,0 +1,74 @@ +/** + * 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.discovery; + +import org.apache.atlas.AtlasException; + +import java.security.PrivilegedActionException; + +public class DiscoveryException extends AtlasException { + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public DiscoveryException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and + * cause.

Note that the detail message associated with + * {@code cause} is not automatically incorporated in + * this exception's detail message. + * + * @param message the detail message (which is saved for later retrieval + * by the {@link #getMessage()} method). + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public DiscoveryException(String message, Throwable cause) { + super(message, cause); + } + + /** + * Constructs a new exception with the specified cause and a detail + * message of (cause==null ? null : cause.toString()) (which + * typically contains the class and detail message of cause). + * This constructor is useful for exceptions that are little more than + * wrappers for other throwables (for example, {@link + * PrivilegedActionException}). + * + * @param cause the cause (which is saved for later retrieval by the + * {@link #getCause()} method). (A null value is + * permitted, and indicates that the cause is nonexistent or + * unknown.) + * @since 1.4 + */ + public DiscoveryException(Throwable cause) { + super(cause); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java b/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java new file mode 100644 index 0000000..e347c2c --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/discovery/DiscoveryService.java @@ -0,0 +1,52 @@ +/** + * 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.discovery; + +import java.util.List; +import java.util.Map; + +/** + * Metadata discovery service. + */ +public interface DiscoveryService { + + /** + * Full text search + */ + String searchByFullText(String query) throws DiscoveryException; + + /** + * Search using query DSL. + * + * @param dslQuery query in DSL format. + * @return JSON representing the type and results. + */ + String searchByDSL(String dslQuery) throws DiscoveryException; + + /** + * Assumes the User is familiar with the persistence structure of the Repository. + * The given query is run uninterpreted against the underlying Graph Store. + * The results are returned as a List of Rows. each row is a Map of Key,Value pairs. + * + * @param gremlinQuery query in gremlin dsl format + * @return List of Maps + * @throws org.apache.atlas.discovery.DiscoveryException + */ + List> searchByGremlin(String gremlinQuery) throws DiscoveryException; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/discovery/LineageService.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/discovery/LineageService.java b/server-api/src/main/java/org/apache/atlas/discovery/LineageService.java new file mode 100644 index 0000000..8dc36cd --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/discovery/LineageService.java @@ -0,0 +1,67 @@ +/** + * 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.discovery; + +import org.apache.atlas.AtlasException; + +/** + * Lineage service interface. + */ +public interface LineageService { + + /** + * Return the lineage outputs for the given tableName. + * + * @param tableName tableName + * @return Outputs as JSON + */ + String getOutputs(String tableName) throws AtlasException; + + /** + * Return the lineage outputs graph for the given tableName. + * + * @param tableName tableName + * @return Outputs Graph as JSON + */ + String getOutputsGraph(String tableName) throws AtlasException; + + /** + * Return the lineage inputs for the given tableName. + * + * @param tableName tableName + * @return Inputs as JSON + */ + String getInputs(String tableName) throws AtlasException; + + /** + * Return the lineage inputs graph for the given tableName. + * + * @param tableName tableName + * @return Inputs Graph as JSON + */ + String getInputsGraph(String tableName) throws AtlasException; + + /** + * Return the schema for the given tableName. + * + * @param tableName tableName + * @return Schema as JSON + */ + String getSchema(String tableName) throws AtlasException; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/listener/EntityChangeListener.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/listener/EntityChangeListener.java b/server-api/src/main/java/org/apache/atlas/listener/EntityChangeListener.java new file mode 100644 index 0000000..619ed85 --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/listener/EntityChangeListener.java @@ -0,0 +1,69 @@ +/** + * 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.listener; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.typesystem.IStruct; +import org.apache.atlas.typesystem.ITypedReferenceableInstance; + +import java.util.Collection; + +/** + * Entity (a Typed instance) change notification listener. + */ +public interface EntityChangeListener { + + /** + * This is upon adding new entities to the repository. + * + * @param entities the created entities + * + * @throws AtlasException if the listener notification fails + */ + void onEntitiesAdded(Collection entities) throws AtlasException; + + /** + * This is upon updating an entity. + * + * @param entities the updated entities + * + * @throws AtlasException if the listener notification fails + */ + void onEntitiesUpdated(Collection entities) throws AtlasException; + + /** + * This is upon adding a new trait to a typed instance. + * + * @param entity the entity + * @param trait trait that needs to be added to entity + * + * @throws AtlasException if the listener notification fails + */ + void onTraitAdded(ITypedReferenceableInstance entity, IStruct trait) throws AtlasException; + + /** + * This is upon deleting a trait from a typed instance. + * + * @param entity the entity + * @param traitName trait name for the instance that needs to be deleted from entity + * + * @throws AtlasException if the listener notification fails + */ + void onTraitDeleted(ITypedReferenceableInstance entity, String traitName) throws AtlasException; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/listener/TypesChangeListener.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/listener/TypesChangeListener.java b/server-api/src/main/java/org/apache/atlas/listener/TypesChangeListener.java new file mode 100644 index 0000000..5ff6d4a --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/listener/TypesChangeListener.java @@ -0,0 +1,49 @@ +/** + * 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.listener; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.typesystem.types.IDataType; + +import java.util.Collection; + +/** + * Types change notification listener. + */ +public interface TypesChangeListener { + + /** + * This is upon adding new type(s) to Store. + * + * @param dataTypes data type + * @throws AtlasException + */ + void onAdd(Collection dataTypes) throws AtlasException; + + /** + * This is upon removing an existing type from the Store. + * + * @param typeName type name + * @throws AtlasException + */ + // void onRemove(String typeName) throws MetadataException; + + //This is upon updating an existing type to the store + void onChange(Collection dataTypes) throws AtlasException; +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/services/MetadataService.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/services/MetadataService.java b/server-api/src/main/java/org/apache/atlas/services/MetadataService.java new file mode 100644 index 0000000..0cfed2e --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/services/MetadataService.java @@ -0,0 +1,187 @@ +/** + * 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.services; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.listener.EntityChangeListener; +import org.apache.atlas.typesystem.Referenceable; +import org.apache.atlas.typesystem.types.DataTypes; +import org.codehaus.jettison.json.JSONObject; + +import java.util.List; + +/** + * Metadata service. + */ +public interface MetadataService { + + /** + * Creates a new type based on the type system to enable adding + * entities (instances for types). + * + * @param typeDefinition definition as json + * @return a unique id for this type + */ + JSONObject createType(String typeDefinition) throws AtlasException; + + /** + * Updates the given types in the type definition + * @param typeDefinition + * @return + * @throws AtlasException + */ + JSONObject updateType(String typeDefinition) throws AtlasException; + + /** + * Return the definition for the given type. + * + * @param typeName name for this type, must be unique + * @return type definition as JSON + */ + String getTypeDefinition(String typeName) throws AtlasException; + + /** + * Return the list of types in the type system. + * + * @return list of type names in the type system + */ + List getTypeNamesList() throws AtlasException; + + /** + * Return the list of trait type names in the type system. + * + * @return list of trait type names in the type system + */ + List getTypeNamesByCategory(DataTypes.TypeCategory typeCategory) throws AtlasException; + + /** + * Creates an entity, instance of the type. + * + * @param entityDefinition definition + * @return guid + */ + String createEntities(String entityDefinition) throws AtlasException; + + /** + * Return the definition for the given guid. + * + * @param guid guid + * @return entity definition as JSON + */ + String getEntityDefinition(String guid) throws AtlasException; + + /** + * Return the definition given type and attribute. The attribute has to be unique attribute for the type + * @param entityType - type name + * @param attribute - attribute name + * @param value - attribute value + * @return + * @throws AtlasException + */ + String getEntityDefinition(String entityType, String attribute, String value) throws AtlasException; + + /** + * Return the list of entity names for the given type in the repository. + * + * @param entityType type + * @return list of entity names for the given type in the repository + */ + List getEntityList(String entityType) throws AtlasException; + + /** + * Adds the property to the given entity id(guid). + * Currently supports updates only on PRIMITIVE, CLASS attribute types + * + * @param guid entity id + * @param attribute property name + * @param value property value + */ + void updateEntityAttributeByGuid(String guid, String attribute, String value) throws AtlasException; + + /** + * Supports Partial updates of an entity. Users can update a subset of attributes for an entity identified by its guid + * Note however that it cannot be used to set attribute values to null or delete attrbute values + * + */ + void updateEntityPartialByGuid(String guid, Referenceable entity) throws AtlasException; + + /** + * Batch API - Adds/Updates the given entity id(guid). + * + * @param entityJson entity json + * @return List of guids which were updated and ones which were newly created as part of the updated entity + */ + String updateEntities(String entityJson) throws AtlasException; + + // Trait management functions + + /** + * Updates entity identified by a qualified name + * + * @param typeName + * @param uniqueAttributeName + * @param attrValue + * @param updatedEntity + * @return Guid of updated entity + * @throws AtlasException + */ + String updateEntityByUniqueAttribute(String typeName, String uniqueAttributeName, String attrValue, + Referenceable updatedEntity) throws AtlasException; + + /** + * Gets the list of trait names for a given entity represented by a guid. + * + * @param guid globally unique identifier for the entity + * @return a list of trait names for the given entity guid + * @throws AtlasException + */ + List getTraitNames(String guid) throws AtlasException; + + /** + * Adds a new trait to an existing entity represented by a guid. + * + * @param guid globally unique identifier for the entity + * @param traitInstanceDefinition trait instance that needs to be added to entity + * @throws AtlasException + */ + void addTrait(String guid, String traitInstanceDefinition) throws AtlasException; + + /** + * Deletes a given trait from an existing entity represented by a guid. + * + * @param guid globally unique identifier for the entity + * @param traitNameToBeDeleted name of the trait + * @throws AtlasException + */ + void deleteTrait(String guid, String traitNameToBeDeleted) throws AtlasException; + + /** + * Register a listener for entity change. + * + * @param listener the listener to register + */ + void registerListener(EntityChangeListener listener); + + /** + * Unregister an entity change listener. + * + * @param listener the listener to unregister + */ + void unregisterListener(EntityChangeListener listener); +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityExistsException.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityExistsException.java b/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityExistsException.java new file mode 100644 index 0000000..b16cfa9 --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityExistsException.java @@ -0,0 +1,32 @@ +/** + * 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.typesystem.exception; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.typesystem.IReferenceableInstance; + +public class EntityExistsException extends AtlasException { + public EntityExistsException(IReferenceableInstance typedInstance, Exception e) { + super("Model violation for type "+ typedInstance.getTypeName(), e); + } + + public EntityExistsException(IReferenceableInstance typedInstance) { + super("Model violation for type "+ typedInstance.getTypeName()); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityNotFoundException.java ---------------------------------------------------------------------- diff --git a/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityNotFoundException.java b/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityNotFoundException.java new file mode 100644 index 0000000..0fec895 --- /dev/null +++ b/server-api/src/main/java/org/apache/atlas/typesystem/exception/EntityNotFoundException.java @@ -0,0 +1,46 @@ +/** + * 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.typesystem.exception; + +import org.apache.atlas.AtlasException; + +/** + * A simple wrapper for 404. + */ +public class EntityNotFoundException extends AtlasException { + public EntityNotFoundException() { + } + + public EntityNotFoundException(String message) { + super(message); + } + + public EntityNotFoundException(String message, Throwable cause) { + super(message, cause); + } + + public EntityNotFoundException(Throwable cause) { + super(cause); + } + + public EntityNotFoundException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/pom.xml ---------------------------------------------------------------------- diff --git a/typesystem/pom.xml b/typesystem/pom.xml index efb49ed..129de58 100755 --- a/typesystem/pom.xml +++ b/typesystem/pom.xml @@ -110,13 +110,8 @@ - com.google.inject - guice - - - - commons-configuration - commons-configuration + org.apache.atlas + atlas-common http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/ApplicationProperties.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/ApplicationProperties.java b/typesystem/src/main/java/org/apache/atlas/ApplicationProperties.java deleted file mode 100644 index 738ec53..0000000 --- a/typesystem/src/main/java/org/apache/atlas/ApplicationProperties.java +++ /dev/null @@ -1,86 +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 - * - * 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; - -import org.apache.commons.configuration.CompositeConfiguration; -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.configuration.PropertiesConfiguration; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.net.URL; -import java.util.Arrays; -import java.util.Iterator; - -public class ApplicationProperties extends PropertiesConfiguration { - private static final Logger LOG = LoggerFactory.getLogger(ApplicationProperties.class); - - public static final String APPLICATION_PROPERTIES = "application.properties"; - public static final String CLIENT_PROPERTIES = "client.properties"; - - private static Configuration INSTANCE = null; - - private ApplicationProperties(URL url) throws ConfigurationException { - super(url); - } - - public static Configuration get() throws AtlasException { - if (INSTANCE == null) { - synchronized (ApplicationProperties.class) { - if (INSTANCE == null) { - Configuration applicationProperties = get(APPLICATION_PROPERTIES); - Configuration clientProperties = get(CLIENT_PROPERTIES); - INSTANCE = new CompositeConfiguration(Arrays.asList(applicationProperties, clientProperties)); - } - } - } - return INSTANCE; - } - - public static Configuration get(String fileName) throws AtlasException { - String confLocation = System.getProperty("atlas.conf"); - try { - URL url = confLocation == null ? ApplicationProperties.class.getResource("/" + fileName) - : new File(confLocation, fileName).toURI().toURL(); - LOG.info("Loading {} from {}", fileName, url); - - Configuration configuration = new ApplicationProperties(url).interpolatedConfiguration(); - logConfiguration(configuration); - return configuration; - } catch (Exception e) { - throw new AtlasException("Failed to load application properties", e); - } - } - - private static void logConfiguration(Configuration configuration) { - if (LOG.isDebugEnabled()) { - Iterator keys = configuration.getKeys(); - LOG.debug("Configuration loaded:"); - while (keys.hasNext()) { - String key = keys.next(); - LOG.debug("{} = {}", key, configuration.getProperty(key)); - } - } - } - - public static final Configuration getSubsetConfiguration(Configuration inConf, String prefix) { - return inConf.subset(prefix); - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/AtlasException.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/AtlasException.java b/typesystem/src/main/java/org/apache/atlas/AtlasException.java deleted file mode 100755 index 2eb0658..0000000 --- a/typesystem/src/main/java/org/apache/atlas/AtlasException.java +++ /dev/null @@ -1,44 +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 - * - * 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; - -/** - * Base Exception class for metadata API. - */ -public class AtlasException extends Exception { - - public AtlasException() { - } - - public AtlasException(String message) { - super(message); - } - - public AtlasException(String message, Throwable cause) { - super(message, cause); - } - - public AtlasException(Throwable cause) { - super(cause); - } - - public AtlasException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/ParamChecker.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/ParamChecker.java b/typesystem/src/main/java/org/apache/atlas/ParamChecker.java deleted file mode 100644 index e900ba3..0000000 --- a/typesystem/src/main/java/org/apache/atlas/ParamChecker.java +++ /dev/null @@ -1,148 +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 - * - * 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; - -import java.util.Arrays; -import java.util.Collection; - -public class ParamChecker { - - /** - * Check that a value is not null. If null throws an IllegalArgumentException. - * - * @param obj value. - * @param name parameter name for the exception message. - * @return the given value. - */ - public static T notNull(T obj, String name) { - if (obj == null) { - throw new IllegalArgumentException(name + " cannot be null"); - } - return obj; - } - - /** - * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements - * throws an IllegalArgumentException. - * @param list the list of T. - * @param name parameter name for the exception message. - */ - public static Collection notNullElements(Collection list, String name) { - notEmpty(list, name); - for (T ele : list) { - notNull(ele, String.format("Collection %s element %s", name, ele)); - } - return list; - } - - /** - * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements - * throws an IllegalArgumentException. - * @param array the array of T. - * @param name parameter name for the exception message. - */ - public static T[] notNullElements(T[] array, String name) { - notEmpty(Arrays.asList(array), name); - for (T ele : array) { - notNull(ele, String.format("Collection %s element %s", name, ele)); - } - return array; - } - - /** - * Check that a list is not null and not empty. - * @param list the list of T. - * @param name parameter name for the exception message. - */ - public static Collection notEmpty(Collection list, String name) { - notNull(list, name); - if (list.isEmpty()) { - throw new IllegalArgumentException(String.format("Collection %s is empty", name)); - } - return list; - } - - /** - * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. - * - * @param value value. - * @param name parameter name for the exception message. - * @return the given value. - */ - public static String notEmpty(String value, String name) { - return notEmpty(value, name, null); - } - - /** - * Check that a string is not empty if its not null. - * - * @param value value. - * @param name parameter name for the exception message. - * @return the given value. - */ - public static String notEmptyIfNotNull(String value, String name) { - return notEmptyIfNotNull(value, name, null); - } - - /** - * Check that a string is not empty if its not null. - * - * @param value value. - * @param name parameter name for the exception message. - * @return the given value. - */ - public static String notEmptyIfNotNull(String value, String name, String info) { - if (value == null) { - return value; - } - - if (value.trim().length() == 0) { - throw new IllegalArgumentException(name + " cannot be empty" + (info == null ? "" : ", " + info)); - } - return value.trim(); - } - - /** - * Check that a string is not null and not empty. If null or emtpy throws an IllegalArgumentException. - * - * @param value value. - * @param name parameter name for the exception message. - * @param info additional information to be printed with the exception message - * @return the given value. - */ - public static String notEmpty(String value, String name, String info) { - if (value == null) { - throw new IllegalArgumentException(name + " cannot be null" + (info == null ? "" : ", " + info)); - } - return notEmptyIfNotNull(value, name, info); - } - - /** - * Check that a list is not null and that none of its elements is null. If null or if the list has emtpy elements - * throws an IllegalArgumentException. - * @param list the list of strings. - * @param name parameter name for the exception message. - */ - public static Collection notEmptyElements(Collection list, String name) { - notEmpty(list, name); - for (String ele : list) { - notEmpty(ele, String.format("list %s element %s", name, ele)); - } - return list; - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/TypeExistsException.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/TypeExistsException.java b/typesystem/src/main/java/org/apache/atlas/TypeExistsException.java deleted file mode 100644 index 1a2cb7c..0000000 --- a/typesystem/src/main/java/org/apache/atlas/TypeExistsException.java +++ /dev/null @@ -1,25 +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 - *

- * 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; - -public class TypeExistsException extends AtlasException { - public TypeExistsException(String message) { - super(message); - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/TypeNotFoundException.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/TypeNotFoundException.java b/typesystem/src/main/java/org/apache/atlas/TypeNotFoundException.java deleted file mode 100644 index 348dd57..0000000 --- a/typesystem/src/main/java/org/apache/atlas/TypeNotFoundException.java +++ /dev/null @@ -1,44 +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 - * - * 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; - -/** - * A simple wrapper for 404. - */ -public class TypeNotFoundException extends AtlasException { - public TypeNotFoundException() { - } - - public TypeNotFoundException(String message) { - super(message); - } - - public TypeNotFoundException(String message, Throwable cause) { - super(message, cause); - } - - public TypeNotFoundException(Throwable cause) { - super(cause); - } - - public TypeNotFoundException(String message, Throwable cause, boolean enableSuppression, - boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/typesystem/IInstance.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/IInstance.java b/typesystem/src/main/java/org/apache/atlas/typesystem/IInstance.java index c903301..ffe40a7 100755 --- a/typesystem/src/main/java/org/apache/atlas/typesystem/IInstance.java +++ b/typesystem/src/main/java/org/apache/atlas/typesystem/IInstance.java @@ -33,6 +33,8 @@ public interface IInstance { void set(String attrName, Object val) throws AtlasException; + void setNull(String attrName) throws AtlasException; + Map getValuesMap() throws AtlasException; } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/typesystem/ITypedInstance.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/ITypedInstance.java b/typesystem/src/main/java/org/apache/atlas/typesystem/ITypedInstance.java index c951172..d7f4cb7 100755 --- a/typesystem/src/main/java/org/apache/atlas/typesystem/ITypedInstance.java +++ b/typesystem/src/main/java/org/apache/atlas/typesystem/ITypedInstance.java @@ -23,6 +23,7 @@ import org.apache.atlas.typesystem.types.FieldMapping; import java.math.BigDecimal; import java.math.BigInteger; +import java.security.MessageDigest; import java.util.Date; /** @@ -37,8 +38,6 @@ public interface ITypedInstance extends IInstance { FieldMapping fieldMapping(); - void setNull(String attrName) throws AtlasException; - boolean getBoolean(String attrName) throws AtlasException; byte getByte(String attrName) throws AtlasException; @@ -82,4 +81,6 @@ public interface ITypedInstance extends IInstance { void setDate(String attrName, Date val) throws AtlasException; void setString(String attrName, String val) throws AtlasException; + + String getSignatureHash(MessageDigest digester) throws AtlasException; } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/typesystem/Referenceable.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/Referenceable.java b/typesystem/src/main/java/org/apache/atlas/typesystem/Referenceable.java index aaf0aa4..b8dcc7e 100755 --- a/typesystem/src/main/java/org/apache/atlas/typesystem/Referenceable.java +++ b/typesystem/src/main/java/org/apache/atlas/typesystem/Referenceable.java @@ -24,7 +24,6 @@ import org.apache.atlas.AtlasException; import org.apache.atlas.classification.InterfaceAudience; import org.apache.atlas.typesystem.persistence.Id; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -95,8 +94,10 @@ public class Referenceable extends Struct implements IReferenceableInstance { */ @SuppressWarnings("unused") private Referenceable() { - this("", "", Collections.emptyMap(), Collections.emptyList(), - Collections.emptyMap()); + super(null, null); + id = null; + traitNames = ImmutableList.of(); + traits = ImmutableMap.of(); } @Override @@ -114,6 +115,42 @@ public class Referenceable extends Struct implements IReferenceableInstance { return traits.get(typeName); } + /** + * Matches traits, values associated with this Referenceable and skips the id match + * @param o The Referenceable which needs to be matched with + * @return + */ + public boolean equalsContents(Object o) { + if(this == o) { + return true; + } + if(o == null) { + return false; + } + if (o.getClass() != getClass()) { + return false; + } + + if(!super.equalsContents(o)) { + return false; + } + + Referenceable obj = (Referenceable)o; + if (!traitNames.equals(obj.getTraits())) { + return false; + } + + return true; + } + + public String toString() { + return "{" + + "Id='" + id + '\'' + + ", traits=" + traitNames + + ", values=" + getValuesMap() + + '}'; + } + private static Map getTraits(IReferenceableInstance instance) throws AtlasException { Map traits = new HashMap<>(); for (String traitName : instance.getTraits() ) { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/51656991/typesystem/src/main/java/org/apache/atlas/typesystem/Struct.java ---------------------------------------------------------------------- diff --git a/typesystem/src/main/java/org/apache/atlas/typesystem/Struct.java b/typesystem/src/main/java/org/apache/atlas/typesystem/Struct.java index d03e2c2..70deab2 100755 --- a/typesystem/src/main/java/org/apache/atlas/typesystem/Struct.java +++ b/typesystem/src/main/java/org/apache/atlas/typesystem/Struct.java @@ -18,6 +18,7 @@ package org.apache.atlas.typesystem; +import org.apache.atlas.AtlasException; import org.apache.atlas.classification.InterfaceAudience; import java.util.Collections; @@ -67,7 +68,52 @@ public class Struct implements IStruct { } @Override + public void setNull(String attrName) throws AtlasException { + values.remove(attrName); + } + + @Override public Map getValuesMap() { return values; } + + @Override + public int hashCode() { + int result = typeName.hashCode(); + result = 31 * result + values.hashCode(); + return result; + } + + /** + * equalContents instead of equals since values is a mutable attribute and could lead + * to incorrect behaviour when added to collections and mutated after that + * i.e when the attribute is mutated collections.contains(struct) returns false + * due to hashcode having changed for the struct. + * @param o + * @return + */ + public boolean equalsContents(Object o) { + if (this == o) { + return true; + } + + if (o == null) { + return false; + } + + if (o.getClass() != getClass()) { + return false; + } + + Struct obj = (Struct)o; + if(!typeName.equals(obj.getTypeName())) { + return false; + } + + if(!values.equals(obj.getValuesMap())) { + return false; + } + + return true; + } }