Commit 4fa10b6a by Jeff Hagelberg Committed by Dave Kantor

ATLAS-693 Titan 0.5.4 implementation of graph db abstraction. (jnhagelb via dkantor)

parent 2ef0fc46
......@@ -30,6 +30,7 @@ core*.dmp
.cache
.classpath
.project
.checkstyle
.settings
.externalToolBuilders
......
......@@ -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 -->
......
......@@ -18,10 +18,10 @@
package org.apache.atlas.repository;
import org.apache.atlas.typesystem.types.AttributeInfo;
import org.apache.atlas.typesystem.types.DataTypes;
import org.apache.atlas.typesystem.types.utils.TypesUtil;
/**
* Repository Constants.
*
*/
public final class Constants {
/**
......@@ -48,7 +48,7 @@ public final class Constants {
public static final String ENTITY_TEXT_PROPERTY_KEY = "entityText";
/**
* Properties for type store graph
* 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";
......@@ -64,20 +64,9 @@ public final class Constants {
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";
public static AttributeInfo getAttributeInfoForSystemAttributes(String field) {
switch (field) {
case STATE_PROPERTY_KEY:
case GUID_PROPERTY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.STRING_TYPE);
case TIMESTAMP_PROPERTY_KEY:
case MODIFICATION_TIMESTAMP_PROPERTY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.LONG_TYPE);
}
return null;
}
public static final String MODIFICATION_TIMESTAMP_PROPERTY_KEY =
INTERNAL_PROPERTY_KEY_PREFIX + "modificationTimestamp";
/**
* search backing index name.
......
......@@ -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", "*")
......
......@@ -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
......
......@@ -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();
}
......@@ -22,6 +22,6 @@ package org.apache.atlas.repository.graphdb;
*/
public enum AtlasEdgeDirection {
IN,
OUT,
OUT,
BOTH
}
......@@ -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();
}
......@@ -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
/**
* 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();
}
......@@ -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);
}
......@@ -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();
}
......@@ -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();
......
/**
* 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();
}
......@@ -22,7 +22,7 @@ package org.apache.atlas.repository.graphdb;
*
*/
public class AtlasSchemaViolationException extends RuntimeException {
public AtlasSchemaViolationException(Throwable cause) {
super(cause);
}
......
......@@ -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();
......
......@@ -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.
......
......@@ -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
......@@ -20,7 +20,7 @@ package org.apache.atlas.repository.graphdb;
/**
* Enumeration of the supported versions of Gremlin
*
*
*
*/
public enum GremlinVersion {
......
<?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>
/**
* 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);
}
/**
* 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();
}
/**
* 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_;
}
}
/**
* 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
/**
* 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
/**
* 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
/**
* 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
/**
* 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
......@@ -32,5 +32,7 @@
<modules>
<module>api</module>
<module>titan0</module>
<module>common</module>
</modules>
</project>
<?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="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
~ 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>apache-atlas</artifactId>
<artifactId>atlas-graphdb</artifactId>
<groupId>org.apache.atlas</groupId>
<version>0.8-incubating-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>atlas-titan</artifactId>
<description>Apache Atlas Titan Overrides</description>
<name>Apache Atlas Titan</name>
<artifactId>atlas-graphdb-titan0</artifactId>
<description>Apache Atlas Titan 0.5.4 Graph DB Impl</description>
<name>Apache Atlas Titan 0.5.4 Graph DB Impl</name>
<packaging>jar</packaging>
<properties>
<tinkerpop.version>2.6.0</tinkerpop.version>
<titan.version>0.5.4</titan.version>
</properties>
<dependencies>
<!-- for graphdb interface definitions -->
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-graphdb-api</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-graphdb-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-core</artifactId>
<version>${titan.version}</version>
</dependency>
<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>
<dependency>
......@@ -47,28 +95,29 @@
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-core</artifactId>
<version>${solr.version}</version>
</dependency>
<dependency>
<groupId>org.apache.solr</groupId>
<artifactId>solr-solrj</artifactId>
<version>${solr.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-es</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-berkeleyje</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-lucene</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
......@@ -81,9 +130,56 @@
<artifactId>mockito-all</artifactId>
</dependency>
<dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!--
Create 'uber' jar that contains all of the dependencies (except those whose scope is provided)
Only Titan 0l5l4 and its dependencies are included. The other dependencies are bundled in the war file.
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<shadedArtifactAttached>false</shadedArtifactAttached>
<artifactSet>
<excludes>
<!-- these are bundled with Atlas -->
<exclude>org.slf4j:*</exclude>
</excludes>
</artifactSet>
<filters>
<filter>
<artifact>com.thinkaurelius.titan:titan-core</artifact>
<!-- force use of our custom LocalLockMediator implementation -->
<excludes>
<exclude>com/thinkaurelius/titan/diskstorage/locking/LocalLockMediator*</exclude>
</excludes>
</filter>
</filters>
<createSourcesJar>true</createSourcesJar>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
......@@ -101,5 +197,61 @@
</plugins>
</build>
<dependencyManagement>
<dependencies>
<!-- Graph DB -->
<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
<version>${tinkerpop.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-core</artifactId>
<version>${titan.version}</version>
<exclusions>
<!-- rexster does not work with servlet-api -->
<exclusion>
<groupId>com.tinkerpop.rexster</groupId>
<artifactId>rexster-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.tinkerpop.rexster</groupId>
<artifactId>rexster-server</artifactId>
</exclusion>
<!-- asm 4.0 does not work with jersey asm 3.1 -->
<exclusion>
<groupId>com.tinkerpop</groupId>
<artifactId>frames</artifactId>
</exclusion>
<exclusion>
<groupId>com.esotericsoftware.reflectasm</groupId>
<artifactId>reflectasm</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion> <!-- GPL license imported from ganglia -->
<groupId>org.acplt</groupId>
<artifactId>oncrpc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-berkeleyje</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-hbase</artifactId>
<version>${titan.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasGraphIndex;
import org.apache.atlas.repository.graphdb.titan0.query.Titan0GraphQuery;
import com.thinkaurelius.titan.core.PropertyKey;
import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
/**
* Factory that serves up instances of graph database abstraction layer classes
* that correspond to Titan/Tinkerpop classes.
*/
public final class GraphDbObjectFactory {
private GraphDbObjectFactory() {
}
/**
* Creates a Titan0Edge that corresponds to the given Gremlin Edge.
*
* @param source
* @return
*/
public static Titan0Edge createEdge(Titan0Graph graph, Edge source) {
if (source == null) {
return null;
}
return new Titan0Edge(graph, source);
}
/**
* Creates a Titan0GraphQuery that corresponds to the given GraphQuery.
* @param source
*
* @return
*/
public static Titan0GraphQuery createQuery(Titan0Graph graph) {
return new Titan0GraphQuery(graph);
}
/**
* Creates a Titan0Vertex that corresponds to the given Gremlin Vertex.
*
* @param source
* @return
*/
public static Titan0Vertex createVertex(Titan0Graph graph, Vertex source) {
if (source == null) {
return null;
}
return new Titan0Vertex(graph, source);
}
/**
* @param propertyKey
* @return
*/
public static Titan0PropertyKey createPropertyKey(PropertyKey propertyKey) {
if (propertyKey == null) {
return null;
}
return new Titan0PropertyKey(propertyKey);
}
/**
* @param index
* @return
*/
public static AtlasGraphIndex createGraphIndex(TitanGraphIndex index) {
if (index == null) {
return null;
}
return new Titan0GraphIndex(index);
}
}
/**
* 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.titan0;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.GraphDatabase;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.collect.ImmutableMap;
import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.schema.TitanManagement;
import com.thinkaurelius.titan.core.util.TitanCleanup;
import com.thinkaurelius.titan.diskstorage.StandardIndexProvider;
import com.thinkaurelius.titan.diskstorage.solr.Solr5Index;
/**
* Titan 0.5.4 implementation of GraphDatabase.
*/
public class Titan0Database implements GraphDatabase<Titan0Vertex, Titan0Edge> {
private static final Logger LOG = LoggerFactory.getLogger(Titan0Database.class);
/**
* Constant for the configuration property that indicates the prefix.
*/
public static final String GRAPH_PREFIX = "atlas.graph";
public static final String INDEX_BACKEND_CONF = "index.search.backend";
public static final String INDEX_BACKEND_LUCENE = "lucene";
public static final String INDEX_BACKEND_ES = "elasticsearch";
private static volatile TitanGraph graphInstance;
public static Configuration getConfiguration() throws AtlasException {
Configuration configProperties = ApplicationProperties.get();
return ApplicationProperties.getSubsetConfiguration(configProperties, GRAPH_PREFIX);
}
static {
addSolr5Index();
}
/**
* Titan loads index backend name to implementation using
* StandardIndexProvider.ALL_MANAGER_CLASSES But
* StandardIndexProvider.ALL_MANAGER_CLASSES is a private static final
* ImmutableMap Only way to inject Solr5Index is to modify this field. So,
* using hacky reflection to add Sol5Index
*/
private static void addSolr5Index() {
try {
Field field = StandardIndexProvider.class.getDeclaredField("ALL_MANAGER_CLASSES");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
Map<String, String> customMap = new HashMap<>(StandardIndexProvider.getAllProviderClasses());
customMap.put("solr", Solr5Index.class.getName()); // for
// consistency
// with Titan
// 1.0.0
customMap.put("solr5", Solr5Index.class.getName()); // for backward
// compatibility
ImmutableMap<String, String> immap = ImmutableMap.copyOf(customMap);
field.set(null, immap);
LOG.debug("Injected solr5 index - {}", Solr5Index.class.getName());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public static TitanGraph getGraphInstance() {
if (graphInstance == null) {
synchronized (Titan0Database.class) {
if (graphInstance == null) {
Configuration config;
try {
config = getConfiguration();
} catch (AtlasException e) {
throw new RuntimeException(e);
}
graphInstance = TitanFactory.open(config);
validateIndexBackend(config);
}
}
}
return graphInstance;
}
public static void unload() {
synchronized (Titan0Database.class) {
if (graphInstance == null) {
return;
}
graphInstance.commit();
//shutdown invalidates the graph instance
graphInstance.shutdown();
graphInstance = null;
}
}
static void validateIndexBackend(Configuration config) {
String configuredIndexBackend = config.getString(INDEX_BACKEND_CONF);
TitanManagement managementSystem = null;
try {
managementSystem = getGraphInstance().getManagementSystem();
String currentIndexBackend = managementSystem.get(INDEX_BACKEND_CONF);
if (!equals(configuredIndexBackend, currentIndexBackend)) {
throw new RuntimeException("Configured Index Backend " + configuredIndexBackend
+ " differs from earlier configured Index Backend " + currentIndexBackend + ". Aborting!");
}
} finally {
if (managementSystem != null) {
managementSystem.commit();
}
}
}
private static boolean equals(Object o1, Object o2) {
if (o1 == null) {
return o2 == null;
}
return o1.equals(o2);
}
@Override
public AtlasGraph<Titan0Vertex, Titan0Edge> getGraph() {
// force graph loading up front to avoid bootstrapping
// issues
getGraphInstance();
return new Titan0Graph();
}
@Override
public boolean isGraphLoaded() {
return graphInstance != null;
}
@Override
public void initializeTestGraph() {
//nothing to do
}
@Override
public void removeTestGraph() {
try {
getGraphInstance().shutdown();
}
catch(Throwable t) {
LOG.warn("Could not shutdown test TitanGraph", t);
t.printStackTrace();
}
try {
TitanCleanup.clear(getGraphInstance());
}
catch(Throwable t) {
LOG.warn("Could not clear test TitanGraph", t);
t.printStackTrace();
}
}
}
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasGraphIndex;
import org.apache.atlas.repository.graphdb.AtlasGraphManagement;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import org.apache.atlas.typesystem.types.Multiplicity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thinkaurelius.titan.core.Cardinality;
import com.thinkaurelius.titan.core.PropertyKey;
import com.thinkaurelius.titan.core.schema.Mapping;
import com.thinkaurelius.titan.core.schema.PropertyKeyMaker;
import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
import com.thinkaurelius.titan.core.schema.TitanManagement;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Vertex;
/**
* Titan 0.5.4 implementation of AtlasGraphManagement.
*/
public class Titan0DatabaseManager implements AtlasGraphManagement {
private static final Logger LOG = LoggerFactory.getLogger(Titan0DatabaseManager.class);
private TitanManagement management;
public Titan0DatabaseManager(TitanManagement managementSystem) {
management = managementSystem;
}
@Override
public void buildMixedVertexIndex(String index, String backingIndex) {
buildMixedIndex(index, Vertex.class, backingIndex);
}
@Override
public void buildMixedEdgeIndex(String index, String backingIndex) {
buildMixedIndex(index, Edge.class, backingIndex);
}
private void buildMixedIndex(String index, Class<? extends Element> titanClass, String backingIndex) {
management.buildIndex(index, titanClass).buildMixedIndex(backingIndex);
}
@Override
public void createFullTextIndex(String indexName, AtlasPropertyKey propertyKey, String backingIndex) {
PropertyKey fullText = TitanObjectFactory.createPropertyKey(propertyKey);
management.buildIndex(indexName, Vertex.class)
.addKey(fullText, com.thinkaurelius.titan.core.schema.Parameter.of("mapping", Mapping.TEXT))
.buildMixedIndex(backingIndex);
}
@Override
public boolean containsPropertyKey(String propertyKey) {
return management.containsPropertyKey(propertyKey);
}
@Override
public void rollback() {
management.rollback();
}
@Override
public void commit() {
management.commit();
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasGraphManagement#makePropertyKey(
* java.lang.String, java.lang.Class,
* org.apache.atlas.typesystem.types.Multiplicity)
*/
@Override
public AtlasPropertyKey makePropertyKey(String propertyName, Class propertyClass, Multiplicity multiplicity) {
PropertyKeyMaker propertyKeyBuilder = management.makePropertyKey(propertyName).dataType(propertyClass);
if (multiplicity != null) {
Cardinality cardinality = TitanObjectFactory.createCardinality(multiplicity);
propertyKeyBuilder.cardinality(cardinality);
}
PropertyKey propertyKey = propertyKeyBuilder.make();
return GraphDbObjectFactory.createPropertyKey(propertyKey);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasGraphManagement#getPropertyKey(
* java.lang.String)
*/
@Override
public AtlasPropertyKey getPropertyKey(String propertyName) {
return GraphDbObjectFactory.createPropertyKey(management.getPropertyKey(propertyName));
}
/*
* (non-Javadoc)
*
* @see org.apache.atlas.repository.graphdb.AtlasGraphManagement#
* createCompositeIndex(java.lang.String,
* org.apache.atlas.repository.graphdb.AtlasPropertyKey, boolean)
*/
@Override
public void createCompositeIndex(String propertyName, AtlasPropertyKey propertyKey, boolean enforceUniqueness) {
PropertyKey titanKey = TitanObjectFactory.createPropertyKey(propertyKey);
TitanManagement.IndexBuilder indexBuilder = management.buildIndex(propertyName, Vertex.class).addKey(titanKey);
if (enforceUniqueness) {
indexBuilder.unique();
}
indexBuilder.buildCompositeIndex();
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasGraphManagement#addIndexKey(java
* .lang.String, org.apache.atlas.repository.graphdb.AtlasPropertyKey)
*/
@Override
public void addIndexKey(String indexName, AtlasPropertyKey propertyKey) {
PropertyKey titanKey = TitanObjectFactory.createPropertyKey(propertyKey);
TitanGraphIndex vertexIndex = management.getGraphIndex(indexName);
management.addIndexKey(vertexIndex, titanKey);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasGraphManagement#getGraphIndex(
* java.lang.String)
*/
@Override
public AtlasGraphIndex getGraphIndex(String indexName) {
TitanGraphIndex index = management.getGraphIndex(indexName);
return GraphDbObjectFactory.createGraphIndex(index);
}
}
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
/**
* Titan 0.5.4 implementation of AtlasEdge.
*/
public class Titan0Edge extends Titan0Element<Edge> implements AtlasEdge<Titan0Vertex, Titan0Edge> {
public Titan0Edge(Titan0Graph graph, Edge edge) {
super(graph, edge);
}
@Override
public String getLabel() {
return wrappedElement.getLabel();
}
@Override
public Titan0Edge getE() {
return this;
}
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> getInVertex() {
Vertex v = wrappedElement.getVertex(Direction.IN);
return GraphDbObjectFactory.createVertex(graph, v);
}
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> getOutVertex() {
Vertex v = wrappedElement.getVertex(Direction.OUT);
return GraphDbObjectFactory.createVertex(graph, v);
}
@Override
public String toString() {
return "Titan0Edge [id=" + getId() + "]";
}
}
/**
* 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.titan0;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasElement;
import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.thinkaurelius.titan.core.SchemaViolationException;
import com.thinkaurelius.titan.core.TitanElement;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONMode;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONUtility;
/**
* Titan 0.5.4 implementation of AtlasElement.
*/
public class Titan0Element<T extends Element> implements AtlasElement {
protected Titan0Graph graph;
protected T wrappedElement;
public Titan0Element(Titan0Graph graph, T element) {
wrappedElement = element;
this.graph = graph;
}
@Override
public Object getId() {
return wrappedElement.getId();
}
@Override
public Set<String> getPropertyKeys() {
return wrappedElement.getPropertyKeys();
}
@Override
public <U> void setProperty(String propertyName, U value) {
try {
wrappedElement.setProperty(propertyName, value);
} catch (SchemaViolationException e) {
throw new AtlasSchemaViolationException(e);
}
}
@Override
public <U> U getProperty(String propertyName, Class<U> clazz) {
return (U)convert(wrappedElement.getProperty(propertyName), clazz);
}
/**
* Gets all of the values of the given property.
* @param propertyName
* @return
*/
@Override
public <T> Collection<T> getPropertyValues(String propertyName, Class<T> type) {
return Collections.singleton(getProperty(propertyName, type));
}
@Override
public void removeProperty(String propertyName) {
wrappedElement.removeProperty(propertyName);
}
@Override
public JSONObject toJson(Set<String> propertyKeys) throws JSONException {
return GraphSONUtility.jsonFromElement(wrappedElement, propertyKeys, GraphSONMode.NORMAL);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasElement#getListProperty(java.
* lang.String)
*/
@Override
public List<String> getListProperty(String propertyName) {
return getProperty(propertyName, List.class);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasElement#setListProperty(java.
* lang.String, java.util.List)
*/
@Override
public void setListProperty(String propertyName, List<String> values) {
setProperty(propertyName, values);
}
// not in interface
public T getWrappedElement() {
return wrappedElement;
}
@Override
public int hashCode() {
int result = 37;
result = 17 * result + getClass().hashCode();
result = 17 * result + getWrappedElement().hashCode();
return result;
}
@Override
public boolean equals(Object other) {
if(other == null) {
return false;
}
if (other.getClass() != getClass()) {
return false;
}
Titan0Element otherElement = (Titan0Element) other;
return getWrappedElement().equals(otherElement.getWrappedElement());
}
/*
* (non-Javadoc)
*
* @see org.apache.atlas.repository.graphdb.AtlasElement#exists()
*/
@Override
public boolean exists() {
try {
return ! ((TitanElement)wrappedElement).isRemoved();
}
catch(IllegalStateException e) {
return false;
}
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasElement#setJsonProperty(java.
* lang.String, java.lang.Object)
*/
@Override
public <T> void setJsonProperty(String propertyName, T value) {
setProperty(propertyName, value);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasElement#getJsonProperty(java.
* lang.String)
*/
@Override
public <T> T getJsonProperty(String propertyName) {
return (T) getProperty(propertyName, String.class);
}
@Override
public String getIdForDisplay() {
return getId().toString();
}
private <T> T convert(Object propertyValue, Class<T> clazz) {
if(propertyValue == null) {
return null;
}
if(AtlasEdge.class.isAssignableFrom(clazz)) {
return (T)graph.getEdge(propertyValue.toString());
}
if(AtlasVertex.class.isAssignableFrom(clazz)) {
return (T)graph.getVertex(propertyValue.toString());
}
return (T)propertyValue;
}
@Override
public <V> List<V> getListProperty(String propertyName, Class<V> elementType) {
List<String> value = getListProperty(propertyName);
if(value == null) {
return null;
}
if(AtlasEdge.class.isAssignableFrom(elementType)) {
return (List<V>)Lists.transform(value, new Function<String,AtlasEdge>(){
@Override
public AtlasEdge apply(String input) {
return graph.getEdge(input);
}
});
}
if(AtlasVertex.class.isAssignableFrom(elementType)) {
return (List<V>)Lists.transform(value, new Function<String,AtlasVertex>(){
@Override
public AtlasVertex apply(String input) {
return graph.getVertex(input);
}
});
}
return (List<V>)value;
}
@Override
public void setPropertyFromElementsIds(String propertyName, List<AtlasElement> values) {
List<String> propertyValue = new ArrayList<>(values.size());
for(AtlasElement element: values) {
propertyValue.add(element.getId().toString());
}
setProperty(propertyName, propertyValue);
}
@Override
public void setPropertyFromElementId(String propertyName, AtlasElement value) {
setProperty(propertyName, value.getId().toString());
}
@Override
public boolean isIdAssigned() {
return true;
}
}
/**
* 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.titan0;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.script.Bindings;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasGraphManagement;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.AtlasIndexQuery;
import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.GremlinVersion;
import org.apache.atlas.repository.graphdb.titan0.query.Titan0GraphQuery;
import org.apache.atlas.typesystem.types.IDataType;
import org.apache.atlas.utils.IteratorToIterableAdapter;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.thinkaurelius.titan.core.SchemaViolationException;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanIndexQuery;
import com.thinkaurelius.titan.core.util.TitanCleanup;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.util.io.graphson.GraphSONWriter;
import com.tinkerpop.pipes.util.structures.Row;
/**
* Titan 0.5.4 implementation of AtlasGraph.
*/
public class Titan0Graph implements AtlasGraph<Titan0Vertex, Titan0Edge> {
public Titan0Graph() {
}
@Override
public AtlasEdge<Titan0Vertex, Titan0Edge> addEdge(AtlasVertex<Titan0Vertex, Titan0Edge> outVertex,
AtlasVertex<Titan0Vertex, Titan0Edge> inVertex, String edgeLabel) {
try {
Edge edge = getGraph().addEdge(null, outVertex.getV().getWrappedElement(),
inVertex.getV().getWrappedElement(), edgeLabel);
return GraphDbObjectFactory.createEdge(this, edge);
} catch (SchemaViolationException e) {
throw new AtlasSchemaViolationException(e);
}
}
@Override
public AtlasGraphQuery<Titan0Vertex, Titan0Edge> query() {
return new Titan0GraphQuery(this);
}
@Override
public AtlasEdge<Titan0Vertex, Titan0Edge> getEdge(String edgeId) {
Edge edge = getGraph().getEdge(edgeId);
return GraphDbObjectFactory.createEdge(this, edge);
}
@Override
public void removeEdge(AtlasEdge<Titan0Vertex, Titan0Edge> edge) {
getGraph().removeEdge(edge.getE().getWrappedElement());
}
@Override
public void removeVertex(AtlasVertex<Titan0Vertex, Titan0Edge> vertex) {
getGraph().removeVertex(vertex.getV().getWrappedElement());
}
@Override
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> getEdges() {
Iterable<Edge> edges = getGraph().getEdges();
return wrapEdges(edges);
}
@Override
public Iterable<AtlasVertex<Titan0Vertex, Titan0Edge>> getVertices() {
Iterable<Vertex> vertices = getGraph().getVertices();
return wrapVertices(vertices);
}
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> addVertex() {
Vertex result = getGraph().addVertex(null);
return GraphDbObjectFactory.createVertex(this, result);
}
@Override
public void commit() {
getGraph().commit();
}
@Override
public void rollback() {
getGraph().rollback();
}
@Override
public AtlasIndexQuery<Titan0Vertex, Titan0Edge> indexQuery(String fulltextIndex, String graphQuery) {
TitanIndexQuery query = getGraph().indexQuery(fulltextIndex, graphQuery);
return new Titan0IndexQuery(this, query);
}
@Override
public AtlasGraphManagement getManagementSystem() {
return new Titan0DatabaseManager(getGraph().getManagementSystem());
}
@Override
public void shutdown() {
getGraph().shutdown();
}
@Override
public Set<String> getVertexIndexKeys() {
return getIndexKeys(Vertex.class);
}
@Override
public Set<String> getEdgeIndexKeys() {
return getIndexKeys(Edge.class);
}
private Set<String> getIndexKeys(Class<? extends Element> titanClass) {
return getGraph().getIndexedKeys(titanClass);
}
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> getVertex(String vertexId) {
Vertex v = getGraph().getVertex(vertexId);
return GraphDbObjectFactory.createVertex(this, v);
}
@Override
public Iterable<AtlasVertex<Titan0Vertex, Titan0Edge>> getVertices(String key, Object value) {
Iterable<Vertex> result = getGraph().getVertices(key, value);
return wrapVertices(result);
}
@Override
public Object getGremlinColumnValue(Object rowValue, String colName, int idx) {
Row<List> rV = (Row<List>) rowValue;
Object value = rV.getColumn(colName).get(idx);
return convertGremlinValue(value);
}
@Override
public Object convertGremlinValue(Object rawValue) {
if (rawValue instanceof Vertex) {
return GraphDbObjectFactory.createVertex(this, (Vertex) rawValue);
}
if (rawValue instanceof Edge) {
return GraphDbObjectFactory.createEdge(this, (Edge) rawValue);
}
return rawValue;
}
@Override
public GremlinVersion getSupportedGremlinVersion() {
return GremlinVersion.TWO;
}
@Override
public List<Object> convertPathQueryResultToList(Object rawValue) {
return (List<Object>) rawValue;
}
@Override
public void clear() {
TitanGraph graph = getGraph();
if (graph.isOpen()) {
// only a shut down graph can be cleared
graph.shutdown();
}
TitanCleanup.clear(graph);
}
private TitanGraph getGraph() {
// return the singleton instance of the graph in the plugin
return Titan0Database.getGraphInstance();
}
@Override
public void exportToGson(OutputStream os) throws IOException {
GraphSONWriter.outputGraph(getGraph(), os);
}
/*
* (non-Javadoc)
*
* @see
* org.apache.atlas.repository.graphdb.AtlasGraph#executeGremlinScript(java.
* lang.String)
*/
@Override
public Object executeGremlinScript(String gremlinQuery) throws ScriptException {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("gremlin-groovy");
Bindings bindings = engine.createBindings();
bindings.put("g", getGraph());
Object result = engine.eval(gremlinQuery, bindings);
return result;
}
@Override
public String generatePersisentToLogicalConversionExpression(String expr, IDataType<?> type) {
//nothing special needed, value is stored in required type
return expr;
}
@Override
public boolean isPropertyValueConversionNeeded(IDataType<?> type) {
return false;
}
@Override
public boolean requiresInitialIndexedPredicate() {
return false;
}
@Override
public String getInitialIndexedPredicate() {
return "";
}
@Override
public String getOutputTransformationPredicate(boolean inSelect, boolean isPath) {
return "";
}
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> wrapEdges(Iterator<Edge> it) {
Iterable<Edge> iterable = new IteratorToIterableAdapter<Edge>(it);
return wrapEdges(iterable);
}
public Iterable<AtlasVertex<Titan0Vertex, Titan0Edge>> wrapVertices(Iterator<Vertex> it) {
Iterable<Vertex> iterable = new IteratorToIterableAdapter<Vertex>(it);
return wrapVertices(iterable);
}
public Iterable<AtlasVertex<Titan0Vertex, Titan0Edge>> wrapVertices(Iterable<Vertex> it) {
return Iterables.transform(it, new Function<Vertex, AtlasVertex<Titan0Vertex, Titan0Edge>>(){
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> apply(Vertex input) {
return GraphDbObjectFactory.createVertex(Titan0Graph.this, input);
}
});
}
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> wrapEdges(Iterable<Edge> it) {
Iterable<Edge> result = (Iterable<Edge>)it;
return Iterables.transform(result, new Function<Edge, AtlasEdge<Titan0Vertex, Titan0Edge>>(){
@Override
public AtlasEdge<Titan0Vertex, Titan0Edge> apply(Edge input) {
return GraphDbObjectFactory.createEdge(Titan0Graph.this, input);
}
});
}
}
/**
* 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.titan0;
import java.util.HashSet;
import java.util.Set;
import org.apache.atlas.repository.graphdb.AtlasGraphIndex;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import com.thinkaurelius.titan.core.PropertyKey;
import com.thinkaurelius.titan.core.schema.TitanGraphIndex;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
/**
* Titan 0.5.4 implementation of AtlasGraphIndex.
*/
public class Titan0GraphIndex implements AtlasGraphIndex {
private TitanGraphIndex wrappedIndex;
public Titan0GraphIndex(TitanGraphIndex toWrap) {
wrappedIndex = toWrap;
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#isMixedIndex()
*/
@Override
public boolean isMixedIndex() {
return wrappedIndex.isMixedIndex();
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#isEdgeIndex()
*/
@Override
public boolean isEdgeIndex() {
return Edge.class.isAssignableFrom(wrappedIndex.getIndexedElement());
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#isVertexIndex()
*/
@Override
public boolean isVertexIndex() {
return Vertex.class.isAssignableFrom(wrappedIndex.getIndexedElement());
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#isCompositeIndex()
*/
@Override
public boolean isCompositeIndex() {
return wrappedIndex.isCompositeIndex();
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#isUnique()
*/
@Override
public boolean isUnique() {
return wrappedIndex.isUnique();
}
/* (non-Javadoc)
* @see org.apache.atlas.repository.graphdb.AtlasGraphIndex#getFieldKeys()
*/
@Override
public Set<AtlasPropertyKey> getFieldKeys() {
PropertyKey[] keys = wrappedIndex.getFieldKeys();
Set<AtlasPropertyKey> result = new HashSet<AtlasPropertyKey>();
for(PropertyKey key : keys) {
result.add(GraphDbObjectFactory.createPropertyKey(key));
}
return result;
}
}
/**
* 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.titan0;
import java.util.Iterator;
import org.apache.atlas.repository.graphdb.AtlasIndexQuery;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import com.google.common.base.Function;
import com.google.common.collect.Iterators;
import com.thinkaurelius.titan.core.TitanIndexQuery;
import com.tinkerpop.blueprints.Vertex;
/**
* Titan 0.5.4 implementation of AtlasIndexQuery.
*/
public class Titan0IndexQuery implements AtlasIndexQuery<Titan0Vertex, Titan0Edge> {
private Titan0Graph graph;
private TitanIndexQuery wrappedIndexQuery;
public Titan0IndexQuery(Titan0Graph graph, TitanIndexQuery query) {
wrappedIndexQuery = query;
this.graph = graph;
}
@Override
public Iterator<AtlasIndexQuery.Result<Titan0Vertex, Titan0Edge>> vertices() {
Iterator<TitanIndexQuery.Result<Vertex>> results = wrappedIndexQuery.vertices().iterator();
Function<TitanIndexQuery.Result<Vertex>, AtlasIndexQuery.Result<Titan0Vertex, Titan0Edge>> function =
new Function<TitanIndexQuery.Result<Vertex>, AtlasIndexQuery.Result<Titan0Vertex, Titan0Edge>>() {
@Override
public AtlasIndexQuery.Result<Titan0Vertex, Titan0Edge> apply(TitanIndexQuery.Result<Vertex> source) {
return new ResultImpl(source);
}
};
return Iterators.transform(results, function);
}
private final class ResultImpl implements AtlasIndexQuery.Result<Titan0Vertex, Titan0Edge> {
private TitanIndexQuery.Result<Vertex> wrappedResult;
public ResultImpl(TitanIndexQuery.Result<Vertex> source) {
wrappedResult = source;
}
@Override
public AtlasVertex<Titan0Vertex, Titan0Edge> getVertex() {
return GraphDbObjectFactory.createVertex(graph, wrappedResult.getElement());
}
@Override
public double getScore() {
return wrappedResult.getScore();
}
}
}
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import com.thinkaurelius.titan.core.PropertyKey;
/**
* Titan 0.5.4 implementaiton of AtlasPropertyKey.
*/
public class Titan0PropertyKey implements AtlasPropertyKey {
private PropertyKey wrappedPropertyKey;
public Titan0PropertyKey(PropertyKey toWrap) {
wrappedPropertyKey = toWrap;
}
/*
* (non-Javadoc)
*
* @see org.apache.atlas.repository.graphdb.AtlasPropertyKey#getName()
*/
@Override
public String getName() {
return wrappedPropertyKey.getName();
}
/**
* @return
*/
public PropertyKey getWrappedPropertyKey() {
return wrappedPropertyKey;
}
@Override
public boolean equals(Object other) {
if (!(other instanceof Titan0PropertyKey)) {
return false;
}
Titan0PropertyKey otherKey = (Titan0PropertyKey) other;
return wrappedPropertyKey.equals(otherKey.wrappedPropertyKey);
}
@Override
public int hashCode() {
int result = 17;
result = 37 * result + wrappedPropertyKey.hashCode();
return result;
}
}
/**
* 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.titan0;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasGraphManagement;
import org.apache.atlas.repository.graphdb.AtlasSchemaViolationException;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.AtlasVertexQuery;
import com.thinkaurelius.titan.core.SchemaViolationException;
import com.thinkaurelius.titan.core.TitanProperty;
import com.thinkaurelius.titan.core.TitanVertex;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
/**
* Titan 0.5.4 implementation of AtlasVertex.
*/
public class Titan0Vertex extends Titan0Element<Vertex> implements AtlasVertex<Titan0Vertex, Titan0Edge> {
public Titan0Vertex(Titan0Graph graph, Vertex source) {
super(graph, source);
}
@Override
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> getEdges(AtlasEdgeDirection dir, String edgeLabel) {
Iterable<Edge> titanEdges = wrappedElement.getEdges(TitanObjectFactory.createDirection(dir), edgeLabel);
return graph.wrapEdges(titanEdges);
}
private TitanVertex getAsTitanVertex() {
return (TitanVertex) wrappedElement;
}
@Override
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> getEdges(AtlasEdgeDirection in) {
Iterable<Edge> titanResult = wrappedElement.getEdges(TitanObjectFactory.createDirection(in));
return graph.wrapEdges(titanResult);
}
@Override
public <T> T getProperty(String propertyName, Class<T> clazz) {
if (AtlasGraphManagement.MULTIPLICITY_MANY_PROPERTY_KEYS.contains(propertyName)) {
// throw exception in this case to be consistent with Titan 1.0.0
// behavior.
throw new IllegalStateException();
}
return super.getProperty(propertyName, clazz);
}
public <T> void setProperty(String propertyName, T value) {
try {
super.setProperty(propertyName, value);
} catch (UnsupportedOperationException e) {
// For consistency with Titan 1.0.0, treat sets of multiplicity many
// properties as adds. Handle this here since this is an uncommon
// occurrence.
if (AtlasGraphManagement.MULTIPLICITY_MANY_PROPERTY_KEYS.contains(propertyName)) {
addProperty(propertyName, value);
} else {
throw e;
}
}
}
@Override
public <T> void addProperty(String propertyName, T value) {
try {
getAsTitanVertex().addProperty(propertyName, value);
} catch (SchemaViolationException e) {
if (getPropertyValues(propertyName, value.getClass()).contains(value)) {
// follow java set semantics, don't throw an exception if
// value is already there.
return;
}
throw new AtlasSchemaViolationException(e);
}
}
@Override
public <T> Collection<T> getPropertyValues(String key, Class<T> clazz) {
TitanVertex tv = getAsTitanVertex();
Collection<T> result = new ArrayList<T>();
for (TitanProperty property : tv.getProperties(key)) {
result.add((T) property.getValue());
}
return result;
}
@Override
public AtlasVertexQuery<Titan0Vertex, Titan0Edge> query() {
return new Titan0VertexQuery(graph, wrappedElement.query());
}
@Override
public Titan0Vertex getV() {
return this;
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return "Titan0Vertex [id=" + getId() + "]";
}
}
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.AtlasVertexQuery;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Vertex;
import com.tinkerpop.blueprints.VertexQuery;
/**
* Titan 0.5.4 implementation of AtlasVertexQuery.
*/
public class Titan0VertexQuery implements AtlasVertexQuery<Titan0Vertex, Titan0Edge> {
private Titan0Graph graph;
private VertexQuery vertexQuery;
public Titan0VertexQuery(Titan0Graph graph, VertexQuery vertexQuery) {
this.vertexQuery = vertexQuery;
this.graph = graph;
}
@Override
public AtlasVertexQuery<Titan0Vertex, Titan0Edge> direction(AtlasEdgeDirection queryDirection) {
vertexQuery.direction(TitanObjectFactory.createDirection(queryDirection));
return this;
}
@Override
public Iterable<AtlasVertex<Titan0Vertex, Titan0Edge>> vertices() {
Iterable<Vertex> vertices = vertexQuery.vertices();
return graph.wrapVertices(vertices);
}
@Override
public Iterable<AtlasEdge<Titan0Vertex, Titan0Edge>> edges() {
Iterable<Edge> edges = vertexQuery.edges();
return graph.wrapEdges(edges);
}
@Override
public long count() {
return vertexQuery.count();
}
}
/**
* 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.titan0;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import org.apache.atlas.typesystem.types.Multiplicity;
import com.thinkaurelius.titan.core.Cardinality;
import com.thinkaurelius.titan.core.PropertyKey;
import com.tinkerpop.blueprints.Direction;
/**
* Factory that serves up instances of Titan/Tinkerpop classes that correspond to
* graph database abstraction layer/Atlas classes.
*/
public final class TitanObjectFactory {
private TitanObjectFactory() {
}
/**
* Retrieves the titan direction corresponding to the given
* AtlasEdgeDirection.
*
* @param dir
* @return
*/
public static Direction createDirection(AtlasEdgeDirection dir) {
switch(dir) {
case IN:
return Direction.IN;
case OUT:
return Direction.OUT;
case BOTH:
return Direction.BOTH;
default:
throw new RuntimeException("Unrecognized direction: " + dir);
}
}
/**
* Converts a Multiplicity to a Cardinality.
*
* @param multiplicity
* @return
*/
public static Cardinality createCardinality(Multiplicity multiplicity) {
if (multiplicity == Multiplicity.OPTIONAL || multiplicity == Multiplicity.REQUIRED) {
return Cardinality.SINGLE;
} else if (multiplicity == Multiplicity.COLLECTION) {
return Cardinality.LIST;
} else if (multiplicity == Multiplicity.SET) {
return Cardinality.SET;
}
// default to LIST as this is the most forgiving
return Cardinality.LIST;
}
public static PropertyKey createPropertyKey(AtlasPropertyKey key) {
return ((Titan0PropertyKey)key).getWrappedPropertyKey();
}
}
/**
* 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.titan0.query;
import java.util.Collection;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery;
import org.apache.atlas.repository.graphdb.titan0.Titan0Database;
import org.apache.atlas.repository.graphdb.titan0.Titan0Edge;
import org.apache.atlas.repository.graphdb.titan0.Titan0Graph;
import org.apache.atlas.repository.graphdb.titan0.Titan0Vertex;
import com.thinkaurelius.titan.core.TitanGraphQuery;
import com.thinkaurelius.titan.core.attribute.Contain;
import com.thinkaurelius.titan.graphdb.query.TitanPredicate;
import com.tinkerpop.blueprints.Compare;
/**
* Titan 0.5.4 implementation of NativeTitanGraphQuery.
*
* @author jeff
*
*/
public class NativeTitan0GraphQuery implements NativeTitanGraphQuery<Titan0Vertex,Titan0Edge> {
private Titan0Graph graph_;
private TitanGraphQuery<?> query_;
public NativeTitan0GraphQuery(Titan0Graph graph) {
query_ = Titan0Database.getGraphInstance().query();
graph_ = graph;
}
@Override
public Iterable<AtlasVertex<Titan0Vertex,Titan0Edge>> vertices() {
Iterable it = query_.vertices();
return graph_.wrapVertices(it);
}
@Override
public void in(String propertyName, Collection<? extends Object> values) {
query_.has(propertyName, Contain.IN, values);
}
@Override
public void has(String propertyName, ComparisionOperator op, Object value) {
Compare c = getGremlinPredicate(op);
TitanPredicate pred = TitanPredicate.Converter.convert(c);
query_.has(propertyName, pred, value);
}
private Compare getGremlinPredicate(ComparisionOperator op) {
switch (op) {
case EQUAL:
return Compare.EQUAL;
case GREATER_THAN_EQUAL:
return Compare.GREATER_THAN_EQUAL;
case LESS_THAN_EQUAL:
return Compare.LESS_THAN_EQUAL;
case NOT_EQUAL:
return Compare.NOT_EQUAL;
default:
throw new RuntimeException("Unsupported comparison operator:" + op);
}
}
}
/**
* 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.titan0.query;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.titan.query.TitanGraphQuery;
import org.apache.atlas.repository.graphdb.titan.query.NativeTitanGraphQuery;
import org.apache.atlas.repository.graphdb.titan.query.NativeTitanQueryFactory;
import org.apache.atlas.repository.graphdb.titan0.Titan0Edge;
import org.apache.atlas.repository.graphdb.titan0.Titan0Graph;
import org.apache.atlas.repository.graphdb.titan0.Titan0Vertex;
/**
* Titan 0.5.4 implementation of AtlasGraphQuery.
*/
public class Titan0GraphQuery extends TitanGraphQuery<Titan0Vertex,Titan0Edge> implements NativeTitanQueryFactory<Titan0Vertex,Titan0Edge> {
public Titan0GraphQuery(Titan0Graph graph, boolean isChildQuery) {
super(graph, isChildQuery);
}
public Titan0GraphQuery(Titan0Graph graph) {
super(graph);
}
@Override
public AtlasGraphQuery<Titan0Vertex, Titan0Edge> createChildQuery() {
return new Titan0GraphQuery((Titan0Graph)graph_, true);
}
@Override
protected NativeTitanQueryFactory<Titan0Vertex,Titan0Edge> getQueryFactory() {
return this;
}
@Override
public NativeTitanGraphQuery<Titan0Vertex, Titan0Edge> createNativeTitanQuery() {
return new NativeTitan0GraphQuery((Titan0Graph)graph_);
}
}
/**
* 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.utils;
import java.util.Iterator;
/**
* Adapter class that allows an Iterator to be presented as an instance of java.util.Iterable.
*/
public final class IteratorToIterableAdapter<T> implements Iterable<T> {
private final Iterator<T> wrapped;
public IteratorToIterableAdapter(Iterator<T> wrapped) {
this.wrapped = wrapped;
}
@Override
public Iterator<T> iterator() {
return wrapped;
}
}
......@@ -18,6 +18,20 @@
package com.thinkaurelius.titan.diskstorage.hbase;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.fail;
import java.util.concurrent.TimeUnit;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.thinkaurelius.titan.diskstorage.BackendException;
import com.thinkaurelius.titan.diskstorage.EntryMetaData;
import com.thinkaurelius.titan.diskstorage.StaticBuffer;
......@@ -28,20 +42,6 @@ import com.thinkaurelius.titan.diskstorage.util.KeyColumn;
import com.thinkaurelius.titan.diskstorage.util.time.StandardDuration;
import com.thinkaurelius.titan.diskstorage.util.time.Timepoint;
import com.thinkaurelius.titan.graphdb.configuration.GraphDatabaseConfiguration;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import java.util.concurrent.TimeUnit;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.testng.Assert.fail;
public class HBaseKeyColumnValueStoreTest {
......
/**
* 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.titan0;
import java.util.ArrayList;
import java.util.List;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasGraphManagement;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.types.Multiplicity;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
/**
*
*/
public abstract class AbstractGraphDatabaseTest {
private static class RunnableWrapper implements Runnable {
private final Runnable r;
private Throwable exceptionThrown_ = null;
private RunnableWrapper(Runnable r) {
this.r = r;
}
@Override
public void run() {
try {
r.run();
}
catch(Throwable e) {
exceptionThrown_ = e;
}
}
public Throwable getExceptionThrown() {
return exceptionThrown_;
}
}
protected static final String WEIGHT_PROPERTY = "weight";
protected static final String TRAIT_NAMES = Constants.TRAIT_NAMES_PROPERTY_KEY;
protected static final String typeProperty = "__type";
protected static final String typeSystem = "typeSystem";
/**
*
*/
private static final String BACKING_INDEX_NAME = "backing";
private AtlasGraph<?,?> graph = null;
@AfterMethod
public void commitGraph() {
//force any pending actions to be committed so we can be sure they don't cause errors.
pushChangesAndFlushCache();
graph.commit();
}
protected <V, E> void pushChangesAndFlushCache() {
AtlasGraph<V, E> graph = getGraph();
graph.commit();
}
@BeforeClass
public static void createIndices() {
Titan0Database db = new Titan0Database();
AtlasGraphManagement mgmt = db.getGraph().getManagementSystem();
if(mgmt.getGraphIndex(BACKING_INDEX_NAME) == null) {
mgmt.buildMixedVertexIndex(BACKING_INDEX_NAME, Constants.BACKING_INDEX);
}
mgmt.makePropertyKey("age13",Integer.class, Multiplicity.OPTIONAL);
createIndices(mgmt, "name", String.class, false, Multiplicity.REQUIRED);
createIndices(mgmt, WEIGHT_PROPERTY, Integer.class, false, Multiplicity.OPTIONAL);
createIndices(mgmt, "size15", String.class, false, Multiplicity.REQUIRED);
createIndices(mgmt, "typeName", String.class, false, Multiplicity.REQUIRED);
createIndices(mgmt, "__type", String.class, false, Multiplicity.REQUIRED);
createIndices(mgmt, Constants.GUID_PROPERTY_KEY, String.class, true, Multiplicity.REQUIRED);
createIndices(mgmt, Constants.TRAIT_NAMES_PROPERTY_KEY, String.class, false, Multiplicity.SET);
createIndices(mgmt, Constants.SUPER_TYPES_PROPERTY_KEY, String.class, false, Multiplicity.SET);
mgmt.commit();
}
@AfterClass
public static void cleanUp() {
Titan0Graph graph = new Titan0Graph();
graph.clear();
}
private static void createIndices(AtlasGraphManagement management, String propertyName, Class propertyClass,
boolean isUnique, Multiplicity cardinality) {
if(management.containsPropertyKey(propertyName)) {
//index was already created
return;
}
AtlasPropertyKey key = management.makePropertyKey(propertyName, propertyClass, cardinality);
try {
if(propertyClass != Integer.class) {
management.addIndexKey(BACKING_INDEX_NAME, key);
}
}
catch(Throwable t) {
//ok
t.printStackTrace();
}
try {
//if(propertyClass != Integer.class) {
management.createCompositeIndex(propertyName, key, isUnique);
//}
}
catch(Throwable t) {
//ok
t.printStackTrace();
}
}
/**
*
*/
public AbstractGraphDatabaseTest() {
super();
}
protected final <V,E> AtlasGraph<V, E> getGraph() {
if(graph == null) {
graph = new Titan0Graph();
}
return (AtlasGraph<V,E>)graph;
}
protected Titan0Graph getTitan0Graph() {
AtlasGraph g = getGraph();
return (Titan0Graph)g;
}
protected List<AtlasVertex> newVertices_ = new ArrayList<>();
protected final <V, E> AtlasVertex<V, E> createVertex(AtlasGraph<V, E> graph) {
AtlasVertex<V,E> vertex = graph.addVertex();
newVertices_.add(vertex);
return vertex;
}
@AfterMethod
public void removeVertices() {
for(AtlasVertex vertex : newVertices_) {
if(vertex.exists()) {
getGraph().removeVertex(vertex);
}
}
getGraph().commit();
newVertices_.clear();
}
protected void runSynchronouslyInNewThread(final Runnable r) throws Throwable {
RunnableWrapper wrapper = new RunnableWrapper(r);
Thread th = new Thread(wrapper);
th.start();
th.join();
Throwable ex = wrapper.getExceptionThrown();
if(ex != null) {
throw ex;
}
}
}
\ No newline at end of file
/**
* 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.titan0;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.atlas.AtlasException;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.testng.annotations.Test;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
/**
* Tests for Titan0GraphQuery
*/
@Test
public class GraphQueryTest extends AbstractGraphDatabaseTest {
@Test
public <V,E> void testQueryThatCannotRunInMemory() throws AtlasException {
AtlasGraph<V,E> graph = getGraph();
AtlasVertex<V,E> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
AtlasVertex<V,E> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
AtlasVertex<V,E> v3 = createVertex(graph);
v3.setProperty("size15", "15");
graph.commit();
AtlasVertex<V,E> v4 = createVertex(graph);
v4.setProperty("name", "Fred");
v4.setProperty("size15", "15");
AtlasGraphQuery q = graph.query();
q.has("name", ComparisionOperator.NOT_EQUAL, "George");
q.has("size15","15");
graph.commit();
pause(); //pause to let the index get updated
assertQueryMatches(q, v1, v3, v4);
}
@Test
public void testCombinationOfAndsAndOrs() throws AtlasException {
Titan0Graph graph = getTitan0Graph();
AtlasVertex<Titan0Vertex,Titan0Edge> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
v1.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v2 = createVertex(graph);
v2.setProperty("name", "George");
v2.setProperty("size15", "16");
v2.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v3 = createVertex(graph);
v3.setProperty("name", "Jane");
v3.setProperty("size15", "17");
v3.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v4 = createVertex(graph);
v4.setProperty("name", "Bob");
v4.setProperty("size15", "18");
v4.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v5 = createVertex(graph);
v5.setProperty("name", "Julia");
v5.setProperty("size15", "19");
v5.setProperty("typeName", "Manager");
AtlasGraphQuery q = getGraphQuery();
q.has("typeName","Person");
//initially match
AtlasGraphQuery inner1a = q.createChildQuery();
AtlasGraphQuery inner1b = q.createChildQuery();
inner1a.has("name","Fred");
inner1b.has("name","Jane");
q.or(toList(inner1a, inner1b));
AtlasGraphQuery inner2a = q.createChildQuery();
AtlasGraphQuery inner2b = q.createChildQuery();
AtlasGraphQuery inner2c = q.createChildQuery();
inner2a.has("size15","18");
inner2b.has("size15","15");
inner2c.has("size15", "16");
q.or(toList(inner2a, inner2b, inner2c));
assertQueryMatches(q, v1);
graph.commit();
pause(); //let the index update
assertQueryMatches(q, v1);
}
@Test
public void testWithinStep() throws AtlasException {
Titan0Graph graph = getTitan0Graph();
AtlasVertex<Titan0Vertex,Titan0Edge> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
v1.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v2 = createVertex(graph);
v2.setProperty("name", "George");
v2.setProperty("size15", "16");
v2.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v3 = createVertex(graph);
v3.setProperty("name", "Jane");
v3.setProperty("size15", "17");
v3.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v4 = createVertex(graph);
v4.setProperty("name", "Bob");
v4.setProperty("size15", "18");
v4.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v5 = createVertex(graph);
v5.setProperty("name", "Julia");
v5.setProperty("size15", "19");
v5.setProperty("typeName", "Manager");
AtlasGraphQuery q = getGraphQuery();
q.has("typeName","Person");
//initially match
q.in("name", toList("Fred", "Jane"));
q.in("size15", toList("18", "15", "16"));
assertQueryMatches(q, v1);
graph.commit();
pause(); //let the index update
assertQueryMatches(q, v1);
}
@Test
public void testWithinStepWhereGraphIsStale() throws AtlasException {
Titan0Graph graph = getTitan0Graph();
AtlasVertex<Titan0Vertex,Titan0Edge> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
v1.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v2 = createVertex(graph);
v2.setProperty("name", "George");
v2.setProperty("size15", "16");
v2.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v3 = createVertex(graph);
v3.setProperty("name", "Jane");
v3.setProperty("size15", "17");
v3.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v4 = createVertex(graph);
v4.setProperty("name", "Bob");
v4.setProperty("size15", "18");
v4.setProperty("typeName", "Person");
AtlasVertex<Titan0Vertex,Titan0Edge> v5 = createVertex(graph);
v5.setProperty("name", "Julia");
v5.setProperty("size15", "19");
v5.setProperty("typeName", "Manager");
AtlasGraphQuery q = getGraphQuery();
q.has("typeName","Person");
//initially match
q.in("name", toList("Fred", "Jane"));
graph.commit();
pause(); //let the index update
assertQueryMatches(q, v1, v3);
v3.setProperty("name", "Janet"); //make v3 no longer match the query. Within step should filter out the vertex since it no longer matches.
assertQueryMatches(q, v1);
}
@Test
public void testSimpleOrQuery() throws AtlasException {
Titan0Graph graph = getTitan0Graph();
AtlasVertex<Titan0Vertex,Titan0Edge> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
AtlasVertex<Titan0Vertex,Titan0Edge> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
AtlasVertex<Titan0Vertex,Titan0Edge> v3 = createVertex(graph);
v3.setProperty("size15", "15");
graph.commit();
AtlasVertex<Titan0Vertex,Titan0Edge> v4 = createVertex(graph);
v4.setProperty("name", "Fred");
v4.setProperty("size15", "15");
AtlasVertex<Titan0Vertex,Titan0Edge> v5 = createVertex(graph);
v5.setProperty("name", "George");
v5.setProperty("size15", "16");
AtlasGraphQuery q = graph.query();
AtlasGraphQuery inner1 = q.createChildQuery().has("name", "Fred");
AtlasGraphQuery inner2 = q.createChildQuery().has("size15", "15");
q.or(toList(inner1, inner2));
assertQueryMatches(q, v1, v2, v3, v4);
graph.commit();
pause(); //pause to let the indexer get updated (this fails frequently without a pause)
assertQueryMatches(q, v1, v2, v3, v4);
}
@Test
public <V,E> void testQueryMatchesAddedVertices() throws AtlasException {
AtlasGraph<V,E> graph = getGraph();
AtlasVertex<V,E> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
AtlasVertex<V,E> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
AtlasVertex<V,E> v3 = createVertex(graph);
v3.setProperty("size15", "15");
graph.commit();
AtlasVertex<V,E> v4 = createVertex(graph);
v4.setProperty("name", "Fred");
v4.setProperty("size15", "15");
AtlasGraphQuery q = getGraphQuery();
q.has("name", "Fred");
q.has("size15","15");
assertQueryMatches(q, v1, v4);
graph.commit();
assertQueryMatches(q, v1, v4);
}
@Test
public <V,E> void testQueryDoesNotMatchRemovedVertices() throws AtlasException {
AtlasGraph<V,E> graph = getGraph();
AtlasVertex<V,E> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
AtlasVertex<V,E> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
AtlasVertex<V,E> v3 = createVertex(graph);
v3.setProperty("size15", "15");
AtlasVertex<V,E> v4 = createVertex(graph);
v4.setProperty("name", "Fred");
v4.setProperty("size15", "15");
graph.commit();
graph.removeVertex(v1);
AtlasGraphQuery q = getGraphQuery();
q.has("name", "Fred");
q.has("size15","15");
assertQueryMatches(q, v4);
graph.commit();
assertQueryMatches(q, v4);
}
@Test
public <V,E> void testQueryDoesNotMatchUncommittedAddedAndRemovedVertices() throws AtlasException {
AtlasGraph<V,E> graph = getGraph();
AtlasVertex<V,E> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
AtlasVertex<V,E> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
AtlasVertex<V,E> v3 = createVertex(graph);
v3.setProperty("size15", "15");
AtlasVertex<V,E> v4 = createVertex(graph);
v4.setProperty("name", "Fred");
v4.setProperty("size15", "15");
AtlasGraphQuery q = getGraphQuery();
q.has("name", "Fred");
q.has("size15","15");
assertQueryMatches(q, v1, v4);
graph.removeVertex(v1);
assertQueryMatches(q, v4);
graph.commit();
assertQueryMatches(q, v4);
}
@Test
public <V,E> void testQueryResultsReflectPropertyAdd() throws AtlasException {
AtlasGraph<V,E> graph = getGraph();
AtlasVertex<V,E> v1 = createVertex(graph);
v1.setProperty("name", "Fred");
v1.setProperty("size15", "15");
v1.addProperty(TRAIT_NAMES, "trait1");
v1.addProperty(TRAIT_NAMES, "trait2");
AtlasVertex<V,E> v2 = createVertex(graph);
v2.setProperty("name", "Fred");
v2.addProperty(TRAIT_NAMES, "trait1");
AtlasVertex<V,E> v3 = createVertex(graph);
v3.setProperty("size15", "15");
v3.addProperty(TRAIT_NAMES, "trait2");
AtlasGraphQuery query = getGraphQuery();
query.has("name", "Fred");
query.has(TRAIT_NAMES, "trait1");
query.has("size15", "15");
assertQueryMatches(query, v1);
//make v3 match the query
v3.setProperty("name", "Fred");
v3.addProperty(TRAIT_NAMES, "trait1");
assertQueryMatches(query, v1, v3);
v3.removeProperty(TRAIT_NAMES);
assertQueryMatches(query, v1);
v3.addProperty(TRAIT_NAMES, "trait2");
assertQueryMatches(query, v1);
v1.removeProperty(TRAIT_NAMES);
assertQueryMatches(query);
graph.commit();
assertQueryMatches(query);
}
private static <T> List<T> toList(Iterable<T> itr) {
List<T> result = new ArrayList<T>();
for(T object : itr) {
result.add(object);
}
return result;
}
private <V,E >void assertQueryMatches(AtlasGraphQuery expr, AtlasVertex... expectedResults) throws AtlasException {
//getGraph().commit();
Collection<AtlasVertex<Titan0Vertex, Titan0Edge>> temp = toList(expr.vertices());
//filter out vertices from previous test executions
Collection<AtlasVertex<Titan0Vertex, Titan0Edge>> result = Collections2.filter(temp, new Predicate<AtlasVertex<Titan0Vertex, Titan0Edge>>() {
@Override
public boolean apply(AtlasVertex<Titan0Vertex, Titan0Edge> input) {
return newVertices_.contains(input);
}
});
assertEquals("Expected/found result sizes differ. Expected: " + Arrays.asList(expectedResults).toString() +", found: " + result, expectedResults.length, result.size());
for(AtlasVertex<V,E> v : expectedResults) {
assertTrue(result.contains(v));
}
}
private static List<Object> toList(Object...objects) {
return Arrays.asList(objects);
}
private AtlasGraphQuery<Titan0Vertex, Titan0Edge> getGraphQuery() {
return getTitan0Graph().query();
}
private void pause() {
try {
Thread.sleep(5000);
}
catch(InterruptedException e)
{}
}
}
/**
* 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.titan0;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import org.apache.atlas.AtlasException;
import org.apache.atlas.repository.Constants;
import org.apache.atlas.repository.graphdb.AtlasEdge;
import org.apache.atlas.repository.graphdb.AtlasEdgeDirection;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.atlas.repository.graphdb.AtlasGraphManagement;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
import org.apache.atlas.repository.graphdb.AtlasPropertyKey;
import org.apache.atlas.repository.graphdb.AtlasVertex;
import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
import org.apache.atlas.typesystem.types.Multiplicity;
import org.testng.annotations.AfterClass;
import org.testng.annotations.Test;
/**
* Sanity test of basic graph operations using the Titan 0.5.4 graphdb
* abstraction layer implementation.
*/
public class Titan0DatabaseTest {
private AtlasGraph<?, ?> atlasGraph;
private <V, E> AtlasGraph<V, E> getGraph() {
if (atlasGraph == null) {
Titan0Database db = new Titan0Database();
atlasGraph = db.getGraph();
AtlasGraphManagement mgmt = atlasGraph.getManagementSystem();
// create the index (which defines these properties as being mult
// many)
for (String propertyName : AtlasGraphManagement.MULTIPLICITY_MANY_PROPERTY_KEYS) {
AtlasPropertyKey propertyKey = mgmt.getPropertyKey(propertyName);
if (propertyKey == null) {
propertyKey = mgmt.makePropertyKey(propertyName, String.class, Multiplicity.SET);
mgmt.createCompositeIndex(propertyName, propertyKey, false);
}
}
mgmt.commit();
}
return (AtlasGraph<V, E>) atlasGraph;
}
@AfterClass
public void cleanup() {
atlasGraph.clear();
atlasGraph = null;
}
@Test
public <V, E> void testPropertyDataTypes() {
// primitives
AtlasGraph<V, E> graph = getGraph();
testProperty(graph, "booleanProperty", Boolean.TRUE);
testProperty(graph, "booleanProperty", Boolean.FALSE);
testProperty(graph, "booleanProperty", new Boolean(Boolean.TRUE));
testProperty(graph, "booleanProperty", new Boolean(Boolean.FALSE));
testProperty(graph, "byteProperty", Byte.MAX_VALUE);
testProperty(graph, "byteProperty", Byte.MIN_VALUE);
testProperty(graph, "byteProperty", new Byte(Byte.MAX_VALUE));
testProperty(graph, "byteProperty", new Byte(Byte.MIN_VALUE));
testProperty(graph, "shortProperty", Short.MAX_VALUE);
testProperty(graph, "shortProperty", Short.MIN_VALUE);
testProperty(graph, "shortProperty", new Short(Short.MAX_VALUE));
testProperty(graph, "shortProperty", new Short(Short.MIN_VALUE));
testProperty(graph, "intProperty", Integer.MAX_VALUE);
testProperty(graph, "intProperty", Integer.MIN_VALUE);
testProperty(graph, "intProperty", new Integer(Integer.MAX_VALUE));
testProperty(graph, "intProperty", new Integer(Integer.MIN_VALUE));
testProperty(graph, "longProperty", Long.MIN_VALUE);
testProperty(graph, "longProperty", Long.MAX_VALUE);
testProperty(graph, "longProperty", new Long(Long.MIN_VALUE));
testProperty(graph, "longProperty", new Long(Long.MAX_VALUE));
testProperty(graph, "doubleProperty", Double.MAX_VALUE);
testProperty(graph, "doubleProperty", Double.MIN_VALUE);
testProperty(graph, "doubleProperty", new Double(Double.MAX_VALUE));
testProperty(graph, "doubleProperty", new Double(Double.MIN_VALUE));
testProperty(graph, "floatProperty", Float.MAX_VALUE);
testProperty(graph, "floatProperty", Float.MIN_VALUE);
testProperty(graph, "floatProperty", new Float(Float.MAX_VALUE));
testProperty(graph, "floatProperty", new Float(Float.MIN_VALUE));
// enumerations - TypeCategory
testProperty(graph, "typeCategoryProperty", TypeCategory.CLASS);
// biginteger
testProperty(graph, "bigIntegerProperty",
new BigInteger(String.valueOf(Long.MAX_VALUE)).multiply(BigInteger.TEN));
// bigdecimal
BigDecimal bigDecimal = new BigDecimal(Double.MAX_VALUE);
testProperty(graph, "bigDecimalProperty", bigDecimal.multiply(bigDecimal));
}
private <V, E> void testProperty(AtlasGraph<V, E> graph, String name, Object value) {
AtlasVertex<V, E> vertex = graph.addVertex();
vertex.setProperty(name, value);
assertEquals(value, vertex.getProperty(name, value.getClass()));
AtlasVertex<V, E> loaded = graph.getVertex(vertex.getId().toString());
assertEquals(value, loaded.getProperty(name, value.getClass()));
}
@Test
public <V, E> void testMultiplicityOnePropertySupport() {
AtlasGraph<V, E> graph = (AtlasGraph<V, E>) getGraph();
AtlasVertex<V, E> vertex = graph.addVertex();
vertex.setProperty("name", "Jeff");
vertex.setProperty("location", "Littleton");
assertEquals("Jeff", vertex.getProperty("name", String.class));
assertEquals("Littleton", vertex.getProperty("location", String.class));
AtlasVertex<V, E> vertexCopy = graph.getVertex(vertex.getId().toString());
assertEquals("Jeff", vertexCopy.getProperty("name", String.class));
assertEquals("Littleton", vertexCopy.getProperty("location", String.class));
assertTrue(vertexCopy.getPropertyKeys().contains("name"));
assertTrue(vertexCopy.getPropertyKeys().contains("location"));
assertTrue(vertexCopy.getPropertyValues("name", String.class).contains("Jeff"));
assertTrue(vertexCopy.getPropertyValues("location", String.class).contains("Littleton"));
assertTrue(vertexCopy.getPropertyValues("test", String.class).isEmpty());
assertNull(vertexCopy.getProperty("test", String.class));
vertex.removeProperty("name");
assertFalse(vertex.getPropertyKeys().contains("name"));
assertNull(vertex.getProperty("name", String.class));
assertTrue(vertex.getPropertyValues("name", String.class).isEmpty());
vertexCopy = graph.getVertex(vertex.getId().toString());
assertFalse(vertexCopy.getPropertyKeys().contains("name"));
assertNull(vertexCopy.getProperty("name", String.class));
assertTrue(vertexCopy.getPropertyValues("name", String.class).isEmpty());
}
@Test
public <V, E> void testRemoveEdge() {
AtlasGraph<V, E> graph = (AtlasGraph<V, E>) getGraph();
AtlasVertex<V, E> v1 = graph.addVertex();
AtlasVertex<V, E> v2 = graph.addVertex();
AtlasEdge<V, E> edge = graph.addEdge(v1, v2, "knows");
// make sure the edge exists
AtlasEdge<V, E> edgeCopy = graph.getEdge(edge.getId().toString());
assertNotNull(edgeCopy);
assertEquals(edgeCopy, edge);
graph.removeEdge(edge);
edgeCopy = graph.getEdge(edge.getId().toString());
// should return null now, since edge was deleted
assertNull(edgeCopy);
}
@Test
public <V, E> void testRemoveVertex() {
AtlasGraph<V, E> graph = (AtlasGraph<V, E>) getGraph();
AtlasVertex<V, E> v1 = graph.addVertex();
assertNotNull(graph.getVertex(v1.getId().toString()));
graph.removeVertex(v1);
assertNull(graph.getVertex(v1.getId().toString()));
}
@Test
public <V, E> void testGetEdges() {
AtlasGraph<V, E> graph = (AtlasGraph<V, E>) getGraph();
AtlasVertex<V, E> v1 = graph.addVertex();
AtlasVertex<V, E> v2 = graph.addVertex();
AtlasVertex<V, E> v3 = graph.addVertex();
AtlasEdge<V, E> knows = graph.addEdge(v2, v1, "knows");
AtlasEdge<V, E> eats = graph.addEdge(v3, v1, "eats");
AtlasEdge<V, E> drives = graph.addEdge(v3, v2, "drives");
AtlasEdge<V, E> sleeps = graph.addEdge(v2, v3, "sleeps");
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.IN), knows, eats);
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.OUT));
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.BOTH), knows, eats);
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.IN, "knows"), knows);
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.OUT, "knows"));
assertEdgesMatch(v1.getEdges(AtlasEdgeDirection.BOTH, "knows"), knows);
assertEdgesMatch(v2.getEdges(AtlasEdgeDirection.IN), drives);
assertEdgesMatch(v2.getEdges(AtlasEdgeDirection.OUT), knows, sleeps);
assertEdgesMatch(v2.getEdges(AtlasEdgeDirection.BOTH), knows, sleeps, drives);
assertEdgesMatch(v2.getEdges(AtlasEdgeDirection.BOTH, "delivers"));
}
private <V, E> void assertEdgesMatch(Iterable<AtlasEdge<V, E>> edgesIt, AtlasEdge<V, E>... expected) {
List<AtlasEdge<V, E>> edges = toList(edgesIt);
assertEquals(expected.length, edges.size());
for (AtlasEdge<V, E> edge : expected) {
assertTrue(edges.contains(edge));
}
}
@Test
public <V, E> void testMultiplictyManyPropertySupport() {
AtlasGraph<V, E> graph = getGraph();
AtlasVertex<V, E> vertex = graph.addVertex();
String vertexId = vertex.getId().toString();
vertex.setProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait1");
vertex.setProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait2");
assertEquals(vertex.getPropertyValues(Constants.TRAIT_NAMES_PROPERTY_KEY, String.class).size(), 2);
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait3");
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait4");
assertTrue(vertex.getPropertyKeys().contains(Constants.TRAIT_NAMES_PROPERTY_KEY));
validateMultManyPropertiesInVertex(vertex);
// fetch a copy of the vertex, make sure result
// is the same
validateMultManyPropertiesInVertex(graph.getVertex(vertexId));
}
private <V, E> void validateMultManyPropertiesInVertex(AtlasVertex<V, E> vertex) {
assertTrue(vertex.getPropertyKeys().contains(Constants.TRAIT_NAMES_PROPERTY_KEY));
Collection<String> traitNames = vertex.getPropertyValues(Constants.TRAIT_NAMES_PROPERTY_KEY, String.class);
assertTrue(traitNames.contains("trait1"));
assertTrue(traitNames.contains("trait2"));
assertTrue(traitNames.contains("trait3"));
assertTrue(traitNames.contains("trait4"));
try {
vertex.getProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, String.class);
fail("Expected exception not thrown");
} catch (IllegalStateException expected) {
// multiple property values exist
}
}
@Test
public <V, E> void testListProperties() throws AtlasException {
AtlasGraph<V, E> graph = getGraph();
AtlasVertex<V, E> vertex = graph.addVertex();
vertex.setListProperty("colors", Arrays.asList(new String[] { "red", "blue", "green" }));
List<String> colors = vertex.getListProperty("colors");
assertTrue(colors.contains("red"));
assertTrue(colors.contains("blue"));
assertTrue(colors.contains("green"));
AtlasVertex<V, E> vertexCopy = graph.getVertex(vertex.getId().toString());
colors = vertexCopy.getListProperty("colors");
assertTrue(colors.contains("red"));
assertTrue(colors.contains("blue"));
assertTrue(colors.contains("green"));
}
@Test
public <V, E> void testRemoveProperty() {
AtlasGraph<V, E> graph = getGraph();
AtlasVertex<V, E> vertex = graph.addVertex();
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait1");
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait1");
vertex.setProperty("name", "Jeff");
// remove existing property - multiplicity one
vertex.removeProperty("jeff");
assertFalse(vertex.getPropertyKeys().contains("jeff"));
// remove existing property - multiplicity many
vertex.removeProperty(Constants.TRAIT_NAMES_PROPERTY_KEY);
assertFalse(vertex.getPropertyKeys().contains(Constants.TRAIT_NAMES_PROPERTY_KEY));
AtlasVertex<V, E> vertexCopy = graph.getVertex(vertex.getId().toString());
assertFalse(vertexCopy.getPropertyKeys().contains("jeff"));
assertFalse(vertexCopy.getPropertyKeys().contains(Constants.TRAIT_NAMES_PROPERTY_KEY));
// remove non-existing property
vertex.removeProperty(Constants.TRAIT_NAMES_PROPERTY_KEY);
vertex.removeProperty("jeff");
}
@Test
public <V, E> void getGetGraphQueryForVertices() {
AtlasGraph<V, E> graph = getGraph();
AtlasVertex<V, E> v1 = graph.addVertex();
AtlasVertex<V, E> v2 = graph.addVertex();
AtlasVertex<V, E> v3 = graph.addVertex();
v1.setProperty("name", "Jeff");
v1.setProperty("weight", 1);
v2.setProperty("name", "Fred");
v2.setProperty("weight", 2);
v3.setProperty("name", "Chris");
v3.setProperty("weight", 3);
AtlasEdge<V, E> knows = graph.addEdge(v2, v1, "knows");
knows.setProperty("weight", 1);
AtlasEdge<V, E> eats = graph.addEdge(v3, v1, "eats");
eats.setProperty("weight", 2);
AtlasEdge<V, E> drives = graph.addEdge(v3, v2, "drives");
drives.setProperty("weight", 3);
AtlasEdge<V, E> sleeps = graph.addEdge(v2, v3, "sleeps");
sleeps.setProperty("weight", 4);
testExecuteGraphQuery("name", null, "Jeff", v1);
testExecuteGraphQuery("weight", ComparisionOperator.EQUAL, 2, v2);
testExecuteGraphQuery("weight", ComparisionOperator.GREATER_THAN_EQUAL, 2, v2, v3);
testExecuteGraphQuery("weight", ComparisionOperator.LESS_THAN_EQUAL, 2, v2, v1);
}
private <V, E> void testExecuteGraphQuery(String property, ComparisionOperator op, Object value,
AtlasVertex<V, E>... expected) {
AtlasGraph<V, E> graph = getGraph();
AtlasGraphQuery<V, E> query = graph.query();
if (op != null) {
query.has(property, op, value);
} else {
query.has(property, value);
}
Iterable<? extends AtlasVertex<V, E>> result = query.vertices();
List<AtlasVertex<V, E>> list = toList(result);
assertEquals(expected.length, list.size());
for (AtlasVertex<V, E> vertex : expected) {
assertTrue(list.contains(vertex));
}
}
@Test
public <V, E> void testAddMultManyPropertyValueTwice() {
AtlasGraph<V, E> graph = getGraph();
String vertexId;
AtlasVertex<V, E> vertex = graph.addVertex();
vertexId = vertex.getId().toString();
vertex.setProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait1");
vertex.setProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait1");
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait2");
vertex.addProperty(Constants.TRAIT_NAMES_PROPERTY_KEY, "trait2");
validateDuplicatePropertyVertex(vertex);
// fetch a copy of the vertex, make sure result is the same
validateDuplicatePropertyVertex(graph.getVertex(vertexId));
}
private <V, E> void validateDuplicatePropertyVertex(AtlasVertex<V, E> vertex) {
assertEquals(2, vertex.getPropertyValues(Constants.TRAIT_NAMES_PROPERTY_KEY, String.class).size());
assertTrue(vertex.getPropertyKeys().contains(Constants.TRAIT_NAMES_PROPERTY_KEY));
Collection<String> traitNames = vertex.getPropertyValues(Constants.TRAIT_NAMES_PROPERTY_KEY, String.class);
assertTrue(traitNames.contains("trait1"));
assertTrue(traitNames.contains("trait2"));
}
private static <T> List<T> toList(Iterable<? extends T> iterable) {
List<T> result = new ArrayList<T>();
for (T item : iterable) {
result.add(item);
}
return result;
}
}
......@@ -15,33 +15,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.atlas.repository.graph;
package org.apache.atlas.repository.graphdb.titan0;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.util.TitanCleanup;
import com.thinkaurelius.titan.diskstorage.Backend;
import com.thinkaurelius.titan.graphdb.database.StandardTitanGraph;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.repository.graphdb.AtlasGraph;
import org.apache.commons.configuration.Configuration;
import org.mockito.Mockito;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
@Test
public class TitanGraphProviderTest {
public class Titan0DatabaseValidationTest {
private Configuration configuration;
private TitanGraph graph;
private Configuration configuration;
private AtlasGraph<?, ?> graph;
@BeforeTest
public void setUp() throws AtlasException {
//First get Instance
graph = TitanGraphProvider.getGraphInstance();
configuration = ApplicationProperties.getSubsetConfiguration(ApplicationProperties.get(), TitanGraphProvider.GRAPH_PREFIX);
}
@BeforeTest
public void setUp() throws AtlasException {
// First get Instance
graph = new Titan0Graph();
configuration = ApplicationProperties.getSubsetConfiguration(ApplicationProperties.get(),
Titan0Database.GRAPH_PREFIX);
}
@AfterClass
public void tearDown() throws Exception {
......@@ -52,27 +49,29 @@ public class TitanGraphProviderTest {
}
try {
TitanCleanup.clear(graph);
graph.clear();
} catch (Exception e) {
e.printStackTrace();
}
}
@Test
public void testValidate() throws AtlasException {
try {
TitanGraphProvider.validateIndexBackend(configuration);
} catch(Exception e){
Assert.fail("Unexpected exception ", e);
}
@Test
public void testValidate() throws AtlasException {
try {
Titan0Database.validateIndexBackend(configuration);
} catch (Exception e) {
Assert.fail("Unexpected exception ", e);
}
//Change backend
configuration.setProperty(TitanGraphProvider.INDEX_BACKEND_CONF, TitanGraphProvider.INDEX_BACKEND_LUCENE);
try {
TitanGraphProvider.validateIndexBackend(configuration);
Assert.fail("Expected exception");
} catch(Exception e){
Assert.assertEquals(e.getMessage(), "Configured Index Backend lucene differs from earlier configured Index Backend elasticsearch. Aborting!");
}
}
// Change backend
configuration.setProperty(Titan0Database.INDEX_BACKEND_CONF, Titan0Database.INDEX_BACKEND_LUCENE);
try {
Titan0Database.validateIndexBackend(configuration);
Assert.fail("Expected exception");
} catch (Exception e) {
Assert.assertEquals(e.getMessage(),
"Configured Index Backend lucene differs from earlier configured "
+ "Index Backend elasticsearch. Aborting!");
}
}
}
#
# 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.
#
######### Graph Database to Use #########
atlas.graphdb.backend=org.apache.atlas.repository.graphdb.titan0.Titan0Database
######### Atlas Server Configs #########
atlas.rest.address=http://localhost:31000
######### Graph Database Configs #########
# Graph Storage
atlas.graph.storage.backend=${titan.storage.backend}
# Graph Search Index Backend
atlas.graph.index.search.backend=${titan.index.backend}
#Berkeley storage directory
atlas.graph.storage.directory=${sys:atlas.data}/berkley
#hbase
#For standalone mode , specify localhost
#for distributed mode, specify zookeeper quorum here - For more information refer http://s3.thinkaurelius.com/docs/titan/current/hbase.html#_remote_server_mode_2
atlas.graph.storage.hostname=${titan.storage.hostname}
atlas.graph.storage.hbase.regions-per-server=1
atlas.graph.storage.lock.wait-time=10000
#ElasticSearch
atlas.graph.index.search.directory=${sys:atlas.data}/es
atlas.graph.index.search.elasticsearch.client-only=false
atlas.graph.index.search.elasticsearch.local-mode=true
atlas.graph.index.search.elasticsearch.create.sleep=2000
# Solr cloud mode properties
atlas.graph.index.search.solr.mode=cloud
atlas.graph.index.search.solr.zookeeper-url=${solr.zk.address}
######### Hive Lineage Configs #########
# This models reflects the base super types for Data and Process
#atlas.lineage.hive.table.type.name=DataSet
#atlas.lineage.hive.process.type.name=Process
#atlas.lineage.hive.process.inputs.name=inputs
#atlas.lineage.hive.process.outputs.name=outputs
## Schema
atlas.lineage.hive.table.schema.query.hive_table=hive_table where name='%s'\, columns
######### Notification Configs #########
atlas.notification.embedded=true
atlas.kafka.zookeeper.connect=localhost:19026
atlas.kafka.bootstrap.servers=localhost:19027
atlas.kafka.data=${sys:atlas.data}/kafka
atlas.kafka.zookeeper.session.timeout.ms=4000
atlas.kafka.zookeeper.sync.time.ms=20
atlas.kafka.consumer.timeout.ms=100
atlas.kafka.auto.commit.interval.ms=100
atlas.kafka.hook.group.id=atlas
atlas.kafka.entities.group.id=atlas_entities
######### Entity Audit Configs #########
atlas.audit.hbase.tablename=ATLAS_ENTITY_AUDIT_EVENTS
atlas.audit.zookeeper.session.timeout.ms=1000
atlas.audit.hbase.zookeeper.quorum=localhost
atlas.audit.hbase.zookeeper.property.clientPort=19026
######### Security Properties #########
# SSL config
atlas.enableTLS=false
atlas.server.https.port=31443
######### Security Properties #########
hbase.security.authentication=simple
atlas.hook.falcon.synchronous=true
######### High Availability Configuration ########
atlas.server.ha.enabled=false
#atlas.server.ids=id1
#atlas.server.address.id1=localhost:21000
......@@ -434,7 +434,8 @@
<titan.storage.backend>berkeleyje</titan.storage.backend>
<titan.index.backend>elasticsearch</titan.index.backend>
<entity.repository.impl>org.apache.atlas.repository.audit.InMemoryEntityAuditRepository</entity.repository.impl>
<entity.repository.impl>org.apache.atlas.repository.audit.InMemoryEntityAuditRepository</entity.repository.impl>
<atlas.surefire.options></atlas.surefire.options>
</properties>
<profiles>
......@@ -446,10 +447,10 @@
</activation>
<properties>
<titan.storage.backend>hbase</titan.storage.backend>
<titan.index.backend>solr5</titan.index.backend>
<titan.index.backend>solr</titan.index.backend>
<solr.zk.address>localhost:9983</solr.zk.address>
<titan.storage.hostname>localhost</titan.storage.hostname>
<entity.repository.impl>org.apache.atlas.repository.audit.HBaseBasedAuditRepository</entity.repository.impl>
<entity.repository.impl>org.apache.atlas.repository.audit.HBaseBasedAuditRepository</entity.repository.impl>
</properties>
</profile>
......@@ -487,7 +488,6 @@
<module>notification</module>
<module>client</module>
<module>graphdb</module>
<module>titan</module>
<module>repository</module>
<module>authorization</module>
<module>catalog</module>
......@@ -683,6 +683,11 @@
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>${hadoop.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
......@@ -874,58 +879,7 @@
</dependency>
<!-- Graph DB -->
<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
<version>${tinkerpop.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-core</artifactId>
<version>${titan.version}</version>
<exclusions>
<!-- rexster does not work with servlet-api -->
<exclusion>
<groupId>com.tinkerpop.rexster</groupId>
<artifactId>rexster-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.tinkerpop.rexster</groupId>
<artifactId>rexster-server</artifactId>
</exclusion>
<!-- asm 4.0 does not work with jersey asm 3.1 -->
<exclusion>
<groupId>com.tinkerpop</groupId>
<artifactId>frames</artifactId>
</exclusion>
<exclusion>
<groupId>com.esotericsoftware.reflectasm</groupId>
<artifactId>reflectasm</artifactId>
</exclusion>
<exclusion>
<groupId>org.ow2.asm</groupId>
<artifactId>asm</artifactId>
</exclusion>
<exclusion> <!-- GPL license imported from ganglia -->
<groupId>org.acplt</groupId>
<artifactId>oncrpc</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-berkeleyje</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-hbase</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
......@@ -980,12 +934,6 @@
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-es</artifactId>
<version>${titan.version}</version>
</dependency>
<dependency>
<groupId>com.vividsolutions</groupId>
<artifactId>jts</artifactId>
<version>1.13</version>
......@@ -1016,6 +964,10 @@
<artifactId>*</artifactId>
<groupId>org.apache.lucene</groupId>
</exclusion>
<exclusion>
<artifactId>*</artifactId>
<groupId>org.apache.hadoop</groupId>
</exclusion>
</exclusions>
</dependency>
......@@ -1025,19 +977,6 @@
<version>${solr.version}</version>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-lucene</artifactId>
<version>${titan.version}</version>
<!--<scope>test</scope>-->
</dependency>
<dependency>
<groupId>com.tinkerpop.gremlin</groupId>
<artifactId>gremlin-java</artifactId>
<version>${tinkerpop.version}</version>
</dependency>
<!-- atlas modules -->
<dependency>
<groupId>org.apache.atlas</groupId>
......@@ -1055,7 +994,13 @@
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-titan</artifactId>
<artifactId>atlas-graphdb-api</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-graphdb-titan0</artifactId>
<version>${project.version}</version>
</dependency>
......@@ -1576,6 +1521,14 @@
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<configuration>
<excludeGroupIds>org.restlet.jee</excludeGroupIds>
</configuration>
</plugin>
</plugins>
</pluginManagement>
......@@ -1628,7 +1581,7 @@
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<argLine>-Djava.awt.headless=true -Dproject.version=${project.version}
-Dhadoop.tmp.dir="${project.build.directory}/tmp-hadoop-${user.name}"
-Xmx1024m -XX:MaxPermSize=512m -Djava.net.preferIPv4Stack=true
-Xmx1024m -XX:MaxPermSize=512m -Djava.net.preferIPv4Stack=true ${atlas.surefire.options}
</argLine>
<skip>${skipUTs}</skip>
</configuration>
......@@ -1654,7 +1607,7 @@
<redirectTestOutputToFile>true</redirectTestOutputToFile>
<argLine>-Djava.awt.headless=true -Dproject.version=${project.version}
-Dhadoop.tmp.dir="${project.build.directory}/tmp-hadoop-${user.name}"
-Xmx1024m -XX:MaxPermSize=512m
-Xmx1024m -XX:MaxPermSize=512m ${atlas.surefire.options}
</argLine>
<skip>${skipITs}</skip>
<parallel>none</parallel>
......@@ -1727,7 +1680,11 @@
<useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
<excludeSubProjects>true</excludeSubProjects>
<excludes>
<exclude>**/dependency-reduced-pom.xml</exclude>
<exclude>.reviewboardrc</exclude>
<exclude>3party-licenses/**</exclude>
<exclude>**/.cache-main</exclude>
<exclude>**/.checkstyle</exclude>
<exclude>*.txt</exclude>
<exclude>**/*.json</exclude>
<exclude>.pc/**</exclude>
......
......@@ -6,6 +6,7 @@ INCOMPATIBLE CHANGES:
ATLAS-1060 Add composite indexes for exact match performance improvements for all attributes (sumasai via shwethags)
ALL CHANGES:
ATLAS-693 Titan 0.5.4 implementation of the graph db abstraction {jnhagelb via dkantor)
ATLAS-1099 UI : multiple tag assign button hides wrongly (Kalyanikashikar via sumasai)
ATLAS-1087 Provide an option to turn off persisting entity definition in audits (sumasai, shwethags)
ATLAS-1097 Fix a potential NPE issue flagged by Coverity scan (mneethiraj via shwethags)
......
......@@ -49,7 +49,12 @@
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-titan</artifactId>
<artifactId>atlas-graphdb-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-graphdb-titan0</artifactId>
</dependency>
<dependency>
......@@ -83,16 +88,6 @@
</dependency>
<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
</dependency>
<dependency>
<groupId>com.tinkerpop.gremlin</groupId>
<artifactId>gremlin-java</artifactId>
</dependency>
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-reflect</artifactId>
</dependency>
......
......@@ -75,9 +75,12 @@ public class RepositoryMetadataModule extends com.google.inject.AbstractModule {
// bind the ITypeStore interface to an implementation
bind(ITypeStore.class).to(GraphBackedTypeStore.class).asEagerSingleton();
//GraphBackedSearchIndexer must be an eager singleton to force the search index creation to happen before
//we try to restore the type system (otherwise we'll end up running queries
//before we have any indices during the initial graph setup)
Multibinder<TypesChangeListener> typesChangeListenerBinder =
Multibinder.newSetBinder(binder(), TypesChangeListener.class);
typesChangeListenerBinder.addBinding().to(GraphBackedSearchIndexer.class);
typesChangeListenerBinder.addBinding().to(GraphBackedSearchIndexer.class).asEagerSingleton();
// bind the MetadataService interface to an implementation
bind(MetadataService.class).to(DefaultMetadataService.class).asEagerSingleton();
......
......@@ -18,18 +18,14 @@
package org.apache.atlas.repository.graph;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanProperty;
import com.thinkaurelius.titan.core.TitanVertex;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.Vertex;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import org.apache.atlas.AtlasException;
import org.apache.atlas.RequestContext;
import org.apache.atlas.repository.Constants;
......@@ -44,17 +40,23 @@ import org.apache.atlas.typesystem.types.DataTypes;
import org.apache.atlas.typesystem.types.HierarchicalType;
import org.apache.atlas.typesystem.types.IDataType;
import org.apache.atlas.typesystem.types.TypeSystem;
import org.apache.atlas.typesystem.types.utils.TypesUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.TitanProperty;
import com.thinkaurelius.titan.core.TitanVertex;
import com.tinkerpop.blueprints.Direction;
import com.tinkerpop.blueprints.Edge;
import com.tinkerpop.blueprints.Element;
import com.tinkerpop.blueprints.Graph;
import com.tinkerpop.blueprints.GraphQuery;
import com.tinkerpop.blueprints.Vertex;
/**
* Utility class for graph operations.
......@@ -295,7 +297,7 @@ public final class GraphHelper {
/**
* Remove the specified edge from the graph.
*
*
* @param edge
*/
public void removeEdge(Edge edge) {
......@@ -304,10 +306,10 @@ public final class GraphHelper {
titanGraph.removeEdge(edge);
LOG.info("Removed {}", edgeString);
}
/**
* Remove the specified vertex from the graph.
*
*
* @param vertex
*/
public void removeVertex(Vertex vertex) {
......@@ -488,4 +490,17 @@ public final class GraphHelper {
}
return key;
}
public static AttributeInfo getAttributeInfoForSystemAttributes(String field) {
switch (field) {
case Constants.STATE_PROPERTY_KEY:
case Constants.GUID_PROPERTY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.STRING_TYPE);
case Constants.TIMESTAMP_PROPERTY_KEY:
case Constants.MODIFICATION_TIMESTAMP_PROPERTY_KEY:
return TypesUtil.newAttributeInfo(field, DataTypes.LONG_TYPE);
}
return null;
}
}
\ No newline at end of file
......@@ -18,122 +18,33 @@
package org.apache.atlas.repository.graph;
import com.google.common.collect.ImmutableMap;
import com.google.inject.Provides;
import com.thinkaurelius.titan.core.TitanFactory;
import com.thinkaurelius.titan.core.TitanGraph;
import com.thinkaurelius.titan.core.schema.TitanManagement;
import com.thinkaurelius.titan.diskstorage.StandardIndexProvider;
import com.thinkaurelius.titan.diskstorage.solr.Solr5Index;
import org.apache.atlas.ApplicationProperties;
import org.apache.atlas.AtlasException;
import org.apache.atlas.repository.graphdb.titan0.Titan0Database;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Singleton;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;
import com.thinkaurelius.titan.core.TitanGraph;
/**
* Default implementation for Graph Provider that doles out Titan Graph.
* Temporary TitanGraphProvider to use until the graph database abstraction
* layer is fully in place. Delegates to the Titan 0.5.4 implementation. This
* will be removed once the abstraction layer is being used.
*/
public class TitanGraphProvider implements GraphProvider<TitanGraph> {
private static final Logger LOG = LoggerFactory.getLogger(TitanGraphProvider.class);
/**
* Constant for the configuration property that indicates the prefix.
*/
public static final String GRAPH_PREFIX = "atlas.graph";
public static final String INDEX_BACKEND_CONF = "index.search.backend";
public static final String INDEX_BACKEND_LUCENE = "lucene";
public static final String INDEX_BACKEND_ES = "elasticsearch";
private static volatile TitanGraph graphInstance;
public static Configuration getConfiguration() throws AtlasException {
Configuration configProperties = ApplicationProperties.get();
return ApplicationProperties.getSubsetConfiguration(configProperties, GRAPH_PREFIX);
}
static {
addSolr5Index();
}
/**
* Titan loads index backend name to implementation using StandardIndexProvider.ALL_MANAGER_CLASSES
* But StandardIndexProvider.ALL_MANAGER_CLASSES is a private static final ImmutableMap
* Only way to inject Solr5Index is to modify this field. So, using hacky reflection to add Sol5Index
/* (non-Javadoc)
* @see org.apache.atlas.repository.graph.GraphProvider#get()
*/
private static void addSolr5Index() {
try {
Field field = StandardIndexProvider.class.getDeclaredField("ALL_MANAGER_CLASSES");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
Map<String, String> customMap = new HashMap(StandardIndexProvider.getAllProviderClasses());
customMap.put("solr5", Solr5Index.class.getName());
ImmutableMap<String, String> immap = ImmutableMap.copyOf(customMap);
field.set(null, immap);
LOG.debug("Injected solr5 index - {}", Solr5Index.class.getName());
} catch(Exception e) {
throw new RuntimeException(e);
}
@Override
public TitanGraph get() {
return Titan0Database.getGraphInstance();
}
public static TitanGraph getGraphInstance() {
if (graphInstance == null) {
synchronized (TitanGraphProvider.class) {
if (graphInstance == null) {
Configuration config;
try {
config = getConfiguration();
} catch (AtlasException e) {
throw new RuntimeException(e);
}
graphInstance = TitanFactory.open(config);
validateIndexBackend(config);
}
}
}
return graphInstance;
}
public static void clear() {
synchronized (TitanGraphProvider.class) {
graphInstance.shutdown();
graphInstance = null;
}
return Titan0Database.getGraphInstance();
}
static void validateIndexBackend(Configuration config) {
String configuredIndexBackend = config.getString(INDEX_BACKEND_CONF);
TitanManagement managementSystem = graphInstance.getManagementSystem();
String currentIndexBackend = managementSystem.get(INDEX_BACKEND_CONF);
managementSystem.commit();
if(!configuredIndexBackend.equals(currentIndexBackend)) {
throw new RuntimeException("Configured Index Backend " + configuredIndexBackend + " differs from earlier configured Index Backend " + currentIndexBackend + ". Aborting!");
}
public static Configuration getConfiguration() throws AtlasException {
return Titan0Database.getConfiguration();
}
@Override
@Singleton
@Provides
public TitanGraph get() {
return getGraphInstance();
}
}
......@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger
import org.apache.atlas.AtlasException
import org.apache.atlas.query.Expressions.{LimitExpression, PathExpression, SelectExpression}
import org.apache.atlas.repository.Constants
import org.apache.atlas.repository.graph.GraphHelper
import org.apache.atlas.typesystem.types.DataTypes.{ArrayType, PrimitiveType, TypeCategory}
import org.apache.atlas.typesystem.types._
......@@ -204,7 +205,7 @@ object TypeUtils {
return Some(FieldInfo(typ,fMap.get.fields.get(id)))
}
val systemField = Constants.getAttributeInfoForSystemAttributes(id)
val systemField = GraphHelper.getAttributeInfoForSystemAttributes(id)
if (systemField != null) {
return Some(FieldInfo(systemField.dataType(), systemField))
}
......
......@@ -23,4 +23,7 @@
<suppressions>
<suppress checks="JavadocType" files="[/\\]src[/\\]test[/\\]java[/\\]"/>
<!-- skip checks on customized titan 0.5.4 files -->
<suppress checks="[a-zA-Z0-9]*" files="[/\\]com[/\\]thinkaurelius[/\\]titan[/\\]"/>
</suppressions>
......@@ -105,6 +105,11 @@
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-graphdb-titan0</artifactId>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-client</artifactId>
</dependency>
......@@ -123,7 +128,6 @@
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-minikdc</artifactId>
......@@ -133,7 +137,7 @@
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
</dependency>
<dependency>
<groupId>org.apache.atlas</groupId>
<artifactId>atlas-catalog</artifactId>
......@@ -166,16 +170,6 @@
</dependency>
<dependency>
<groupId>com.tinkerpop.blueprints</groupId>
<artifactId>blueprints-core</artifactId>
</dependency>
<dependency>
<groupId>com.thinkaurelius.titan</groupId>
<artifactId>titan-core</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
</dependency>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment