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!");
+        }
+    }
+}