You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@atlas.apache.org by sa...@apache.org on 2017/10/27 21:16:26 UTC
[2/4] atlas git commit: ATLAS-1757: Introduce JanusGraph 0.1.1 graph
store in atlas
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/graphson/AtlasGraphSONUtility.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/graphson/AtlasGraphSONUtility.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/graphson/AtlasGraphSONUtility.java
new file mode 100644
index 0000000..b3c9095
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/graphson/AtlasGraphSONUtility.java
@@ -0,0 +1,513 @@
+/**
+ * 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.janus.graphson;
+
+import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasElement;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.graphdb.janus.graphson.AtlasElementPropertyConfig.ElementPropertiesRule;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.codehaus.jettison.json.JSONTokener;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeFactory;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * This class was largely removed from tinkerpop 1. We're adding it back here to
+ * avoid changing the format of the JSON that we produce.
+ *
+ * Helps write individual graph elements to TinkerPop JSON format known as
+ * GraphSON.
+ *
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+public final class AtlasGraphSONUtility {
+
+ private static final JsonNodeFactory JSON_NODE_FACTORY = JsonNodeFactory.instance;
+
+ private static final ObjectMapper MAPPER = new ObjectMapper();
+
+ private final AtlasGraphSONMode mode;
+ private final List<String> vertexPropertyKeys;
+ private final List<String> edgePropertyKeys;
+
+ private final ElementPropertiesRule vertexPropertiesRule;
+ private final ElementPropertiesRule edgePropertiesRule;
+ private final boolean normalized;
+
+ private final boolean includeReservedVertexId;
+ private final boolean includeReservedEdgeId;
+ private final boolean includeReservedVertexType;
+ private final boolean includeReservedEdgeType;
+ private final boolean includeReservedEdgeLabel;
+ private final boolean includeReservedEdgeOutV;
+ private final boolean includeReservedEdgeInV;
+
+ /**
+ * A GraphSONUtility that includes the specified properties.
+ */
+ private AtlasGraphSONUtility(final AtlasGraphSONMode mode, final Set<String> vertexPropertyKeySet,
+ final Set<String> edgePropertyKeySet) {
+
+ AtlasElementPropertyConfig config = AtlasElementPropertyConfig.includeProperties(vertexPropertyKeySet,
+ edgePropertyKeySet);
+
+ this.vertexPropertyKeys = config.getVertexPropertyKeys();
+ this.edgePropertyKeys = config.getEdgePropertyKeys();
+ this.vertexPropertiesRule = config.getVertexPropertiesRule();
+ this.edgePropertiesRule = config.getEdgePropertiesRule();
+ this.normalized = config.isNormalized();
+
+ this.mode = mode;
+
+ this.includeReservedVertexId = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_ID, vertexPropertyKeys,
+ this.vertexPropertiesRule);
+ this.includeReservedEdgeId = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_ID, edgePropertyKeys,
+ this.edgePropertiesRule);
+ this.includeReservedVertexType = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_TYPE, vertexPropertyKeys,
+ this.vertexPropertiesRule);
+ this.includeReservedEdgeType = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_TYPE, edgePropertyKeys,
+ this.edgePropertiesRule);
+ this.includeReservedEdgeLabel = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_LABEL, edgePropertyKeys,
+ this.edgePropertiesRule);
+ this.includeReservedEdgeOutV = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_OUT_V, edgePropertyKeys,
+ this.edgePropertiesRule);
+ this.includeReservedEdgeInV = includeReservedKey(mode, AtlasGraphSONTokens.INTERNAL_IN_V, edgePropertyKeys,
+ this.edgePropertiesRule);
+ }
+
+ /*
+ * Creates GraphSON for a single graph element.
+ */
+ private JSONObject jsonFromElement(final AtlasElement element) throws JSONException {
+ final ObjectNode objectNode = this.objectNodeFromElement(element);
+
+ try {
+ return new JSONObject(new JSONTokener(MAPPER.writeValueAsString(objectNode)));
+ } catch (IOException ioe) {
+ // repackage this as a JSONException...seems sensible as the caller will only know about
+ // the jettison object not being created
+ throw new JSONException(ioe);
+ }
+ }
+
+ /**
+ * Creates GraphSON for a single graph element.
+ */
+ private ObjectNode objectNodeFromElement(final AtlasElement element) {
+ final boolean isEdge = element instanceof AtlasEdge;
+ final boolean showTypes = mode == AtlasGraphSONMode.EXTENDED;
+ final List<String> propertyKeys = isEdge ? this.edgePropertyKeys : this.vertexPropertyKeys;
+ final ElementPropertiesRule elementPropertyConfig = isEdge ? this.edgePropertiesRule
+ : this.vertexPropertiesRule;
+
+ final ObjectNode jsonElement = createJSONMap(
+ createPropertyMap(element, propertyKeys, elementPropertyConfig, normalized), propertyKeys, showTypes);
+
+ if ((isEdge && this.includeReservedEdgeId) || (!isEdge && this.includeReservedVertexId)) {
+ putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId());
+ }
+
+ // it's important to keep the order of these straight. check AtlasEdge first and then AtlasVertex because there
+ // are graph implementations that have AtlasEdge extend from AtlasVertex
+ if (element instanceof AtlasEdge) {
+ final AtlasEdge edge = (AtlasEdge) element;
+
+ if (this.includeReservedEdgeId) {
+ putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId());
+ }
+
+ if (this.includeReservedEdgeType) {
+ jsonElement.put(AtlasGraphSONTokens.INTERNAL_TYPE, AtlasGraphSONTokens.EDGE);
+ }
+
+ if (this.includeReservedEdgeOutV) {
+ putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_OUT_V, edge.getOutVertex().getId());
+ }
+
+ if (this.includeReservedEdgeInV) {
+ putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_IN_V, edge.getInVertex().getId());
+ }
+
+ if (this.includeReservedEdgeLabel) {
+ jsonElement.put(AtlasGraphSONTokens.INTERNAL_LABEL, edge.getLabel());
+ }
+ } else if (element instanceof AtlasVertex) {
+ if (this.includeReservedVertexId) {
+ putObject(jsonElement, AtlasGraphSONTokens.INTERNAL_ID, element.getId());
+ }
+
+ if (this.includeReservedVertexType) {
+ jsonElement.put(AtlasGraphSONTokens.INTERNAL_TYPE, AtlasGraphSONTokens.VERTEX);
+ }
+ }
+
+ return jsonElement;
+ }
+
+ /**
+ * Creates a Jettison JSONObject from a graph element.
+ *
+ * @param element
+ * the graph element to convert to JSON.
+ * @param propertyKeys
+ * The property getPropertyKeys() at the root of the element to
+ * serialize. If null, then all getPropertyKeys() are serialized.
+ * @param mode
+ * the type of GraphSON to be generated.
+ */
+ public static JSONObject jsonFromElement(final AtlasElement element, final Set<String> propertyKeys,
+ final AtlasGraphSONMode mode)
+ throws JSONException {
+
+ final AtlasGraphSONUtility graphson = element instanceof AtlasEdge
+ ? new AtlasGraphSONUtility(mode, null, propertyKeys)
+ : new AtlasGraphSONUtility(mode, propertyKeys, null);
+ return graphson.jsonFromElement(element);
+ }
+
+ private static ObjectNode objectNodeFromElement(final AtlasElement element, final List<String> propertyKeys,
+ final AtlasGraphSONMode mode) {
+ final AtlasGraphSONUtility graphson = element instanceof AtlasEdge
+ ? new AtlasGraphSONUtility(mode, null, new HashSet<String>(propertyKeys))
+ : new AtlasGraphSONUtility(mode, new HashSet<String>(propertyKeys), null);
+ return graphson.objectNodeFromElement(element);
+ }
+
+ private static boolean includeReservedKey(final AtlasGraphSONMode mode, final String key,
+ final List<String> propertyKeys, final ElementPropertiesRule rule) {
+ // the key is always included in modes other than compact. if it is compact, then validate that the
+ // key is in the property key list
+ return mode != AtlasGraphSONMode.COMPACT || includeKey(key, propertyKeys, rule);
+ }
+
+ private static boolean includeKey(final String key, final List<String> propertyKeys,
+ final ElementPropertiesRule rule) {
+ if (propertyKeys == null) {
+ // when null always include the key and shortcut this piece
+ return true;
+ }
+
+ // default the key situation. if it's included then it should be explicitly defined in the
+ // property getPropertyKeys() list to be included or the reverse otherwise
+ boolean keySituation = rule == ElementPropertiesRule.INCLUDE;
+
+ switch (rule) {
+ case INCLUDE:
+ keySituation = propertyKeys.contains(key);
+ break;
+ case EXCLUDE:
+ keySituation = !propertyKeys.contains(key);
+ break;
+ default:
+ throw new RuntimeException("Unhandled rule: " + rule);
+ }
+
+ return keySituation;
+ }
+
+ private static ArrayNode createJSONList(final List<Object> list, final List<String> propertyKeys,
+ final boolean showTypes) {
+ final ArrayNode jsonList = JSON_NODE_FACTORY.arrayNode();
+ for (Object item : list) {
+ if (item instanceof AtlasElement) {
+ jsonList.add(objectNodeFromElement((AtlasElement) item, propertyKeys,
+ showTypes ? AtlasGraphSONMode.EXTENDED : AtlasGraphSONMode.NORMAL));
+ } else if (item instanceof List) {
+ jsonList.add(createJSONList((List<Object>) item, propertyKeys, showTypes));
+ } else if (item instanceof Map) {
+ jsonList.add(createJSONMap((Map<String, Object>) item, propertyKeys, showTypes));
+ } else if (item != null && item.getClass().isArray()) {
+ jsonList.add(createJSONList(convertArrayToList(item), propertyKeys, showTypes));
+ } else {
+ addObject(jsonList, item);
+ }
+ }
+ return jsonList;
+ }
+
+ private static ObjectNode createJSONMap(final Map<String, Object> map, final List<String> propertyKeys,
+ final boolean showTypes) {
+ final ObjectNode jsonMap = JSON_NODE_FACTORY.objectNode();
+ for (Object key : map.keySet()) {
+ Object value = map.get(key);
+ if (value != null) {
+ if (value instanceof List) {
+ value = createJSONList((List<Object>) value, propertyKeys, showTypes);
+ } else if (value instanceof Map) {
+ value = createJSONMap((Map<String, Object>) value, propertyKeys, showTypes);
+ } else if (value instanceof AtlasElement) {
+ value = objectNodeFromElement((AtlasElement) value, propertyKeys,
+ showTypes ? AtlasGraphSONMode.EXTENDED : AtlasGraphSONMode.NORMAL);
+ } else if (value.getClass().isArray()) {
+ value = createJSONList(convertArrayToList(value), propertyKeys, showTypes);
+ }
+ }
+
+ putObject(jsonMap, key.toString(), getValue(value, showTypes));
+ }
+ return jsonMap;
+
+ }
+
+ private static void addObject(final ArrayNode jsonList, final Object value) {
+ if (value == null) {
+ jsonList.add((JsonNode) null);
+ } else if (value.getClass() == Boolean.class) {
+ jsonList.add((Boolean) value);
+ } else if (value.getClass() == Long.class) {
+ jsonList.add((Long) value);
+ } else if (value.getClass() == Integer.class) {
+ jsonList.add((Integer) value);
+ } else if (value.getClass() == Float.class) {
+ jsonList.add((Float) value);
+ } else if (value.getClass() == Double.class) {
+ jsonList.add((Double) value);
+ } else if (value.getClass() == Byte.class) {
+ jsonList.add((Byte) value);
+ } else if (value.getClass() == Short.class) {
+ jsonList.add((Short) value);
+ } else if (value.getClass() == String.class) {
+ jsonList.add((String) value);
+ } else if (value instanceof ObjectNode) {
+ jsonList.add((ObjectNode) value);
+ } else if (value instanceof ArrayNode) {
+ jsonList.add((ArrayNode) value);
+ } else {
+ jsonList.add(value.toString());
+ }
+ }
+
+ private static void putObject(final ObjectNode jsonMap, final String key, final Object value) {
+ if (value == null) {
+ jsonMap.put(key, (JsonNode) null);
+ } else if (value.getClass() == Boolean.class) {
+ jsonMap.put(key, (Boolean) value);
+ } else if (value.getClass() == Long.class) {
+ jsonMap.put(key, (Long) value);
+ } else if (value.getClass() == Integer.class) {
+ jsonMap.put(key, (Integer) value);
+ } else if (value.getClass() == Float.class) {
+ jsonMap.put(key, (Float) value);
+ } else if (value.getClass() == Double.class) {
+ jsonMap.put(key, (Double) value);
+ } else if (value.getClass() == Short.class) {
+ jsonMap.put(key, (Short) value);
+ } else if (value.getClass() == Byte.class) {
+ jsonMap.put(key, (Byte) value);
+ } else if (value.getClass() == String.class) {
+ jsonMap.put(key, (String) value);
+ } else if (value instanceof ObjectNode) {
+ jsonMap.put(key, (ObjectNode) value);
+ } else if (value instanceof ArrayNode) {
+ jsonMap.put(key, (ArrayNode) value);
+ } else {
+ jsonMap.put(key, value.toString());
+ }
+ }
+
+ private static Map<String, Object> createPropertyMap(final AtlasElement element, final List<String> propertyKeys,
+ final ElementPropertiesRule rule, final boolean normalized) {
+ final Map<String, Object> map = new HashMap<String, Object>();
+ final List<String> propertyKeyList;
+ if (normalized) {
+ final List<String> sorted = new ArrayList<String>(element.getPropertyKeys());
+ Collections.sort(sorted);
+ propertyKeyList = sorted;
+ } else {
+ propertyKeyList = new ArrayList<String>(element.getPropertyKeys());
+ }
+
+ if (propertyKeys == null) {
+ for (String key : propertyKeyList) {
+ final Object valToPutInMap = element.getProperty(key, Object.class);
+ if (valToPutInMap != null) {
+ map.put(key, valToPutInMap);
+ }
+ }
+ } else {
+ if (rule == ElementPropertiesRule.INCLUDE) {
+ for (String key : propertyKeys) {
+ final Object valToPutInMap = element.getProperty(key, Object.class);
+ if (valToPutInMap != null) {
+ map.put(key, valToPutInMap);
+ }
+ }
+ } else {
+ for (String key : propertyKeyList) {
+ if (!propertyKeys.contains(key)) {
+ final Object valToPutInMap = element.getProperty(key, Object.class);
+ if (valToPutInMap != null) {
+ map.put(key, valToPutInMap);
+ }
+ }
+ }
+ }
+ }
+
+ return map;
+ }
+
+ private static Object getValue(Object value, final boolean includeType) {
+
+ Object returnValue = value;
+
+ // if the includeType is set to true then show the data types of the properties
+ if (includeType) {
+
+ // type will be one of: map, list, string, long, int, double, float.
+ // in the event of a complex object it will call a toString and store as a
+ // string
+ String type = determineType(value);
+
+ ObjectNode valueAndType = JSON_NODE_FACTORY.objectNode();
+ valueAndType.put(AtlasGraphSONTokens.TYPE, type);
+
+ if (type.equals(AtlasGraphSONTokens.TYPE_LIST)) {
+
+ // values of lists must be accumulated as ObjectNode objects under the value key.
+ // will return as a ArrayNode. called recursively to traverse the entire
+ // object graph of each item in the array.
+ ArrayNode list = (ArrayNode) value;
+
+ // there is a set of values that must be accumulated as an array under a key
+ ArrayNode valueArray = valueAndType.putArray(AtlasGraphSONTokens.VALUE);
+ for (int ix = 0; ix < list.size(); ix++) {
+ // the value of each item in the array is a node object from an ArrayNode...must
+ // get the value of it.
+ addObject(valueArray, getValue(getTypedValueFromJsonNode(list.get(ix)), includeType));
+ }
+
+ } else if (type.equals(AtlasGraphSONTokens.TYPE_MAP)) {
+
+ // maps are converted to a ObjectNode. called recursively to traverse
+ // the entire object graph within the map.
+ ObjectNode convertedMap = JSON_NODE_FACTORY.objectNode();
+ ObjectNode jsonObject = (ObjectNode) value;
+ Iterator<?> keyIterator = jsonObject.fieldNames();
+ while (keyIterator.hasNext()) {
+ Object key = keyIterator.next();
+
+ // no need to getValue() here as this is already a ObjectNode and should have type info
+ convertedMap.put(key.toString(), jsonObject.get(key.toString()));
+ }
+
+ valueAndType.put(AtlasGraphSONTokens.VALUE, convertedMap);
+ } else {
+
+ // this must be a primitive value or a complex object. if a complex
+ // object it will be handled by a call to toString and stored as a
+ // string value
+ putObject(valueAndType, AtlasGraphSONTokens.VALUE, value);
+ }
+
+ // this goes back as a JSONObject with data type and value
+ returnValue = valueAndType;
+ }
+
+ return returnValue;
+ }
+
+ private static Object getTypedValueFromJsonNode(JsonNode node) {
+ Object theValue = null;
+
+ if (node != null && !node.isNull()) {
+ if (node.isBoolean()) {
+ theValue = node.booleanValue();
+ } else if (node.isDouble()) {
+ theValue = node.doubleValue();
+ } else if (node.isFloatingPointNumber()) {
+ theValue = node.floatValue();
+ } else if (node.isInt()) {
+ theValue = node.intValue();
+ } else if (node.isLong()) {
+ theValue = node.longValue();
+ } else if (node.isTextual()) {
+ theValue = node.textValue();
+ } else if (node.isArray()) {
+ // this is an array so just send it back so that it can be
+ // reprocessed to its primitive components
+ theValue = node;
+ } else if (node.isObject()) {
+ // this is an object so just send it back so that it can be
+ // reprocessed to its primitive components
+ theValue = node;
+ } else {
+ theValue = node.textValue();
+ }
+ }
+
+ return theValue;
+ }
+
+ private static List<Object> convertArrayToList(final Object value) {
+ final ArrayList<Object> list = new ArrayList<Object>();
+ int arrlength = Array.getLength(value);
+ for (int i = 0; i < arrlength; i++) {
+ Object object = Array.get(value, i);
+ list.add(object);
+ }
+ return list;
+ }
+
+ private static String determineType(final Object value) {
+ String type = AtlasGraphSONTokens.TYPE_STRING;
+ if (value == null) {
+ type = AtlasGraphSONTokens.TYPE_UNKNOWN;
+ } else if (value.getClass() == Double.class) {
+ type = AtlasGraphSONTokens.TYPE_DOUBLE;
+ } else if (value.getClass() == Float.class) {
+ type = AtlasGraphSONTokens.TYPE_FLOAT;
+ } else if (value.getClass() == Byte.class) {
+ type = AtlasGraphSONTokens.TYPE_BYTE;
+ } else if (value.getClass() == Short.class) {
+ type = AtlasGraphSONTokens.TYPE_SHORT;
+ } else if (value.getClass() == Integer.class) {
+ type = AtlasGraphSONTokens.TYPE_INTEGER;
+ } else if (value.getClass() == Long.class) {
+ type = AtlasGraphSONTokens.TYPE_LONG;
+ } else if (value.getClass() == Boolean.class) {
+ type = AtlasGraphSONTokens.TYPE_BOOLEAN;
+ } else if (value instanceof ArrayNode) {
+ type = AtlasGraphSONTokens.TYPE_LIST;
+ } else if (value instanceof ObjectNode) {
+ type = AtlasGraphSONTokens.TYPE_MAP;
+ }
+
+ return type;
+ }
+
+ static class ElementFactory {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/AtlasJanusGraphQuery.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/AtlasJanusGraphQuery.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/AtlasJanusGraphQuery.java
new file mode 100644
index 0000000..3ea04aa
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/AtlasJanusGraphQuery.java
@@ -0,0 +1,56 @@
+/**
+ * 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.janus.query;
+
+import org.apache.atlas.repository.graphdb.AtlasGraphQuery;
+import org.apache.atlas.repository.graphdb.tinkerpop.query.TinkerpopGraphQuery;
+import org.apache.atlas.repository.graphdb.tinkerpop.query.NativeTinkerpopGraphQuery;
+import org.apache.atlas.repository.graphdb.tinkerpop.query.NativeTinkerpopQueryFactory;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusEdge;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusGraph;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusVertex;
+
+/**
+ * Janus implementation of TinkerpopGraphQuery.
+ */
+public class AtlasJanusGraphQuery extends TinkerpopGraphQuery<AtlasJanusVertex, AtlasJanusEdge>
+ implements NativeTinkerpopQueryFactory<AtlasJanusVertex, AtlasJanusEdge> {
+
+ public AtlasJanusGraphQuery(AtlasJanusGraph graph, boolean isChildQuery) {
+ super(graph, isChildQuery);
+ }
+
+ public AtlasJanusGraphQuery(AtlasJanusGraph graph) {
+ super(graph);
+ }
+
+ @Override
+ public AtlasGraphQuery<AtlasJanusVertex, AtlasJanusEdge> createChildQuery() {
+ return new AtlasJanusGraphQuery((AtlasJanusGraph) graph, true);
+ }
+
+ @Override
+ protected NativeTinkerpopQueryFactory<AtlasJanusVertex, AtlasJanusEdge> getQueryFactory() {
+ return this;
+ }
+
+ @Override
+ public NativeTinkerpopGraphQuery<AtlasJanusVertex, AtlasJanusEdge> createNativeTinkerpopQuery() {
+ return new NativeJanusGraphQuery((AtlasJanusGraph) graph);
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java
new file mode 100644
index 0000000..679e3dc
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/query/NativeJanusGraphQuery.java
@@ -0,0 +1,141 @@
+/**
+ * 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.janus.query;
+
+import org.janusgraph.core.JanusGraphEdge;
+import org.janusgraph.core.JanusGraphQuery;
+import org.janusgraph.core.JanusGraphVertex;
+import org.janusgraph.core.attribute.Contain;
+import org.janusgraph.core.attribute.Text;
+import org.janusgraph.graphdb.query.JanusGraphPredicate;
+import org.apache.atlas.repository.graphdb.AtlasEdge;
+import org.apache.atlas.repository.graphdb.AtlasGraphQuery.ComparisionOperator;
+import org.apache.atlas.repository.graphdb.AtlasGraphQuery.MatchingOperator;
+import org.apache.atlas.repository.graphdb.AtlasGraphQuery.QueryOperator;
+import org.apache.atlas.repository.graphdb.AtlasVertex;
+import org.apache.atlas.repository.graphdb.tinkerpop.query.NativeTinkerpopGraphQuery;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusEdge;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusGraph;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusGraphDatabase;
+import org.apache.atlas.repository.graphdb.janus.AtlasJanusVertex;
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+
+import java.util.*;
+
+/**
+ * Janus implementation of NativeTinkerpopGraphQuery.
+ */
+public class NativeJanusGraphQuery implements NativeTinkerpopGraphQuery<AtlasJanusVertex, AtlasJanusEdge> {
+
+ private AtlasJanusGraph graph;
+ private JanusGraphQuery<?> query;
+
+ public NativeJanusGraphQuery(AtlasJanusGraph graph) {
+ this.query = AtlasJanusGraphDatabase.getGraphInstance().query();
+ this.graph = graph;
+ }
+
+ @Override
+ public Iterable<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>> vertices() {
+ Iterable<JanusGraphVertex> it = query.vertices();
+ return graph.wrapVertices(it);
+ }
+
+ @Override
+ public Iterable<AtlasEdge<AtlasJanusVertex, AtlasJanusEdge>> edges() {
+ Iterable<JanusGraphEdge> it = query.edges();
+ return graph.wrapEdges(it);
+ }
+
+ @Override
+ public Iterable<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>> vertices(int limit) {
+ Iterable<JanusGraphVertex> it = query.limit(limit).vertices();
+ return graph.wrapVertices(it);
+ }
+
+ @Override
+ public Iterable<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>> vertices(int offset, int limit) {
+ List<Vertex> result = new ArrayList<>(limit);
+ Iterator<? extends Vertex> iter = query.limit(offset + limit).vertices().iterator();
+
+ for (long resultIdx = 0; iter.hasNext() && result.size() < limit; resultIdx++) {
+ if (resultIdx < offset) {
+ continue;
+ }
+
+ result.add(iter.next());
+ }
+
+ return graph.wrapVertices(result);
+ }
+
+ @Override
+ public void in(String propertyName, Collection<? extends Object> values) {
+ query.has(propertyName, Contain.IN, values);
+
+ }
+
+ @Override
+ public void has(String propertyName, QueryOperator op, Object value) {
+ JanusGraphPredicate pred;
+ if (op instanceof ComparisionOperator) {
+ Compare c = getGremlinPredicate((ComparisionOperator) op);
+ pred = JanusGraphPredicate.Converter.convert(c);
+ } else {
+ pred = getGremlinPredicate((MatchingOperator)op);
+ }
+ query.has(propertyName, pred, value);
+ }
+
+ private Text getGremlinPredicate(MatchingOperator op) {
+ switch (op) {
+ case CONTAINS:
+ return Text.CONTAINS;
+ case PREFIX:
+ return Text.PREFIX;
+ case SUFFIX:
+ return Text.CONTAINS_REGEX;
+ case REGEX:
+ return Text.REGEX;
+ default:
+ throw new RuntimeException("Unsupported matching operator:" + op);
+ }
+ }
+
+ private Compare getGremlinPredicate(ComparisionOperator op) {
+ switch (op) {
+ case EQUAL:
+ return Compare.eq;
+ case GREATER_THAN:
+ return Compare.gt;
+ case GREATER_THAN_EQUAL:
+ return Compare.gte;
+ case LESS_THAN:
+ return Compare.lt;
+ case LESS_THAN_EQUAL:
+ return Compare.lte;
+ case NOT_EQUAL:
+ return Compare.neq;
+
+ default:
+ throw new RuntimeException("Unsupported comparison operator:" + op);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigDecimalSerializer.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigDecimalSerializer.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigDecimalSerializer.java
new file mode 100644
index 0000000..cd63f9f
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigDecimalSerializer.java
@@ -0,0 +1,49 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.graphdb.janus.serializer;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.janusgraph.core.attribute.AttributeSerializer;
+import org.janusgraph.diskstorage.ScanBuffer;
+import org.janusgraph.diskstorage.WriteBuffer;
+
+/**
+ * Serializer for BigDecimal values.
+ */
+public class BigDecimalSerializer implements AttributeSerializer<BigDecimal> {
+
+ private final BigIntegerSerializer bigIntegerDelegate = new BigIntegerSerializer();
+
+ @Override
+ public BigDecimal read(ScanBuffer buffer) {
+ BigInteger unscaledVal = bigIntegerDelegate.read(buffer);
+ int scale = buffer.getInt();
+ return new BigDecimal(unscaledVal, scale);
+ }
+
+ @Override
+ public void write(WriteBuffer buffer, BigDecimal attribute) {
+ BigInteger unscaledVal = attribute.unscaledValue();
+ int scale = attribute.scale();
+ bigIntegerDelegate.write(buffer, unscaledVal);
+ buffer.putInt(scale);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigIntegerSerializer.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigIntegerSerializer.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigIntegerSerializer.java
new file mode 100644
index 0000000..04af099
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/BigIntegerSerializer.java
@@ -0,0 +1,46 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.atlas.repository.graphdb.janus.serializer;
+
+import java.math.BigInteger;
+
+import org.janusgraph.core.attribute.AttributeSerializer;
+import org.janusgraph.diskstorage.ScanBuffer;
+import org.janusgraph.diskstorage.WriteBuffer;
+import org.janusgraph.graphdb.database.serialize.attribute.ByteArraySerializer;
+
+/**
+ * Serializer for BigInteger values.
+ */
+public class BigIntegerSerializer implements AttributeSerializer<BigInteger> {
+
+ private final ByteArraySerializer delegate = new ByteArraySerializer();
+
+ @Override
+ public BigInteger read(ScanBuffer buffer) {
+ byte[] value = delegate.read(buffer);
+ return new BigInteger(value);
+ }
+
+ @Override
+ public void write(WriteBuffer buffer, BigInteger attribute) {
+ byte[] value = attribute.toByteArray();
+ delegate.write(buffer, value);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/StringListSerializer.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/StringListSerializer.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/StringListSerializer.java
new file mode 100644
index 0000000..fa6f5fd
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/StringListSerializer.java
@@ -0,0 +1,54 @@
+/**
+ * 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.janus.serializer;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.janusgraph.core.attribute.AttributeSerializer;
+import org.janusgraph.diskstorage.ScanBuffer;
+import org.janusgraph.diskstorage.WriteBuffer;
+import org.janusgraph.graphdb.database.idhandling.VariableLong;
+import org.janusgraph.graphdb.database.serialize.attribute.StringSerializer;
+
+/**
+ * Serializer for String lists.
+ */
+public class StringListSerializer implements AttributeSerializer<List<String>> {
+
+ private final StringSerializer stringSerializer = new StringSerializer();
+
+ @Override
+ public List<String> read(ScanBuffer buffer) {
+ int length = (int)VariableLong.readPositive(buffer);
+ List<String> result = new ArrayList<String>(length);
+ for(int i = 0; i < length; i++) {
+ result.add(stringSerializer.read(buffer));
+ }
+ return result;
+ }
+
+ @Override
+ public void write(WriteBuffer buffer, List<String> attributes) {
+ VariableLong.writePositive(buffer, attributes.size());
+ for(String attr : attributes) {
+ stringSerializer.write(buffer, attr);
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/TypeCategorySerializer.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/TypeCategorySerializer.java b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/TypeCategorySerializer.java
new file mode 100644
index 0000000..3db6679
--- /dev/null
+++ b/graphdb/janus/src/main/java/org/apache/atlas/repository/graphdb/janus/serializer/TypeCategorySerializer.java
@@ -0,0 +1,31 @@
+/**
+ * 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.janus.serializer;
+
+import org.apache.atlas.typesystem.types.DataTypes.TypeCategory;
+
+import org.janusgraph.graphdb.database.serialize.attribute.EnumSerializer;
+
+/**
+ * Serializer for TypeCategory value.
+ */
+public class TypeCategorySerializer extends EnumSerializer<TypeCategory> {
+ public TypeCategorySerializer() {
+ super(TypeCategory.class);
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory b/graphdb/janus/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
new file mode 100644
index 0000000..24c8a75
--- /dev/null
+++ b/graphdb/janus/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory
@@ -0,0 +1 @@
+org.apache.tinkerpop.gremlin.groovy.jsr223.GremlinGroovyScriptEngineFactory
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AbstractGraphDatabaseTest.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AbstractGraphDatabaseTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AbstractGraphDatabaseTest.java
new file mode 100644
index 0000000..5574a4c
--- /dev/null
+++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AbstractGraphDatabaseTest.java
@@ -0,0 +1,189 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.atlas.repository.graphdb.janus;
+
+import org.apache.atlas.graph.GraphSandboxUtil;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graphdb.AtlasCardinality;
+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.testng.annotations.AfterClass;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeClass;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ *
+ */
+public abstract class AbstractGraphDatabaseTest {
+
+ protected static final String WEIGHT_PROPERTY = "weight";
+ protected static final String TRAIT_NAMES = Constants.TRAIT_NAMES_PROPERTY_KEY;
+ protected static final String TYPE_PROPERTY_NAME = "__type";
+ protected static final String TYPESYSTEM = "TYPESYSTEM";
+
+ private static final String BACKING_INDEX_NAME = "backing";
+
+ private AtlasGraph<?, ?> graph = null;
+
+ @BeforeClass
+ public static void createIndices() {
+ GraphSandboxUtil.create();
+
+ AtlasJanusGraphDatabase db = new AtlasJanusGraphDatabase();
+ AtlasGraphManagement mgmt = db.getGraph().getManagementSystem();
+
+ if (mgmt.getGraphIndex(BACKING_INDEX_NAME) == null) {
+ mgmt.createVertexIndex(BACKING_INDEX_NAME, Constants.BACKING_INDEX,
+ Collections.<AtlasPropertyKey>emptyList());
+ }
+ mgmt.makePropertyKey("age13", Integer.class, AtlasCardinality.SINGLE);
+
+ createIndices(mgmt, "name", String.class, false, AtlasCardinality.SINGLE);
+ createIndices(mgmt, WEIGHT_PROPERTY, Integer.class, false, AtlasCardinality.SINGLE);
+ createIndices(mgmt, "size15", String.class, false, AtlasCardinality.SINGLE);
+ createIndices(mgmt, "typeName", String.class, false, AtlasCardinality.SINGLE);
+ createIndices(mgmt, "__type", String.class, false, AtlasCardinality.SINGLE);
+ createIndices(mgmt, Constants.GUID_PROPERTY_KEY, String.class, true, AtlasCardinality.SINGLE);
+ createIndices(mgmt, Constants.TRAIT_NAMES_PROPERTY_KEY, String.class, false, AtlasCardinality.SET);
+ createIndices(mgmt, Constants.SUPER_TYPES_PROPERTY_KEY, String.class, false, AtlasCardinality.SET);
+ mgmt.commit();
+ }
+
+ @AfterMethod
+ public void commitGraph() {
+ //force any pending actions to be committed so we can be sure they don't cause errors.
+ pushChangesAndFlushCache();
+ getGraph().commit();
+ }
+
+ @AfterClass
+ public static void cleanUp() {
+ AtlasJanusGraph graph = new AtlasJanusGraph();
+ graph.clear();
+
+ }
+
+ protected <V, E> void pushChangesAndFlushCache() {
+ getGraph().commit();
+ }
+
+ private static void createIndices(AtlasGraphManagement management, String propertyName, Class propertyClass,
+ boolean isUnique, AtlasCardinality cardinality) {
+
+ if (management.containsPropertyKey(propertyName)) {
+ //index was already created
+ return;
+ }
+
+ AtlasPropertyKey key = management.makePropertyKey(propertyName, propertyClass, cardinality);
+ try {
+ if (propertyClass != Integer.class) {
+ management.addVertexIndexKey(BACKING_INDEX_NAME, key);
+ }
+ } catch(Throwable t) {
+ //ok
+ t.printStackTrace();
+ }
+ try {
+ management.createExactMatchIndex(propertyName, isUnique, Collections.singletonList(key));
+
+ } catch(Throwable t) {
+ //ok
+ t.printStackTrace();
+ }
+
+
+ }
+
+
+
+
+ protected final <V, E> AtlasGraph<V, E> getGraph() {
+ if (graph == null) {
+ graph = new AtlasJanusGraph();
+ }
+ return (AtlasGraph<V, E>)graph;
+ }
+
+ protected AtlasJanusGraph getAtlasJanusGraph() {
+ AtlasGraph g = getGraph();
+ return (AtlasJanusGraph)g;
+ }
+
+
+ protected List<AtlasVertex> newVertices = new ArrayList<>();
+
+ protected final <V, E> AtlasVertex<V, E> createVertex(AtlasGraph<V, E> theGraph) {
+ AtlasVertex<V, E> vertex = theGraph.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;
+ }
+ }
+
+ private static final 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;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java
new file mode 100644
index 0000000..4919de2
--- /dev/null
+++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/AtlasJanusDatabaseTest.java
@@ -0,0 +1,431 @@
+/**
+ * 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.janus;
+
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.graph.GraphSandboxUtil;
+import org.apache.atlas.repository.Constants;
+import org.apache.atlas.repository.graphdb.AtlasCardinality;
+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.testng.annotations.AfterClass;
+import org.testng.annotations.Test;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import static org.testng.Assert.*;
+
+/**
+ * Sanity test of basic graph operations using the Janus graphdb
+ * abstraction layer implementation.
+ */
+public class AtlasJanusDatabaseTest {
+
+ private AtlasGraph<?, ?> atlasGraph;
+
+ private <V, E> AtlasGraph<V, E> getGraph() {
+ GraphSandboxUtil.create();
+
+ if (atlasGraph == null) {
+ AtlasJanusGraphDatabase db = new AtlasJanusGraphDatabase();
+ atlasGraph = db.getGraph();
+ AtlasGraphManagement mgmt = atlasGraph.getManagementSystem();
+ // create the index (which defines these properties as being mult
+ // many)
+ for (String propertyName : new String[]{"__superTypeNames", "__traitNames"}) {
+ AtlasPropertyKey propertyKey = mgmt.getPropertyKey(propertyName);
+ if (propertyKey == null) {
+ propertyKey = mgmt.makePropertyKey(propertyName, String.class, AtlasCardinality.SET);
+ mgmt.createExactMatchIndex(propertyName, false, Collections.singletonList(propertyKey));
+ }
+ }
+ mgmt.commit();
+ }
+ return (AtlasGraph<V, E>) atlasGraph;
+ }
+
+ @AfterClass
+ public void cleanup() {
+ if (atlasGraph != null) {
+ 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();
+ List<String> colorsToSet = new ArrayList<String>();
+ colorsToSet.add("red");
+ colorsToSet.add("blue");
+ colorsToSet.add("green");
+ vertex.setListProperty("colors", colorsToSet);
+ 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;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/GraphQueryTest.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/GraphQueryTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/GraphQueryTest.java
new file mode 100644
index 0000000..4797357
--- /dev/null
+++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/GraphQueryTest.java
@@ -0,0 +1,451 @@
+/**
+ * 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.janus;
+
+
+
+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 AtlasJanusGraphQuery.
+ */
+@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 {
+ AtlasJanusGraph graph = getAtlasJanusGraph();
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v1 = createVertex(graph);
+
+ v1.setProperty("name", "Fred");
+ v1.setProperty("size15", "15");
+ v1.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v2 = createVertex(graph);
+ v2.setProperty("name", "George");
+ v2.setProperty("size15", "16");
+ v2.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v3 = createVertex(graph);
+ v3.setProperty("name", "Jane");
+ v3.setProperty("size15", "17");
+ v3.setProperty("typeName", "Person");
+
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v4 = createVertex(graph);
+ v4.setProperty("name", "Bob");
+ v4.setProperty("size15", "18");
+ v4.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> 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 {
+ AtlasJanusGraph graph = getAtlasJanusGraph();
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v1 = createVertex(graph);
+
+ v1.setProperty("name", "Fred");
+ v1.setProperty("size15", "15");
+ v1.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v2 = createVertex(graph);
+ v2.setProperty("name", "George");
+ v2.setProperty("size15", "16");
+ v2.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v3 = createVertex(graph);
+ v3.setProperty("name", "Jane");
+ v3.setProperty("size15", "17");
+ v3.setProperty("typeName", "Person");
+
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v4 = createVertex(graph);
+ v4.setProperty("name", "Bob");
+ v4.setProperty("size15", "18");
+ v4.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> 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 {
+ AtlasJanusGraph graph = getAtlasJanusGraph();
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v1 = createVertex(graph);
+
+ v1.setProperty("name", "Fred");
+ v1.setProperty("size15", "15");
+ v1.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v2 = createVertex(graph);
+ v2.setProperty("name", "George");
+ v2.setProperty("size15", "16");
+ v2.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v3 = createVertex(graph);
+ v3.setProperty("name", "Jane");
+ v3.setProperty("size15", "17");
+ v3.setProperty("typeName", "Person");
+
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v4 = createVertex(graph);
+ v4.setProperty("name", "Bob");
+ v4.setProperty("size15", "18");
+ v4.setProperty("typeName", "Person");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> 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);
+ //make v3 no longer match the query. Within step should filter out the vertex since it no longer matches.
+ v3.setProperty("name", "Janet");
+ assertQueryMatches(q, v1);
+ }
+
+ @Test
+ public void testSimpleOrQuery() throws AtlasException {
+ AtlasJanusGraph graph = getAtlasJanusGraph();
+
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v1 = createVertex(graph);
+
+ v1.setProperty("name", "Fred");
+ v1.setProperty("size15", "15");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v2 = createVertex(graph);
+ v2.setProperty("name", "Fred");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v3 = createVertex(graph);
+ v3.setProperty("size15", "15");
+
+ graph.commit();
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> v4 = createVertex(graph);
+ v4.setProperty("name", "Fred");
+ v4.setProperty("size15", "15");
+
+ AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> 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<AtlasJanusVertex, AtlasJanusEdge>> temp = toList(expr.vertices());
+ //filter out vertices from previous test executions
+ Collection<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>> result =
+ Collections2.filter(temp, new Predicate<AtlasVertex<AtlasJanusVertex, AtlasJanusEdge>>() {
+
+ @Override
+ public boolean apply(AtlasVertex<AtlasJanusVertex, AtlasJanusEdge> input) {
+ return newVertices.contains(input);
+ }
+
+ });
+ String errorMessage = "Expected/found result sizes differ. Expected: "
+ + Arrays.asList(expectedResults).toString() +", found: " + result;
+ assertEquals(errorMessage, 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<AtlasJanusVertex, AtlasJanusEdge> getGraphQuery() {
+ return getAtlasJanusGraph().query();
+ }
+
+ private void pause() {
+ try {
+ Thread.sleep(5000);
+ } catch(InterruptedException e) {
+ //ignore
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/atlas/blob/503dddb8/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java
----------------------------------------------------------------------
diff --git a/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java
new file mode 100644
index 0000000..7c1dda7
--- /dev/null
+++ b/graphdb/janus/src/test/java/org/apache/atlas/repository/graphdb/janus/JanusGraphProviderTest.java
@@ -0,0 +1,80 @@
+/**
+ * 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.janus;
+
+import org.apache.atlas.ApplicationProperties;
+import org.apache.atlas.AtlasException;
+import org.apache.atlas.graph.GraphSandboxUtil;
+import org.apache.atlas.repository.graphdb.AtlasGraph;
+import org.apache.commons.configuration.Configuration;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+@Test
+public class JanusGraphProviderTest {
+
+ private Configuration configuration;
+ private AtlasGraph<?, ?> graph;
+
+ @BeforeTest
+ public void setUp() throws AtlasException {
+ GraphSandboxUtil.create();
+
+ //First get Instance
+ graph = new AtlasJanusGraph();
+ configuration = ApplicationProperties.getSubsetConfiguration(ApplicationProperties.get(),
+ AtlasJanusGraphDatabase.GRAPH_PREFIX);
+ }
+
+ @AfterClass
+ public void tearDown() throws Exception {
+ try {
+ graph.shutdown();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ try {
+ graph.clear();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testValidate() throws AtlasException {
+ try {
+ AtlasJanusGraphDatabase.validateIndexBackend(configuration);
+ } catch (Exception e) {
+ Assert.fail("Unexpected exception ", e);
+ }
+
+ //Change backend
+ configuration.setProperty(AtlasJanusGraphDatabase.INDEX_BACKEND_CONF, AtlasJanusGraphDatabase.INDEX_BACKEND_LUCENE);
+ try {
+ AtlasJanusGraphDatabase.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!");
+ }
+ }
+}