ATLAS-693 Titan 0.5.4 implementation of graph db abstraction. (jnhagelb via dkantor)
Project: http://git-wip-us.apache.org/repos/asf/incubator-atlas/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-atlas/commit/4fa10b6a Tree: http://git-wip-us.apache.org/repos/asf/incubator-atlas/tree/4fa10b6a Diff: http://git-wip-us.apache.org/repos/asf/incubator-atlas/diff/4fa10b6a Branch: refs/heads/master Commit: 4fa10b6aecb248d09ee2a58b289a1d47f7d24419 Parents: 2ef0fc4 Author: Jeff Hagelberg <[email protected]> Authored: Fri Aug 5 23:22:41 2016 +0100 Committer: Dave Kantor <[email protected]> Committed: Fri Aug 5 23:22:41 2016 +0100 ---------------------------------------------------------------------- .gitignore | 1 + catalog/pom.xml | 9 +- .../org/apache/atlas/repository/Constants.java | 90 ++ distro/src/bin/atlas_start.py | 1 - distro/src/test/python/scripts/TestMetadata.py | 8 +- .../atlas/repository/graphdb/AtlasEdge.java | 20 +- .../repository/graphdb/AtlasEdgeDirection.java | 2 +- .../atlas/repository/graphdb/AtlasElement.java | 120 ++- .../atlas/repository/graphdb/AtlasGraph.java | 152 ++- .../repository/graphdb/AtlasGraphIndex.java | 61 ++ .../graphdb/AtlasGraphManagement.java | 92 +- .../repository/graphdb/AtlasGraphQuery.java | 71 +- .../repository/graphdb/AtlasIndexQuery.java | 20 +- .../repository/graphdb/AtlasPropertyKey.java | 30 + .../graphdb/AtlasSchemaViolationException.java | 2 +- .../atlas/repository/graphdb/AtlasVertex.java | 36 +- .../repository/graphdb/AtlasVertexQuery.java | 16 +- .../atlas/repository/graphdb/GraphDatabase.java | 22 +- .../repository/graphdb/GremlinVersion.java | 2 +- graphdb/common/pom.xml | 64 ++ .../titan/query/NativeTitanGraphQuery.java | 60 ++ .../titan/query/NativeTitanQueryFactory.java | 34 + .../graphdb/titan/query/TitanGraphQuery.java | 189 ++++ .../graphdb/titan/query/expr/AndCondition.java | 96 ++ .../graphdb/titan/query/expr/HasPredicate.java | 50 + .../graphdb/titan/query/expr/InPredicate.java | 49 + .../graphdb/titan/query/expr/OrCondition.java | 136 +++ .../titan/query/expr/QueryPredicate.java | 33 + graphdb/pom.xml | 2 + graphdb/titan0/pom.xml | 257 +++++ .../titan/diskstorage/hbase/AdminMask.java | 62 ++ .../titan/diskstorage/hbase/ConnectionMask.java | 30 + .../titan/diskstorage/hbase/HBaseAdmin0_98.java | 152 +++ .../titan/diskstorage/hbase/HBaseAdmin1_0.java | 135 +++ .../titan/diskstorage/hbase/HBaseCompat.java | 60 ++ .../diskstorage/hbase/HBaseCompat0_98.java | 58 ++ .../titan/diskstorage/hbase/HBaseCompat1_0.java | 58 ++ .../titan/diskstorage/hbase/HBaseCompat1_1.java | 58 ++ .../diskstorage/hbase/HBaseCompatLoader.java | 80 ++ .../hbase/HBaseKeyColumnValueStore.java | 425 ++++++++ .../diskstorage/hbase/HBaseStoreManager.java | 935 ++++++++++++++++++ .../diskstorage/hbase/HBaseTransaction.java | 75 ++ .../diskstorage/hbase/HConnection0_98.java | 49 + .../titan/diskstorage/hbase/HConnection1_0.java | 50 + .../titan/diskstorage/hbase/HTable0_98.java | 65 ++ .../titan/diskstorage/hbase/HTable1_0.java | 65 ++ .../titan/diskstorage/hbase/TableMask.java | 41 + .../diskstorage/locking/LocalLockMediator.java | 345 +++++++ .../titan/diskstorage/solr/Solr5Index.java | 975 +++++++++++++++++++ .../query/graph/GraphCentricQueryBuilder.java | 457 +++++++++ .../graphdb/titan0/GraphDbObjectFactory.java | 100 ++ .../graphdb/titan0/Titan0Database.java | 204 ++++ .../graphdb/titan0/Titan0DatabaseManager.java | 170 ++++ .../repository/graphdb/titan0/Titan0Edge.java | 62 ++ .../graphdb/titan0/Titan0Element.java | 267 +++++ .../repository/graphdb/titan0/Titan0Graph.java | 301 ++++++ .../graphdb/titan0/Titan0GraphIndex.java | 96 ++ .../graphdb/titan0/Titan0IndexQuery.java | 76 ++ .../graphdb/titan0/Titan0PropertyKey.java | 69 ++ .../repository/graphdb/titan0/Titan0Vertex.java | 135 +++ .../graphdb/titan0/Titan0VertexQuery.java | 65 ++ .../graphdb/titan0/TitanObjectFactory.java | 83 ++ .../titan0/query/NativeTitan0GraphQuery.java | 88 ++ .../graphdb/titan0/query/Titan0GraphQuery.java | 56 ++ .../atlas/utils/IteratorToIterableAdapter.java | 38 + .../hbase/HBaseKeyColumnValueStoreTest.java | 139 +++ .../locking/LocalLockMediatorTest.java | 60 ++ .../titan0/AbstractGraphDatabaseTest.java | 200 ++++ .../graphdb/titan0/GraphQueryTest.java | 447 +++++++++ .../graphdb/titan0/Titan0DatabaseTest.java | 428 ++++++++ .../titan0/Titan0DatabaseValidationTest.java | 77 ++ .../test/resources/atlas-application.properties | 97 ++ pom.xml | 113 +-- release-log.txt | 1 + repository/pom.xml | 17 +- .../apache/atlas/RepositoryMetadataModule.java | 5 +- .../org/apache/atlas/repository/Constants.java | 101 -- .../atlas/repository/graph/GraphHelper.java | 59 +- .../repository/graph/TitanGraphProvider.java | 115 +-- .../org/apache/atlas/query/TypeUtils.scala | 3 +- .../graph/TitanGraphProviderTest.java | 78 -- src/build/checkstyle-suppressions.xml | 3 + titan/pom.xml | 105 -- .../titan/diskstorage/hbase/AdminMask.java | 62 -- .../titan/diskstorage/hbase/ConnectionMask.java | 30 - .../titan/diskstorage/hbase/HBaseAdmin0_98.java | 152 --- .../titan/diskstorage/hbase/HBaseAdmin1_0.java | 135 --- .../titan/diskstorage/hbase/HBaseCompat.java | 60 -- .../diskstorage/hbase/HBaseCompat0_98.java | 58 -- .../titan/diskstorage/hbase/HBaseCompat1_0.java | 58 -- .../titan/diskstorage/hbase/HBaseCompat1_1.java | 58 -- .../diskstorage/hbase/HBaseCompatLoader.java | 80 -- .../hbase/HBaseKeyColumnValueStore.java | 425 -------- .../diskstorage/hbase/HBaseStoreManager.java | 935 ------------------ .../diskstorage/hbase/HBaseTransaction.java | 75 -- .../diskstorage/hbase/HConnection0_98.java | 49 - .../titan/diskstorage/hbase/HConnection1_0.java | 50 - .../titan/diskstorage/hbase/HTable0_98.java | 65 -- .../titan/diskstorage/hbase/HTable1_0.java | 65 -- .../titan/diskstorage/hbase/TableMask.java | 41 - .../diskstorage/locking/LocalLockMediator.java | 345 ------- .../titan/diskstorage/solr/Solr5Index.java | 975 ------------------- .../query/graph/GraphCentricQueryBuilder.java | 457 --------- .../hbase/HBaseKeyColumnValueStoreTest.java | 139 --- .../locking/LocalLockMediatorTest.java | 60 -- webapp/pom.xml | 18 +- 106 files changed, 9098 insertions(+), 5052 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/.gitignore ---------------------------------------------------------------------- diff --git a/.gitignore b/.gitignore index 0086a69..e10adbc 100755 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ core*.dmp .cache .classpath .project +.checkstyle .settings .externalToolBuilders http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/catalog/pom.xml ---------------------------------------------------------------------- diff --git a/catalog/pom.xml b/catalog/pom.xml index 5946c10..2f58a8f 100755 --- a/catalog/pom.xml +++ b/catalog/pom.xml @@ -30,7 +30,12 @@ <description>Apache Atlas Business Catalog Module</description> <name>Apache Atlas Business Catalog</name> <packaging>jar</packaging> - + + <properties> + <tinkerpop.version>2.6.0</tinkerpop.version> + <titan.version>0.5.4</titan.version> + </properties> + <dependencies> <dependency> <groupId>org.apache.atlas</groupId> @@ -82,11 +87,13 @@ <dependency> <groupId>com.tinkerpop.blueprints</groupId> <artifactId>blueprints-core</artifactId> + <version>${tinkerpop.version}</version> </dependency> <dependency> <groupId>com.tinkerpop.gremlin</groupId> <artifactId>gremlin-java</artifactId> + <version>${tinkerpop.version}</version> </dependency> <!-- testing --> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/common/src/main/java/org/apache/atlas/repository/Constants.java ---------------------------------------------------------------------- diff --git a/common/src/main/java/org/apache/atlas/repository/Constants.java b/common/src/main/java/org/apache/atlas/repository/Constants.java new file mode 100644 index 0000000..d7f9c89 --- /dev/null +++ b/common/src/main/java/org/apache/atlas/repository/Constants.java @@ -0,0 +1,90 @@ +/** + * 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; + +/** + * Repository Constants. + * + */ +public final class Constants { + + /** + * Globally Unique identifier property key. + */ + + public static final String INTERNAL_PROPERTY_KEY_PREFIX = "__"; + public static final String GUID_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "guid"; + + /** + * Entity type name property key. + */ + public static final String ENTITY_TYPE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "typeName"; + + /** + * Entity type's super types property key. + */ + public static final String SUPER_TYPES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "superTypeNames"; + + /** + * Full-text for the entity for enabling full-text search. + */ + //weird issue in TitanDB if __ added to this property key. Not adding it for now + public static final String ENTITY_TEXT_PROPERTY_KEY = "entityText"; + + /** + * Properties for type store graph. + */ + public static final String TYPE_CATEGORY_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.category"; + public static final String VERTEX_TYPE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type"; + public static final String TYPENAME_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.name"; + public static final String TYPEDESCRIPTION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "type.description"; + + /** + * Trait names property key and index name. + */ + public static final String TRAIT_NAMES_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "traitNames"; + + public static final String VERSION_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "version"; + public static final String STATE_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "state"; + + public static final String TIMESTAMP_PROPERTY_KEY = INTERNAL_PROPERTY_KEY_PREFIX + "timestamp"; + + public static final String MODIFICATION_TIMESTAMP_PROPERTY_KEY = + INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp"; + + /** + * search backing index name. + */ + public static final String BACKING_INDEX = "search"; + + /** + * search backing index name for vertex keys. + */ + public static final String VERTEX_INDEX = "vertex_index"; + + /** + * search backing index name for edge labels. + */ + public static final String EDGE_INDEX = "edge_index"; + + public static final String FULLTEXT_INDEX = "fulltext_index"; + + private Constants() { + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/distro/src/bin/atlas_start.py ---------------------------------------------------------------------- diff --git a/distro/src/bin/atlas_start.py b/distro/src/bin/atlas_start.py index bb61898..4590548 100755 --- a/distro/src/bin/atlas_start.py +++ b/distro/src/bin/atlas_start.py @@ -75,7 +75,6 @@ def main(): p = os.pathsep atlas_classpath = confdir + p \ + os.path.join(web_app_dir, "atlas", "WEB-INF", "classes" ) + p \ - + os.path.join(web_app_dir, "atlas", "WEB-INF", "lib", "atlas-titan-${project.version}.jar" ) + p \ + os.path.join(web_app_dir, "atlas", "WEB-INF", "lib", "*" ) + p \ + os.path.join(atlas_home, "libext", "*") http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/distro/src/test/python/scripts/TestMetadata.py ---------------------------------------------------------------------- diff --git a/distro/src/test/python/scripts/TestMetadata.py b/distro/src/test/python/scripts/TestMetadata.py index f943b8a..329dc3e 100644 --- a/distro/src/test/python/scripts/TestMetadata.py +++ b/distro/src/test/python/scripts/TestMetadata.py @@ -86,14 +86,14 @@ class TestMetadata(unittest.TestCase): java_mock.assert_called_with( 'org.apache.atlas.Atlas', ['-app', 'atlas_home\\server\\webapp\\atlas'], - 'atlas_home\\conf;atlas_home\\server\\webapp\\atlas\\WEB-INF\\classes;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\atlas-titan-${project.version}.jar;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\*;atlas_home\\libext\\*;atlas_home\\hbase\\conf', + 'atlas_home\\conf;atlas_home\\server\\webapp\\atlas\\WEB-INF\\classes;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\*;atlas_home\\libext\\*;atlas_home\\hbase\\conf', ['-Datlas.log.dir=atlas_home\\logs', '-Datlas.log.file=application.log', '-Datlas.home=atlas_home', '-Datlas.conf=atlas_home\\conf', '-Xmx1024m', '-XX:MaxPermSize=512m', '-Dlog4j.configuration=atlas-log4j.xml', '-Djava.net.preferIPv4Stack=true'], 'atlas_home\\logs') else: java_mock.assert_called_with( 'org.apache.atlas.Atlas', ['-app', 'atlas_home/server/webapp/atlas'], - 'atlas_home/conf:atlas_home/server/webapp/atlas/WEB-INF/classes:atlas_home/server/webapp/atlas/WEB-INF/lib/atlas-titan-${project.version}.jar:atlas_home/server/webapp/atlas/WEB-INF/lib/*:atlas_home/libext/*:atlas_home/hbase/conf', + 'atlas_home/conf:atlas_home/server/webapp/atlas/WEB-INF/classes:atlas_home/server/webapp/atlas/WEB-INF/lib/*:atlas_home/libext/*:atlas_home/hbase/conf', ['-Datlas.log.dir=atlas_home/logs', '-Datlas.log.file=application.log', '-Datlas.home=atlas_home', '-Datlas.conf=atlas_home/conf', '-Xmx1024m', '-XX:MaxPermSize=512m', '-Dlog4j.configuration=atlas-log4j.xml', '-Djava.net.preferIPv4Stack=true'], 'atlas_home/logs') pass @@ -152,14 +152,14 @@ class TestMetadata(unittest.TestCase): java_mock.assert_called_with( 'org.apache.atlas.Atlas', ['-app', 'atlas_home\\server\\webapp\\atlas'], - 'atlas_home\\conf;atlas_home\\server\\webapp\\atlas\\WEB-INF\\classes;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\atlas-titan-${project.version}.jar;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\*;atlas_home\\libext\\*;atlas_home\\hbase\\conf', + 'atlas_home\\conf;atlas_home\\server\\webapp\\atlas\\WEB-INF\\classes;atlas_home\\server\\webapp\\atlas\\WEB-INF\\lib\\*;atlas_home\\libext\\*;atlas_home\\hbase\\conf', ['-Datlas.log.dir=atlas_home\\logs', '-Datlas.log.file=application.log', '-Datlas.home=atlas_home', '-Datlas.conf=atlas_home\\conf', '-Xmx1024m', '-XX:MaxPermSize=512m', '-Dlog4j.configuration=atlas-log4j.xml', '-Djava.net.preferIPv4Stack=true'], 'atlas_home\\logs') else: java_mock.assert_called_with( 'org.apache.atlas.Atlas', ['-app', 'atlas_home/server/webapp/atlas'], - 'atlas_home/conf:atlas_home/server/webapp/atlas/WEB-INF/classes:atlas_home/server/webapp/atlas/WEB-INF/lib/atlas-titan-${project.version}.jar:atlas_home/server/webapp/atlas/WEB-INF/lib/*:atlas_home/libext/*:atlas_home/hbase/conf', + 'atlas_home/conf:atlas_home/server/webapp/atlas/WEB-INF/classes:atlas_home/server/webapp/atlas/WEB-INF/lib/*:atlas_home/libext/*:atlas_home/hbase/conf', ['-Datlas.log.dir=atlas_home/logs', '-Datlas.log.file=application.log', '-Datlas.home=atlas_home', '-Datlas.conf=atlas_home/conf', '-Xmx1024m', '-XX:MaxPermSize=512m', '-Dlog4j.configuration=atlas-log4j.xml', '-Djava.net.preferIPv4Stack=true'], 'atlas_home/logs') pass http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdge.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdge.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdge.java index 71b577b..dd4b7e6 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdge.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdge.java @@ -24,37 +24,37 @@ package org.apache.atlas.repository.graphdb; * @param <V> vertex class used by the graph * @param <E> edge class used by the graph */ -public interface AtlasEdge<V,E> extends AtlasElement { +public interface AtlasEdge<V, E> extends AtlasElement { /** * Gets the incoming vertex for this edge * @param in * @return */ - AtlasVertex<V,E> getInVertex(); + AtlasVertex<V, E> getInVertex(); /** * Gets the outgoing vertex for this edge - * + * * @param in * @return */ - AtlasVertex<V,E> getOutVertex(); - + AtlasVertex<V, E> getOutVertex(); + /** * Gets the label associated with this edge. - * + * * @return */ String getLabel(); - + /** * Converts the edge to an instance of the underlying implementation class. This * is syntactic sugar that allows the graph database implementation code to be strongly typed. This - * should not be called in other places. - * + * should not be called in other places. + * * @return */ - public E getE(); + public E getE(); } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdgeDirection.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdgeDirection.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdgeDirection.java index e7da1c9..a4b5b93 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdgeDirection.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasEdgeDirection.java @@ -22,6 +22,6 @@ package org.apache.atlas.repository.graphdb; */ public enum AtlasEdgeDirection { IN, - OUT, + OUT, BOTH } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasElement.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasElement.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasElement.java index 3c41693..1bc0fc3 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasElement.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasElement.java @@ -19,19 +19,23 @@ package org.apache.atlas.repository.graphdb; import java.util.Collection; +import java.util.List; import java.util.Set; +import org.apache.atlas.AtlasException; import org.codehaus.jettison.json.JSONException; import org.codehaus.jettison.json.JSONObject; /** - * Represents a graph element. + * Represents a graph element. * */ public interface AtlasElement { /** - * Gets the id of this element + * Gets the id of this element. If the object has not been physically created in the underlying graph, + * calling this method will force the element to be created so that a valid Id can be returned. + * * @return */ Object getId(); @@ -43,32 +47,122 @@ public interface AtlasElement { Collection<? extends String> getPropertyKeys(); /** - * Gets the value of the element property with the given name - * + * Gets the value of the element property with the given name. The value + * returned is guaranteed to be an instance of the specified class (or + * an exception will be thrown). + * + * @param propertyName + * @return + * @throws IllegalStateException if the property is multi-valued in the graph schema. + */ + <T> T getProperty(String propertyName, Class<T> clazz); + + /** + * Gets all of the values of the given property. * @param propertyName * @return */ - <T> T getProperty(String propertyName); - + <T> Collection<T> getPropertyValues(String propertyName, Class<T> type); + + /** + * Gets the value of a multiplicity one property whose value is a String list. + * The lists of super types and traits are stored this way. A separate method + * is needed for this because special logic is required to handle this situation + * in some implementations. + */ + List<String> getListProperty(String propertyName); + + /** + * Gets the value of a multiplicity one property whose value is a list. It + * attempts to convert the elements in the list to the specified type. Currently + * conversion is only supported for subclasses of AtlasElement and String. + */ + <V> List<V> getListProperty(String propertyName, Class<V> elementType); + + /** + * Sets a multiplicity one property whose value is a String list. + * The lists of super types and traits are stored this way. A separate method + * is needed for this because special logic is required to handle this situation + * in some implementations. + */ + void setListProperty(String propertyName, List<String> values) throws AtlasException; + + + /** + * Sets a multiplicity one property whose effective value is a String list whose + * values consist of the ids of the supplied elements. This is implemented efficiently + * so that in many cases the property can be set without requiring new elements + * to be immediately created in the graph database. It allows the actual underlying element + * creation to be deferred until commit time. + */ + void setPropertyFromElementsIds(String propertyName, List<AtlasElement> values); + + /** + * Sets a multiplicity one property whose effective value is a String whose value is the id of the supplied + * element. This is implemented efficiently so that in many cases the property can be set without requiring + * new elements to be immediately created in the graph database. It allows the actual underlying element + * creation to be deferred until commit time. + */ + void setPropertyFromElementId(String propertyName, AtlasElement value); + + /** * Removes a property from the vertex. */ void removeProperty(String propertyName); /** - * Sets a single-valued property to the given value. - * + * Sets a single-valued property to the given value. For + * properties defined as multiplicty many in the graph schema, the value is added instead + * (following set semantics) + * * @param propertyName * @param value */ - <T> void setProperty(String propertyName, T value); - - + <T> void setProperty(String propertyName, T value); + + /** * Creates a Jettison JSONObject from this Element * * @param propertyKeys The property keys at the root of the element to serialize. If null, then all keys are serialized. */ - JSONObject toJson(Set<String> propertyKeys) throws JSONException; - + JSONObject toJson(Set<String> propertyKeys) throws JSONException; + + /** + * Determines if this element exists in the graph database. If the element has not + * actually been loaded from the underlying graph, this will cause it to be loaded + * so that the result is correct. + * + * @return + */ + boolean exists(); + + /** + * @param propertyName + * @param value + */ + <T> void setJsonProperty(String propertyName, T value); + + /** + * @param propertyName + * @return + */ + <T> T getJsonProperty(String propertyName); + + /** + * Gets a human-readable id without forcing the element to + * be created if it does not exist in the graph yet. + * + * @return + */ + public String getIdForDisplay(); + + /** + * Whether or not an id has been assigned yet for this Element. This can happen if the element has been created + * in memory but has not been actually pushed into the underlying graph yet. + * + * @return + */ + boolean isIdAssigned(); } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java index f312117..995c545 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraph.java @@ -22,70 +22,82 @@ import java.io.OutputStream; import java.util.List; import java.util.Set; -import javax.script.Bindings; import javax.script.ScriptException; +import org.apache.atlas.typesystem.types.IDataType; + /** * Represents a graph - * + * * @param <V> vertex implementation class * @param <E> edge implementation class */ -public interface AtlasGraph<V,E> { +public interface AtlasGraph<V, E> { /** * Adds an edge to the graph - * + * * @param outVertex * @param inVertex * @param label * @return */ - AtlasEdge<V,E> addEdge(AtlasVertex<V,E> outVertex, AtlasVertex<V,E> inVertex, String label); + AtlasEdge<V, E> addEdge(AtlasVertex<V, E> outVertex, AtlasVertex<V, E> inVertex, String label); /** * Adds a vertex to the graph - * + * * @return */ - AtlasVertex<V,E> addVertex(); + AtlasVertex<V, E> addVertex(); /** * Removes the specified edge from the graph - * + * * @param edge */ - void removeEdge(AtlasEdge<V,E> edge); + void removeEdge(AtlasEdge<V, E> edge); /** * Removes the specified vertex from the graph. - * + * * @param vertex */ - void removeVertex(AtlasVertex<V,E> vertex); + void removeVertex(AtlasVertex<V, E> vertex); /** - * Retrieves the edge with the specified id + * Retrieves the edge with the specified id. As an optimization, a non-null Edge may be + * returned by some implementations if the Edge does not exist. In that case, + * you can call {@link AtlasElement#exists()} to determine whether the vertex + * exists. This allows the retrieval of the Edge information to be deferred + * or in come cases avoided altogether in implementations where that might + * be an expensive operation. + * * @param edgeId * @return */ - AtlasEdge<V,E> getEdge(String edgeId); + AtlasEdge<V, E> getEdge(String edgeId); /** * Gets all the edges in the graph. * @return */ - Iterable<AtlasEdge<V,E>> getEdges(); + Iterable<AtlasEdge<V, E>> getEdges(); /** * Gets all the vertices in the graph. * @return */ - Iterable<AtlasVertex<V,E>> getVertices(); + Iterable<AtlasVertex<V, E>> getVertices(); /** - * Gets the vertex with the specified id - * + * Gets the vertex with the specified id. As an optimization, a non-null vertex may be + * returned by some implementations if the Vertex does not exist. In that case, + * you can call {@link AtlasElement#exists()} to determine whether the vertex + * exists. This allows the retrieval of the Vertex information to be deferred + * or in come cases avoided altogether in implementations where that might + * be an expensive operation. + * * @param vertexId * @return */ @@ -94,7 +106,7 @@ public interface AtlasGraph<V,E> { /** * Gets the names of the indexes on edges * type. - * + * * @param type * @return */ @@ -104,40 +116,40 @@ public interface AtlasGraph<V,E> { /** * Gets the names of the indexes on vertices. * type. - * + * * @param type * @return */ Set<String> getVertexIndexKeys(); - + /** * Finds the vertices where the given property key * has the specified value. For multi-valued properties, * finds the vertices where the value list contains * the specified value. - * + * * @param key * @param value * @return */ - Iterable<AtlasVertex<V,E>> getVertices(String key, Object value); + Iterable<AtlasVertex<V, E>> getVertices(String key, Object value); /** * Creates a graph query * @return */ - AtlasGraphQuery<V,E> query(); + AtlasGraphQuery<V, E> query(); /** * Creates an index query - * + * * @param indexName index name * @param queryString the query - * + * * @see <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html">Elastic Search Reference</a> for query syntax */ - AtlasIndexQuery<V,E> indexQuery(String indexName, String queryString); + AtlasIndexQuery<V, E> indexQuery(String indexName, String queryString); /** * Gets the management object associated with this graph and opens a transaction @@ -160,26 +172,30 @@ public interface AtlasGraph<V,E> { * Unloads and releases any resources associated with the graph. */ void shutdown(); - + /** - * deletes everything in the graph. For testing only + * Deletes all data in the graph. May or may not delete + * the indices, depending on the what the underlying graph supports. + * + * For testing only. + * */ void clear(); /** * Converts the graph to gson and writes it to the specified stream - * + * * @param os * @throws IOException */ void exportToGson(OutputStream os) throws IOException; - + //the following methods insulate Atlas from the details //of the interaction with Gremlin - - + + /** - * + * * When we construct Gremlin select queries, the information we request * is grouped by the vertex the information is coming from. Each vertex * is assigned a column name which uniquely identifies it. The queries @@ -197,26 +213,26 @@ public interface AtlasGraph<V,E> { * <p/> * If the value found is a vertex or edge, it is automatically converted * to an AtlasVertex/AtlasEdge. - * + * * @param rowValue the raw row value that was returned by Gremin * @param colName the column name to use - * @param idx the index of the value within the column to retrieve. - * + * @param idx the index of the value within the column to retrieve. + * */ Object getGremlinColumnValue(Object rowValue, String colName, int idx); /** - * When Gremlin queries are executed, they return + * When Gremlin queries are executed, they return * Vertex and Edge objects that are specific to the underlying * graph database. This method provides a way to convert these * objects back into the AtlasVertex/AtlasEdge objects that - * Atlas requires. - * + * Atlas requires. + * * @param rawValue the value that was obtained from Gremlin * @return either an AtlasEdge, an AtlasVertex, or the original * value depending on whether the rawValue represents an edge, * vertex, or something else. - * + * */ Object convertGremlinValue(Object rawValue); @@ -224,27 +240,75 @@ public interface AtlasGraph<V,E> { * Gremlin 2 and Gremlin 3 represent the results of "path" * queries differently. This method takes as input the * path from Gremlin and returns the list of objects in the path. - * + * * @param rawValue * @return */ List<Object> convertPathQueryResultToList(Object rawValue); /** + * This method is used in the generation of queries. It is used to + * convert property values from the value that is stored in the graph + * to the value/type that the user expects to get back. + * + * @param expr - gremlin expr that represents the persistent property value + * @param type + * @return + */ + String generatePersisentToLogicalConversionExpression(String valueExpr, IDataType<?> type); + + /** + * Indicates whether or not stored values with the specified type need to be converted + * within generated gremlin queries before they can be compared with literal values. + * As an example, a graph database might choose to store Long values as Strings or + * List values as a delimited list. In this case, the generated gremlin needs to + * convert the stored property value prior to comparing it a literal. In this returns + * true, @code{generatePersisentToLogicalConversionExpression} is used to generate a + * gremlin expression with the converted value. In addition, this cause the gremlin + * 'filter' step to be used to compare the values instead of a 'has' step. + */ + boolean isPropertyValueConversionNeeded(IDataType<?> type); + + /** * Gets the version of Gremlin that this graph uses. - * + * * @return */ GremlinVersion getSupportedGremlinVersion(); + + /** + * Whether or not an initial predicate needs to be added to gremlin queries + * in order for them to run successfully. This is needed for some graph database where + * graph scans are disabled. + * @return + */ + boolean requiresInitialIndexedPredicate(); + + /** + * Some graph database backends have graph scans disabled. In order to execute some queries there, + * an initial 'dummy' predicate needs to be added to gremlin queries so that the first + * condition uses an index. + * + * @return + */ + String getInitialIndexedPredicate(); /** + * As an optimization, a graph database implementation may want to retrieve additional + * information about the query results. For example, in the IBM Graph implementation, + * this changes the query to return both matching vertices and their outgoing edges to + * avoid the need to make an extra REST API call to look up those edges. For implementations + * that do not require any kind of transform, an empty String should be returned. + */ + String getOutputTransformationPredicate(boolean isSelect, boolean isPath); + + /** * Executes a gremlin query, returns an object with the raw * result. - * + * * @param gremlinQuery * @return */ Object executeGremlinScript(String gremlinQuery) throws ScriptException; - } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphIndex.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphIndex.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphIndex.java new file mode 100644 index 0000000..41194d3 --- /dev/null +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphIndex.java @@ -0,0 +1,61 @@ +/** + * 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.graphdb; + +import java.util.Set; + +/** + * Represents a graph index on the database + */ +public interface AtlasGraphIndex { + + /** + * Indicates if the index is a mixed index. + * @return + */ + boolean isMixedIndex(); + + + /** + * Indicates if the index is a composite index. + * @return + */ + boolean isCompositeIndex(); + + /** + * Indicates if the index applies to edges + * + * @return + */ + boolean isEdgeIndex(); + + /** + * Indicates if the index applies to vertices + * + * @return + */ + boolean isVertexIndex(); + + + + boolean isUnique(); + + Set<AtlasPropertyKey> getFieldKeys(); + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java index 2776b22..c8cd284 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphManagement.java @@ -18,48 +18,62 @@ package org.apache.atlas.repository.graphdb; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + +import org.apache.atlas.AtlasException; +import org.apache.atlas.repository.Constants; import org.apache.atlas.typesystem.types.Multiplicity; /** * Management interface for a graph - * + * */ public interface AtlasGraphManagement { + public static final Set<String> MULTIPLICITY_MANY_PROPERTY_KEYS = + Collections.unmodifiableSet(new HashSet<String>(Arrays.asList( + Constants.SUPER_TYPES_PROPERTY_KEY, + Constants.TRAIT_NAMES_PROPERTY_KEY ))); + + /** * Checks whether a property with the given key has been defined in the graph schema. - * + * * @param key * @return */ boolean containsPropertyKey(String key); /** - * Creates a mixed Vertex index for the graph - * + * Creates a mixed Vertex index for the graph + * * @param index the name of the index to create * @param backingIndex the name of the backing index to use */ void buildMixedVertexIndex(String index, String backingIndex); - - + + /** - * Creates a mixed Edge index for the graph - * + * Creates a mixed Edge index for the graph + * * @param index the name of the index to create * @param backingIndex the name of the backing index to use */ void buildMixedEdgeIndex(String index, String backingIndex); - + /** - * Creates a full text index for the given property - * + * Creates a full text index for the given property + * * @param indexName the name of the index to create - * @param propertyKey the name of the property + * @param propertyKey full text property to index * @param backingIndex the name of the backing index to use */ - void createFullTextIndex(String indexName, String propertyKey, String backingIndex); + void createFullTextIndex(String indexName, AtlasPropertyKey propertyKey, String backingIndex); /** * Rolls back the changes that have been made to the management system. @@ -73,26 +87,44 @@ public interface AtlasGraphManagement { void commit(); /** - * Creates a composite index for the given property. - * - * @param propertyName name of the property being indexed - * @param propertyClass the java class of the property value(s) - * @param multiplicity the multiplicity of the property - * @param isUnique whether the property values must be unique + * @param propertyName + * @param propertyClass + * @param cardinality + * @return + */ + AtlasPropertyKey makePropertyKey(String propertyName, Class propertyClass, Multiplicity multiplicity); + + /** + * @param propertyKey + * @return + */ + AtlasPropertyKey getPropertyKey(String propertyName); + + /** + * Creates a composite index for the graph. + * + * @param propertyName + * @param propertyKey + * @param isUnique */ - void createCompositeIndex(String propertyName, Class propertyClass, Multiplicity multiplicity, - boolean isUnique); - + void createCompositeIndex(String propertyName, AtlasPropertyKey propertyKey, boolean isUnique); + /** - * Creates an index for a property. - * - * @param propertyName name of the property being indexed - * @param vertexIndexName name of the index to create - * @param propertyClass the java class of the property value(s) - * @param multiplicity the multiplicity of the property + * Adds a property key to the given index in the graph. + * + * @param vertexIndex + * @param propertyKey + */ + void addIndexKey(String vertexIndex, AtlasPropertyKey propertyKey); + + /** + * Looks up the index with the specified name in the graph. Returns null if + * there is no index with the given name. + * + * @param edgeIndex + * @return */ - void createBackingIndex(String propertyName, String vertexIndexName, Class propertyClass, - Multiplicity multiplicity); + AtlasGraphIndex getGraphIndex(String indexName); } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java index f0dca9a..9344749 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasGraphQuery.java @@ -18,8 +18,14 @@ package org.apache.atlas.repository.graphdb; +import java.util.Collection; +import java.util.List; + +import org.apache.atlas.AtlasException; + /** - * Represents a query against the graph. + * Represents a query against the graph within the context of the + * current transaction. * * @param <V> vertex class used by the graph * @param <E> edge class used by the graph @@ -27,10 +33,10 @@ package org.apache.atlas.repository.graphdb; public interface AtlasGraphQuery<V,E> { /** - * Adds a predicate that the returned elements must have the specified + * Adds a predicate that the returned vertices must have the specified * property and that one of the values of the property must be the * given value. - * + * * @param propertyKey * @param value * @return @@ -38,34 +44,73 @@ public interface AtlasGraphQuery<V,E> { AtlasGraphQuery<V,E> has(String propertyKey, Object value); /** - * Executes the query and returns the matching vertices. + * Adds a predicate that the returned vertices must have the specified + * property and that one of the value of the property must be in + * the specified list of values. + * + * @param propertyKey + * @param value * @return */ - Iterable<AtlasVertex<V, E>> vertices(); + AtlasGraphQuery<V,E> in(String propertyKey, Collection<? extends Object> values); + - /** - * Executes the query and returns the matching edges. + * Executes the query and returns the matching vertices. * @return + * @throws AtlasException */ - Iterable<AtlasEdge<V, E>> edges(); + Iterable<AtlasVertex<V, E>> vertices(); - /** - * Adds a predicate that the returned elements must have the specified + * Adds a predicate that the returned vertices must have the specified * property and that its value matches the criterion specified. - * + * * @param propertyKey * @param value * @return */ - AtlasGraphQuery<V,E> has(String propertyKey, ComparisionOperator compMethod, Object value); + AtlasGraphQuery<V,E> has(String propertyKey, ComparisionOperator compMethod, Object values); + + /** + * Adds a predicate that the vertices returned must satisfy the + * conditions in at least one of the child queries provided. + * + * @param childQueries + * @return + */ + AtlasGraphQuery<V,E> or(List<AtlasGraphQuery<V,E>> childQueries); + + /** + * Creates a child query that can be used to add "or" conditions + * + * @return + */ + AtlasGraphQuery<V,E> createChildQuery(); + public static enum ComparisionOperator { GREATER_THAN_EQUAL, EQUAL, - LESS_THAN_EQUAL + LESS_THAN_EQUAL, + NOT_EQUAL } + /** + * Adds all of the predicates that have been added to this query to the + * specified query. + * @param otherQuery + * @return + */ + AtlasGraphQuery<V, E> addConditionsFrom(AtlasGraphQuery<V, E> otherQuery); + + /** + * Whether or not this is a child query + * + * @return + */ + boolean isChildQuery(); + + } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasIndexQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasIndexQuery.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasIndexQuery.java index 7ee6b28..e719d30 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasIndexQuery.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasIndexQuery.java @@ -26,31 +26,31 @@ import java.util.Iterator; * @param <V> vertex class used by the graph * @param <E> edge class used by the graph */ -public interface AtlasIndexQuery<V,E> { +public interface AtlasIndexQuery<V, E> { /** * Gets the query results. - * + * * @return */ - Iterator<Result<V,E>> vertices(); + Iterator<Result<V, E>> vertices(); - /** + /** * Query result from an index query. - * + * * @param <V> * @param <E> */ - public interface Result<V,E> { - + public interface Result<V, E> { + /** * Gets the vertex for this result */ - AtlasVertex<V,E> getVertex(); - + AtlasVertex<V, E> getVertex(); + /** * Gets the score for this result. - * + * */ double getScore(); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasPropertyKey.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasPropertyKey.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasPropertyKey.java new file mode 100644 index 0000000..315ecdd --- /dev/null +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasPropertyKey.java @@ -0,0 +1,30 @@ +/** + * 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.graphdb; + +/** + * Represent a property key + * + * @param <V> vertex class used by the graph + * @param <E> edge class used by the graph + */ +public interface AtlasPropertyKey { + + String getName(); +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasSchemaViolationException.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasSchemaViolationException.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasSchemaViolationException.java index fda83b8..048eeaa 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasSchemaViolationException.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasSchemaViolationException.java @@ -22,7 +22,7 @@ package org.apache.atlas.repository.graphdb; * */ public class AtlasSchemaViolationException extends RuntimeException { - + public AtlasSchemaViolationException(Throwable cause) { super(cause); } http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertex.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertex.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertex.java index e027b69..fff6fb7 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertex.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertex.java @@ -17,64 +17,56 @@ */ package org.apache.atlas.repository.graphdb; -import java.util.Collection; - /** - * Represents a Vertex + * Represents a Vertex * * @param <V> vertex class used by the graph * @param <E> edge class used by the graph */ -public interface AtlasVertex<V,E> extends AtlasElement { - - - +public interface AtlasVertex<V, E> extends AtlasElement { /** * Gets the edges incident to this vertex going the * specified direction that have the specified edgeLabel. If * the edgeLabel is null, it is ignored. - * + * * @param in * @return */ - Iterable<AtlasEdge<V,E>> getEdges(AtlasEdgeDirection out, String edgeLabel); + Iterable<AtlasEdge<V, E>> getEdges(AtlasEdgeDirection out, String edgeLabel); /** * Gets the edges associated with this vertex going the * specified direction. - * + * * @param in * @return */ - Iterable<AtlasEdge<V,E>> getEdges(AtlasEdgeDirection in); - + Iterable<AtlasEdge<V, E>> getEdges(AtlasEdgeDirection in); + /** - * Adds a value to a multiplicity many property. - * + * Adds a value to a multiplicity many property. Follows Java set + * semantics. If the property is already present, it is not added again, + * and no exception is thrown. + * + * * @param propertyName * @param value */ <T> void addProperty(String propertyName, T value); - /** - * Gets all of the values of the given property. - * @param propertyName - * @return - */ - <T> Collection<T> getPropertyValues(String propertyName); /** * Creates a vertex query. * @return */ - AtlasVertexQuery<V,E> query(); + AtlasVertexQuery<V, E> query(); /** * Syntactic sugar to get the vertex as an instance of its * implementation type. This allows the graph database implementation * code to be strongly typed. - * + * * @return */ V getV(); http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertexQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertexQuery.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertexQuery.java index fd20a65..366cfe1 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertexQuery.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/AtlasVertexQuery.java @@ -19,33 +19,33 @@ package org.apache.atlas.repository.graphdb; /** - * A query against a particular vertex. + * A query against a particular vertex. * * @param <V> vertex class used by the graph - * @param <E> edge class used by the graph + * @param <E> edge class used by the graph */ -public interface AtlasVertexQuery<V,E> { +public interface AtlasVertexQuery<V, E> { /** * Specifies the edge direction that should be query - * + * * @param queryDirection * @return */ - AtlasVertexQuery<V,E> direction(AtlasEdgeDirection queryDirection); + AtlasVertexQuery<V, E> direction(AtlasEdgeDirection queryDirection); /** * Returns the vertices that satisfy the query condition. - * + * * @return */ - Iterable<AtlasVertex<V,E>> vertices(); + Iterable<AtlasVertex<V, E>> vertices(); /** * Returns the incident edges that satisfy the query condition. * @return */ - Iterable<AtlasEdge<V,E>> edges(); + Iterable<AtlasEdge<V, E>> edges(); /** * Returns the number of elements that match the query. http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GraphDatabase.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GraphDatabase.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GraphDatabase.java index a608eb2..37acda5 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GraphDatabase.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GraphDatabase.java @@ -23,22 +23,28 @@ package org.apache.atlas.repository.graphdb; * @param <V> vertex class used by the graph database * @param <E> edge class used by the graph database */ -public interface GraphDatabase<V,E> { - +public interface GraphDatabase<V, E> { + /** * Returns whether the graph has been loaded. * @return */ - boolean isGraphLoaded(); - + boolean isGraphLoaded(); + /** * Gets the graph, loading it if it has not been loaded already * @return */ - AtlasGraph<V,E> getGraph(); - + AtlasGraph<V, E> getGraph(); + + /** + * Sets things up so that getGraph() will return a graph that can be used for running + * tests. + */ + void initializeTestGraph(); + /** - * Unloads the graph (used testing) + * Removes the test graph that was created. */ - void unloadGraph(); + void removeTestGraph(); } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GremlinVersion.java ---------------------------------------------------------------------- diff --git a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GremlinVersion.java b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GremlinVersion.java index e817cba..f328d3c 100644 --- a/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GremlinVersion.java +++ b/graphdb/api/src/main/java/org/apache/atlas/repository/graphdb/GremlinVersion.java @@ -20,7 +20,7 @@ package org.apache.atlas.repository.graphdb; /** * Enumeration of the supported versions of Gremlin - * + * * */ public enum GremlinVersion { http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/pom.xml ---------------------------------------------------------------------- diff --git a/graphdb/common/pom.xml b/graphdb/common/pom.xml new file mode 100644 index 0000000..f3b1860 --- /dev/null +++ b/graphdb/common/pom.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- ~ 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. --> + +<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns="http://maven.apache.org/POM/4.0.0" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <artifactId>atlas-graphdb</artifactId> + <groupId>org.apache.atlas</groupId> + <version>0.8-incubator-SNAPSHOT</version> + </parent> + <artifactId>atlas-graphdb-common</artifactId> + + <description>Adds IBM Graph Database Support to Apache Atlas</description> + <name>Graph Database Common Code</name> + <packaging>jar</packaging> + + <dependencies> + <dependency> + <groupId>org.apache.atlas</groupId> + <artifactId>atlas-graphdb-api</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>18.0</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.9</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.testng</groupId> + <artifactId>testng</artifactId> + <version>6.9.4</version> + <scope>test</scope> + </dependency> + + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <version>1.9.5</version> + <scope>test</scope> + </dependency> + </dependencies> + +</project> http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanGraphQuery.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanGraphQuery.java new file mode 100644 index 0000000..b79bf79 --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanGraphQuery.java @@ -0,0 +1,60 @@ +/** + * 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.graphdb.titan.query; + +import java.util.Collection; + +import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator; +import org.apache.atlas.repository.graphdb.AtlasVertex; + +/** + * Interfaces that provides a thin wrapper around GraphQuery (used by Titan0) and + * TitanGraphQuery (used by Titan 1). + * + * This abstraction allows TitanGraphQuery to work on any version of Titan. + * + * @param <V> + * @param <E> + */ +public interface NativeTitanGraphQuery<V,E> { + + /** + * Executes the graph query + * @return + */ + Iterable<AtlasVertex<V,E>> vertices(); + + + /** + * Adds an in condition to the query + * + * @param propertyName + * @param values + */ + void in(String propertyName, Collection<? extends Object> values); + + /** + * Adds a has condition to the query + * + * @param propertyName + * @param op + * @param value + */ + void has(String propertyName, ComparisionOperator op, Object value); + +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanQueryFactory.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanQueryFactory.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanQueryFactory.java new file mode 100644 index 0000000..5c65411 --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/NativeTitanQueryFactory.java @@ -0,0 +1,34 @@ +/** + * 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.graphdb.titan.query; + +/** + * Interface that indicates that something can create instances of + * NativeTitanGraphQuery. + * + * @param <V> + * @param <E> + */ +public interface NativeTitanQueryFactory<V,E> { + + /** + * Creates a NativeTitanGraphQuery + * @return + */ + NativeTitanGraphQuery<V,E> createNativeTitanQuery(); +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/TitanGraphQuery.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/TitanGraphQuery.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/TitanGraphQuery.java new file mode 100644 index 0000000..f23847a --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/TitanGraphQuery.java @@ -0,0 +1,189 @@ +/** + * 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.graphdb.titan.query; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.atlas.repository.graphdb.AtlasGraph; +import org.apache.atlas.repository.graphdb.AtlasGraphQuery; +import org.apache.atlas.repository.graphdb.AtlasVertex; +import org.apache.atlas.repository.graphdb.titan.query.expr.AndCondition; +import org.apache.atlas.repository.graphdb.titan.query.expr.HasPredicate; +import org.apache.atlas.repository.graphdb.titan.query.expr.InPredicate; +import org.apache.atlas.repository.graphdb.titan.query.expr.OrCondition; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Abstract implementation of AtlasGraphQuery that is used by both Titan 0.5.4 + * and Titan 1.0.0. + * + * Represents a graph query as an OrConditions which consists of + * 1 or more AndConditions. The query is executed by converting + * the AndConditions to native GraphQuery instances that can be executed + * directly against Titan. The overall result is obtained by unioning together + * the results from those individual GraphQueries. + * + * Here is a pictoral view of what is going on here. Conceptually, + * the query being executed can be though of as the where clause + * in a query + * + * + * where (a =1 and b=2) or (a=2 and b=3) + * + * || + * \||/ + * \/ + * + * OrCondition + * | + * +---------+--------+ + * | | + * AndCondition AndCondition + * (a=1 and b=2) (a=2 and b=3) + * + * || || + * \||/ \||/ + * \/ \/ + * + * GraphQuery GraphQuery + * + * || || + * \||/ \||/ + * \/ \/ + * + * vertices vertices + * \ / + * _\/ \/_ + * (UNION) + * + * || + * \||/ + * \/ + * + * result + * + * + * + */ +public abstract class TitanGraphQuery<V,E> implements AtlasGraphQuery<V, E> { + + private final Logger LOG = LoggerFactory.getLogger(TitanGraphQuery.class); + protected final AtlasGraph<V,E> graph_; + private final OrCondition queryCondition_ = new OrCondition(); + private final boolean isChildQuery_; + protected abstract NativeTitanQueryFactory<V, E> getQueryFactory(); + + /** + * Creates a TitanGraphQuery + * + * @param graph + */ + public TitanGraphQuery(AtlasGraph<V,E> graph) { + graph_ = graph; + isChildQuery_ = false; + } + + /** + * Creates a TitanGraphQuery + * + * @param graph + * @param isChildQuery + */ + public TitanGraphQuery(AtlasGraph<V,E> graph, boolean isChildQuery) { + graph_ = graph; + isChildQuery_ = isChildQuery; + } + + @Override + public AtlasGraphQuery<V, E> has(String propertyKey, Object value) { + queryCondition_.andWith(new HasPredicate(propertyKey, ComparisionOperator.EQUAL, value)); + return this; + } + + @Override + public Iterable<AtlasVertex<V, E>> vertices() { + LOG.debug("Executing: " ); + LOG.debug(queryCondition_.toString()); + //compute the overall result by unioning the results from all of the + //AndConditions together. + Set<AtlasVertex<V, E>> result = new HashSet<>(); + for(AndCondition andExpr : queryCondition_.getAndTerms()) { + NativeTitanGraphQuery<V,E> andQuery = andExpr.create(getQueryFactory()); + for(AtlasVertex<V,E> vertex : andQuery.vertices()) { + result.add(vertex); + } + } + return result; + } + + @Override + public AtlasGraphQuery<V, E> has(String propertyKey, ComparisionOperator operator, + Object value) { + queryCondition_.andWith(new HasPredicate(propertyKey, operator, value)); + return this; + } + + + @Override + public AtlasGraphQuery<V, E> in(String propertyKey, Collection<? extends Object> values) { + queryCondition_.andWith(new InPredicate(propertyKey, values)); + return this; + } + + @Override + public AtlasGraphQuery<V, E> or(List<AtlasGraphQuery<V, E>> childQueries) { + + //Construct an overall OrCondition by combining all of the children for + //the OrConditions in all of the childQueries that we passed in. Then, "and" the current + //query condition with this overall OrCondition. + + OrCondition overallChildQuery = new OrCondition(false); + + for(AtlasGraphQuery<V, E> atlasChildQuery : childQueries) { + if(! atlasChildQuery.isChildQuery()) { + throw new IllegalArgumentException(atlasChildQuery + " is not a child query"); + } + TitanGraphQuery<V,E> childQuery = (TitanGraphQuery<V,E>)atlasChildQuery; + overallChildQuery.orWith(childQuery.getOrCondition()); + } + + queryCondition_.andWith(overallChildQuery); + return this; + } + + private OrCondition getOrCondition() { + return queryCondition_; + } + + @Override + public AtlasGraphQuery<V, E> addConditionsFrom(AtlasGraphQuery<V, E> otherQuery) { + + TitanGraphQuery<V, E> childQuery = (TitanGraphQuery<V, E>)otherQuery; + queryCondition_.andWith(childQuery.getOrCondition()); + return this; + } + + @Override + public boolean isChildQuery() { + return isChildQuery_; + } +} http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/AndCondition.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/AndCondition.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/AndCondition.java new file mode 100644 index 0000000..f3996d9 --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/AndCondition.java @@ -0,0 +1,96 @@ +/** + * 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.graphdb.titan.query.expr; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanQueryFactory; + +/** + * Represents an AndCondition in a graph query. Only vertices that + * satisfy the conditions in all of the query predicates will be returned + * + * Represents a query with predicates that are 'AND'ed together. These can be + * executed natively using Titan's GraphQuery mechanism. + */ +public class AndCondition { + + private List<QueryPredicate> children_ = new ArrayList<>(); + + public AndCondition() { + + } + + /** + * Adds a query predicate that must be met by vertices + * @param predicate + */ + public void andWith(QueryPredicate predicate) { + children_.add(predicate); + } + + /** + * Adds multiple predicates that much be met by the vertices + * + * @param predicates + */ + public void andWith(List<QueryPredicate> predicates) { + children_.addAll(predicates); + } + + /** + * Makes a copy of this AndExpr. + * + * @return + */ + public AndCondition copy() { + AndCondition builder = new AndCondition(); + builder.children_.addAll(children_); + return builder; + } + + /** + * Gets the query predicates + * + * @return + */ + public List<QueryPredicate> getTerms() { + return children_; + } + + /** + * Creates a NativeTitanGraphQuery that can be used to evaluate this condition. + * + * @param graph + * @return + */ + public <V,E> NativeTitanGraphQuery<V, E> create(NativeTitanQueryFactory<V,E> factory) { + NativeTitanGraphQuery<V, E> query = factory.createNativeTitanQuery(); + for (QueryPredicate predicate : children_) { + predicate.addTo(query); + } + return query; + } + + @Override + public String toString() { + return "AndExpr [predicates=" + children_ + "]"; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/HasPredicate.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/HasPredicate.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/HasPredicate.java new file mode 100644 index 0000000..8d7bc15 --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/HasPredicate.java @@ -0,0 +1,50 @@ +/** + * 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.graphdb.titan.query.expr; + +import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator; +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; + +/** + * Query predicate that checks whether the given property has the specified + * relationship with the value specified. + */ +public class HasPredicate implements QueryPredicate { + + private String propertyName_; + private ComparisionOperator op_; + private Object value_; + + public HasPredicate(String propertyName, ComparisionOperator op, Object value) { + super(); + propertyName_ = propertyName; + op_ = op; + value_ = value; + } + + @Override + public void addTo(NativeTitanGraphQuery query) { + query.has(propertyName_, op_, value_); + } + + @Override + public String toString() { + return "HasTerm [propertyName_=" + propertyName_ + ", op_=" + op_ + ", value_=" + value_ + "]"; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/InPredicate.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/InPredicate.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/InPredicate.java new file mode 100644 index 0000000..5a43a6a --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/InPredicate.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.repository.graphdb.titan.query.expr; + +import java.util.Collection; + +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; + +/** + * Query predicate that checks whether the value of a given property is within the + * provided set of allowed values. + */ +public class InPredicate implements QueryPredicate { + + private String propertyName_; + private Collection<? extends Object> values_; + + public InPredicate(String propertyName, Collection<? extends Object> values) { + super(); + propertyName_ = propertyName; + values_ = values; + } + + @Override + public void addTo(NativeTitanGraphQuery query) { + query.in(propertyName_, values_); + } + + @Override + public String toString() { + return "InPredicate [propertyName_=" + propertyName_ + ", values_=" + values_ + "]"; + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/OrCondition.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/OrCondition.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/OrCondition.java new file mode 100644 index 0000000..9de4655 --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/OrCondition.java @@ -0,0 +1,136 @@ +/** + * 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.graphdb.titan.query.expr; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * Represents an OrCondition that has one or more AndConditions as it children. The OrCondition + * matches vertices that meet the criteria in at least one of its children. The overall query result is + * computed by executing the TitanGraphQuery queries that correspond to each AndCondition individually and + * then unioning their results together. This is needed because the native Titan query mechanism does not + * natively support 'OR' conditions. When we execute the query, we accomplish the 'OR' by executing all of the + * individual queries and unioning the results together. + * + */ +public class OrCondition { + + private List<AndCondition> children_; + + public OrCondition() { + this(true); + } + + private OrCondition(List<AndCondition> children) { + children_ = children; + } + + public OrCondition(boolean addInitialTerm) { + children_ = new ArrayList<AndCondition>(); + if (addInitialTerm) { + children_.add(new AndCondition()); + } + } + + /** + /** + * Updates this OrCondition in place so that it matches vertices that satisfy the current + * OrCondition AND that match the specified predicate. + * + * @param other + */ + public void andWith(QueryPredicate predicate) { + + for (AndCondition child : children_) { + child.andWith(predicate); + } + } + + public List<AndCondition> getAndTerms() { + return children_; + } + + /** + * Updates this OrCondition in place so that it matches vertices that satisfy the current + * OrCondition AND that satisfy the provided OrCondition + * + * @param other + */ + public void andWith(OrCondition other) { + + //Because Titan does not natively support Or conditions in Graph Queries, + //we need to expand out the condition so it is in the form of a single OrCondition + //that contains only AndConditions. We do this by following the rules of boolean + //algebra. As an example, suppose the current condition is ((a=1 and b=2) or (c=3 and d=4)). + //Suppose "other" is ((e=5 and f=6) or (g=7 or h=8)). The overall condition, after applying the + //"and" is: + // + //((a=1 and b=2) or (c=3 and d=4)) and ((e=5 and f=6) or (g=7 and h=8)) + // + //This needs to be expanded out to remove the nested or clauses. The result of this expansion is: + // + //(a=1 and b=2 and e=5 and f=6) or + //(a=1 and b=2 and g=7 and h=8) or + //(c=3 and d=4 and e=5 and f=6) or + //(c=3 and d=4 and g=7 and h=8) + + //The logic below does this expansion, in a generalized way. It loops through the existing AndConditions + //and, in a nested loop, through the AndConditions in "other". For each of those combinations, + //it creates a new AndCondition that combines the two AndConditions together. These combined + //AndConditions become the new set of AndConditions in this OrCondition. + + List<AndCondition> expandedExpressionChildren = new ArrayList<AndCondition>(); + for (AndCondition otherExprTerm : other.getAndTerms()) { + for (AndCondition currentExpr : children_) { + AndCondition currentAndConditionCopy = currentExpr.copy(); + currentAndConditionCopy.andWith(otherExprTerm.getTerms()); + expandedExpressionChildren.add(currentAndConditionCopy); + } + } + children_ = expandedExpressionChildren; + } + + /** + * Updates this OrCondition in place so that it matches vertices that satisfy the current + * OrCondition OR that satisfy the provided OrCondition + * + * @param other + */ + public void orWith(OrCondition other) { + children_.addAll(other.getAndTerms()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("OrCondition [andExprs="); + Iterator<AndCondition> it = children_.iterator(); + while (it.hasNext()) { + AndCondition andExpr = it.next(); + builder.append(andExpr.toString()); + if (it.hasNext()) { + builder.append(","); + } + } + builder.append("]"); + return builder.toString(); + } + +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/QueryPredicate.java ---------------------------------------------------------------------- diff --git a/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/QueryPredicate.java b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/QueryPredicate.java new file mode 100644 index 0000000..61c692f --- /dev/null +++ b/graphdb/common/src/main/java/org/apache/atlas/repository/graphdb/titan/query/expr/QueryPredicate.java @@ -0,0 +1,33 @@ +/** + * 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.graphdb.titan.query.expr; + +import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery; + +/** + * Represents a predicate in an AndExpression + */ +public interface QueryPredicate { + + /** + * Adds the query term to a NativeTitanGraphQuery that is being generated. + * + * @param query + */ + void addTo(NativeTitanGraphQuery query); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-atlas/blob/4fa10b6a/graphdb/pom.xml ---------------------------------------------------------------------- diff --git a/graphdb/pom.xml b/graphdb/pom.xml index ea763c5..ad34617 100644 --- a/graphdb/pom.xml +++ b/graphdb/pom.xml @@ -32,5 +32,7 @@ <modules> <module>api</module> + <module>titan0</module> + <module>common</module> </modules> </project>
