/*
 * 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.tinkerpop.gremlin.structure;

import org.apache.commons.configuration.Configuration;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource;
import org.apache.tinkerpop.gremlin.structure.io.GraphReader;
import org.apache.tinkerpop.gremlin.structure.io.GraphWriter;
import org.apache.tinkerpop.gremlin.structure.io.Io;
import org.apache.tinkerpop.gremlin.structure.io.IoRegistry;
import org.apache.tinkerpop.gremlin.structure.util.FeatureDescriptor;
import org.apache.tinkerpop.gremlin.structure.util.GraphFactory;
import org.apache.tinkerpop.gremlin.structure.util.Host;
import org.javatuples.Pair;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationTargetException;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * A {@link Graph} is a container object for a collection of {@link Vertex}, {@link Edge}, {@link VertexProperty},
 * and {@link Property} objects.
 *
 * @author Marko A. Rodriguez (http://markorodriguez.com)
 * @author Stephen Mallette (http://stephen.genoprime.com)
 * @author Pieter Martin
 */
public interface Graph extends AutoCloseable, Host {

    /**
     * Configuration key used by {@link GraphFactory}} to determine which graph to instantiate.
     */
    public static final String GRAPH = "gremlin.graph";

    /**
     * This should only be used by providers to create keys, labels, etc. in a namespace safe from users.
     * Users are not allowed to generate property keys, step labels, etc. that are key'd "hidden".
     */
    public static class Hidden {

        /**
         * The prefix to denote that a key is a hidden key.
         */
        private static final String HIDDEN_PREFIX = "~";
        private static final int HIDDEN_PREFIX_LENGTH = HIDDEN_PREFIX.length();

        /**
         * Turn the provided key into a hidden key. If the key is already a hidden key, return key.
         *
         * @param key The key to make a hidden key
         * @return The hidden key
         */
        public static String hide(final String key) {
            return isHidden(key) ? key : HIDDEN_PREFIX.concat(key);
        }

        /**
         * Turn the provided hidden key into an non-hidden key. If the key is not a hidden key, return key.
         *
         * @param key The hidden key
         * @return The non-hidden representation of the key
         */
        public static String unHide(final String key) {
            return isHidden(key) ? key.substring(HIDDEN_PREFIX_LENGTH) : key;
        }

        /**
         * Determines whether the provided key is a hidden key or not.
         *
         * @param key The key to check for hidden status
         * @return Whether the provided key is a hidden key or not
         */
        public static boolean isHidden(final String key) {
            return key.startsWith(HIDDEN_PREFIX);
        }
    }

    /**
     * Add a {@link Vertex} to the graph given an optional series of key/value pairs.  These key/values
     * must be provided in an even number where the odd numbered arguments are {@link String} property keys and the
     * even numbered arguments are the related property values.
     *
     * @param keyValues The key/value pairs to turn into vertex properties
     * @return The newly created vertex
     */
    public Vertex addVertex(final Object... keyValues);

    /**
     * Add a {@link Vertex} to the graph with provided vertex label.
     *
     * @param label the label of the vertex
     * @return The newly created labeled vertex
     */
    public default Vertex addVertex(final String label) {
        return this.addVertex(T.label, label);
    }

    /**
     * Declare the {@link GraphComputer} to use for OLAP operations on the graph.
     * If the graph does not support graph computer then an {@code UnsupportedOperationException} is thrown.
     *
     * @param graphComputerClass The graph computer class to use.
     * @return A graph computer for processing this graph
     * @throws IllegalArgumentException if the provided {@link GraphComputer} class is not supported.
     */
    public <C extends GraphComputer> C compute(final Class<C> graphComputerClass) throws IllegalArgumentException;

    /**
     * Generate a {@link GraphComputer} using the default engine of the underlying graph system.
     * This is a shorthand method for the more involved method that uses {@link Graph#compute(Class)}.
     *
     * @return A default graph computer
     * @throws IllegalArgumentException if there is no default graph computer
     */
    public GraphComputer compute() throws IllegalArgumentException;

    /**
     * Generate a {@link TraversalSource} using the specified {@code TraversalSource} class.
     * The reusable {@link TraversalSource} provides methods for spawning {@link Traversal} instances.
     *
     * @param traversalSourceClass The traversal source class
     * @param <C>                  The traversal source class
     */
    public default <C extends TraversalSource> C traversal(final Class<C> traversalSourceClass) {
        try {
            return traversalSourceClass.getConstructor(Graph.class).newInstance(this);
        } catch (final Exception e) {
            throw new IllegalStateException(e.getMessage(), e);
        }
    }

    /**
     * Generate a reusable {@link GraphTraversalSource} instance.
     * The {@link GraphTraversalSource} provides methods for creating {@link GraphTraversal} instances.
     *
     * @return A graph traversal source
     */
    public default GraphTraversalSource traversal() {
        return new GraphTraversalSource(this);
    }

    /**
     * Get the {@link Vertex} objects in this graph with the provided vertex ids or {@link Vertex} objects themselves.
     * If no ids are provided, get all vertices.  Note that a vertex identifier does not need to correspond to the
     * actual id used in the graph.  It needs to be a bit more flexible than that in that given the
     * {@link Graph.Features} around id support, multiple arguments might be applicable here.
     * <p/>
     * If the graph return {@code true} for {@link Features.VertexFeatures#supportsNumericIds()} then it should support
     * filters as with:
     * <ul>
     * <li>g.vertices(v)</li>
     * <li>g.vertices(v.id())</li>
     * <li>g.vertices(1)</li>
     * <li>g.vertices(1L)</li>
     * <li>g.vertices(1.0d)</li>
     * <li>g.vertices(1.0f)</li>
     * <li>g.vertices("1")</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.VertexFeatures#supportsCustomIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.vertices(v)</li>
     * <li>g.vertices(v.id())</li>
     * <li>g.vertices(v.id().toString())</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.VertexFeatures#supportsAnyIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.vertices(v)</li>
     * <li>g.vertices(v.id())</li>
     * </ul>
     * <p/>                                                                                                         
     * If the graph return {@code true} for {@link Features.VertexFeatures#supportsStringIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.vertices(v)</li>
     * <li>g.vertices(v.id().toString())</li>
     * <li>g.vertices("id")</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.EdgeFeatures#supportsStringIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.vertices(v)</li>
     * <li>g.vertices(v.id().toString())</li>
     * <li>g.vertices("id")</li>
     * </ul>
     *
     * @param vertexIds the ids of the vertices to get
     * @return an {@link Iterator} of vertices that match the provided vertex ids
     */
    public Iterator<Vertex> vertices(final Object... vertexIds);

    /**
     * Get the {@link Edge} objects in this graph with the provided edge ids or {@link Edge} objects. If no ids are
     * provided, get all edges. Note that an edge identifier does not need to correspond to the actual id used in the
     * graph.  It needs to be a bit more flexible than that in that given the {@link Graph.Features} around id support,
     * multiple arguments might be applicable here.
     * <p/>
     * If the graph return {@code true} for {@link Features.EdgeFeatures#supportsNumericIds()} then it should support
     * filters as with:
     * <ul>
     * <li>g.edges(e)</li>
     * <li>g.edges(e.id())</li>
     * <li>g.edges(1)</li>
     * <li>g.edges(1L)</li>
     * <li>g.edges(1.0d)</li>
     * <li>g.edges(1.0f)</li>
     * <li>g.edges("1")</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.EdgeFeatures#supportsCustomIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.edges(e)</li>
     * <li>g.edges(e.id())</li>
     * <li>g.edges(e.id().toString())</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.EdgeFeatures#supportsAnyIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.edges(e)</li>
     * <li>g.edges(e.id())</li>
     * </ul>
     * <p/>
     * If the graph return {@code true} for {@link Features.EdgeFeatures#supportsStringIds()} ()} then it should support
     * filters as with:
     * <ul>
     * <li>g.edges(e)</li>
     * <li>g.edges(e.id().toString())</li>
     * <li>g.edges("id")</li>
     * </ul>
     *
     * @param edgeIds the ids of the edges to get
     * @return an {@link Iterator} of edges that match the provided edge ids
     */
    public Iterator<Edge> edges(final Object... edgeIds);

    /**
     * Configure and control the transactions for those graphs that support this feature.  Note that this method does
     * not indicate the creation of a "transaction" object.  A {@link Transaction} in the TinkerPop context is a
     * transaction "factory" or "controller" that helps manage transactions owned by the underlying graph database.
     */
    public Transaction tx();

    /**
     * Closing a {@code Graph} is equivalent to "shutdown" and implies that no further operations can be executed on
     * the instance.  Users should consult the documentation of the underlying graph database implementation for what
     * this "shutdown" will mean in general and, if supported, how open transactions are handled.  It will typically
     * be the end user's responsibility to synchronize the thread that calls {@code close()} with other threads that
     * are accessing open transactions. In other words, be sure that all work performed on the {@code Graph} instance
     * is complete prior to calling this method.
     * <p/>
     * TinkerPop does not enforce any particular semantics with respect to "shutdown". It is up to the graph provider
     * to decide what this method will do.
     */
    @Override
    void close() throws Exception;

    /**
     * Construct a particular {@link Io} implementation for reading and writing the {@code Graph} and other data.
     * End-users will "select" the {@link Io} implementation that they want to use by supplying the
     * {@link Io.Builder} that constructs it.  In this way, {@code Graph} vendors can supply their {@link IoRegistry}
     * to that builder thus allowing for custom serializers to be auto-configured into the {@link Io} instance.
     * Registering custom serializers is particularly useful for those  graphs that have complex types for
     * {@link Element} identifiers.
     * </p>
     * For those graphs that do not need to register any custom serializers, the default implementation should suffice.
     * If the default is overridden, take care to register the current graph via the
     * {@link org.apache.tinkerpop.gremlin.structure.io.Io.Builder#graph(Graph)} method.
     *
     * @deprecated As of release 3.4.0, partially replaced by {@link GraphTraversalSource#io(String)}. Notice
     * {@link GraphTraversalSource#io(String)} doesn't support read operation from {@code java.io.InputStream}
     * or write operation to {@code java.io.OutputStream}. Thus for readers or writers which need this functionality
     * are safe to use this deprecated method. There is no intention to remove this method unless all the
     * functionality is replaced by the `io` step of {@link GraphTraversalSource}.
     */
    @Deprecated
    public default <I extends Io> I io(final Io.Builder<I> builder) {
        return (I) builder.graph(this).create();
    }

    /**
     * A collection of global {@link Variables} associated with the graph.
     * Variables are used for storing metadata about the graph.
     *
     * @return The variables associated with this graph
     */
    public Variables variables();

    /**
     * Get the {@code Configuration} associated with the construction of this graph.  Whatever configuration was
     * passed to {@link GraphFactory#open(Configuration)} is what should be returned by this method.
     *
     * @return the configuration used during graph construction.
     */
    public Configuration configuration();

    /**
     * Graph variables are a set of key/value pairs associated with the graph. The keys are String and the values
     * are Objects.
     */
    public interface Variables {

        /**
         * Keys set for the available variables.
         */
        public Set<String> keys();

        /**
         * Gets a variable.
         */
        public <R> Optional<R> get(final String key);

        /**
         * Sets a variable.
         */
        public void set(final String key, Object value);

        /**
         * Removes a variable.
         */
        public void remove(final String key);

        /**
         * Gets the variables of the {@link Graph} as a {@code Map}.
         */
        public default Map<String, Object> asMap() {
            final Map<String, Object> map = keys().stream()
                    .map(key -> Pair.with(key, get(key).get()))
                    .collect(Collectors.toMap(Pair::getValue0, Pair::getValue1));
            return Collections.unmodifiableMap(map);
        }

        public static class Exceptions {

            private Exceptions() {
            }

            public static IllegalArgumentException variableKeyCanNotBeEmpty() {
                return new IllegalArgumentException("Graph variable key can not be the empty string");
            }

            public static IllegalArgumentException variableKeyCanNotBeNull() {
                return new IllegalArgumentException("Graph variable key can not be null");
            }

            public static IllegalArgumentException variableValueCanNotBeNull() {
                return new IllegalArgumentException("Graph variable value can not be null");
            }

            public static UnsupportedOperationException dataTypeOfVariableValueNotSupported(final Object val) {
                return dataTypeOfVariableValueNotSupported(val, null);
            }

            public static UnsupportedOperationException dataTypeOfVariableValueNotSupported(final Object val, final Exception rootCause) {
                return new UnsupportedOperationException(String.format("Graph variable value [%s] is of type %s is not supported", val, val.getClass()), rootCause);
            }
        }

    }

    /**
     * Gets the {@link Features} exposed by the underlying {@code Graph} implementation.
     */
    public default Features features() {
        return new Features() {
        };
    }

    /**
     * An interface that represents the capabilities of a {@code Graph} implementation.  By default all methods
     * of features return {@code true} and it is up to implementers to disable feature they don't support.  Users
     * should check features prior to using various functions of TinkerPop to help ensure code portability
     * across implementations.  For example, a common usage would be to check if a graph supports transactions prior
     * to calling the commit method on {@link #tx()}.
     * <p/>
     * As an additional notice to Graph Providers, feature methods will be used by the test suite to determine which
     * tests will be ignored and which will be executed, therefore proper setting of these features is essential to
     * maximizing the amount of testing performed by the suite. Further note, that these methods may be called by the
     * TinkerPop core code to determine what operations may be appropriately executed which will have impact on
     * features utilized by users.
     */
    public interface Features {

        /**
         * Gets the features related to "graph" operation.
         */
        public default GraphFeatures graph() {
            return new GraphFeatures() {
            };
        }

        /**
         * Gets the features related to "vertex" operation.
         */
        public default VertexFeatures vertex() {
            return new VertexFeatures() {
            };
        }

        /**
         * Gets the features related to "edge" operation.
         */
        public default EdgeFeatures edge() {
            return new EdgeFeatures() {
            };
        }

        /**
         * Features specific to a operations of a "graph".
         */
        public interface GraphFeatures extends FeatureSet {
            public static final String FEATURE_COMPUTER = "Computer";
            public static final String FEATURE_TRANSACTIONS = "Transactions";
            public static final String FEATURE_PERSISTENCE = "Persistence";
            public static final String FEATURE_THREADED_TRANSACTIONS = "ThreadedTransactions";
            public static final String FEATURE_CONCURRENT_ACCESS = "ConcurrentAccess";
            public static final String FEATURE_IO_READ = "IoRead";
            public static final String FEATURE_IO_WRITE = "IoWrite";

            /**
             * Determines if the {@code Graph} implementation supports {@link GraphComputer} based processing.
             */
            @FeatureDescriptor(name = FEATURE_COMPUTER)
            public default boolean supportsComputer() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementation supports persisting it's contents natively to disk.
             * This feature does not refer to every graph's ability to write to disk via the Gremlin IO packages
             * (.e.g. GraphML), unless the graph natively persists to disk via those options somehow.  For example,
             * TinkerGraph does not support this feature as it is a pure in-sideEffects graph.
             */
            @FeatureDescriptor(name = FEATURE_PERSISTENCE)
            public default boolean supportsPersistence() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementation supports more than one connection to the same instance
             * at the same time.  For example, Neo4j embedded does not support this feature because concurrent
             * access to the same database files by multiple instances is not possible.  However, Neo4j HA could
             * support this feature as each new {@code Graph} instance coordinates with the Neo4j cluster allowing
             * multiple instances to operate on the same database.
             */
            @FeatureDescriptor(name = FEATURE_CONCURRENT_ACCESS)
            public default boolean supportsConcurrentAccess() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementations supports transactions.
             */
            @FeatureDescriptor(name = FEATURE_TRANSACTIONS)
            public default boolean supportsTransactions() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementation supports threaded transactions which allow a transaction
             * to be executed across multiple threads via {@link Transaction#createThreadedTx()}.
             */
            @FeatureDescriptor(name = FEATURE_THREADED_TRANSACTIONS)
            public default boolean supportsThreadedTransactions() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementations supports read operations as executed with the
             * {@link GraphTraversalSource#io(String)} step. Graph implementations will generally support this by
             * default as any graph that can support direct mutation through the Structure API will by default
             * accept data from the standard TinkerPop {@link GraphReader} implementations. However, some graphs like
             * {@code HadoopGraph} don't accept direct mutations but can still do reads from that {@code io()} step.
             */
            @FeatureDescriptor(name = FEATURE_IO_READ)
            public default boolean supportsIoRead() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementations supports write operations as executed with the
             * {@link GraphTraversalSource#io(String)} step. Graph implementations will generally support this by
             * default given the standard TinkerPop {@link GraphWriter} implementations. However, some graphs like
             * {@code HadoopGraph} will use a different approach to handle writes.
             */
            @FeatureDescriptor(name = FEATURE_IO_WRITE)
            public default boolean supportsIoWrite() {
                return true;
            }

            /**
             * Gets the features related to "graph sideEffects" operation.
             */
            public default VariableFeatures variables() {
                return new VariableFeatures() {
                };
            }
        }

        /**
         * Features that are related to {@link Vertex} operations.
         */
        public interface VertexFeatures extends ElementFeatures {
            public static final String FEATURE_ADD_VERTICES = "AddVertices";
            public static final String FEATURE_MULTI_PROPERTIES = "MultiProperties";
            public static final String FEATURE_DUPLICATE_MULTI_PROPERTIES = "DuplicateMultiProperties";
            public static final String FEATURE_META_PROPERTIES = "MetaProperties";
            public static final String FEATURE_REMOVE_VERTICES = "RemoveVertices";
            public static final String FEATURE_UPSERT = "Upsert";

            /**
             * Gets the {@link VertexProperty.Cardinality} for a key.  By default, this method will return
             * {@link VertexProperty.Cardinality#list}.  Implementations that employ a schema can consult it to
             * determine the {@link VertexProperty.Cardinality}.  Those that do no have a schema can return their
             * default {@link VertexProperty.Cardinality} for every key.
             * <p/>
             * Note that this method is primarily used by TinkerPop for internal usage and may not be suitable to
             * reliably determine the cardinality of a key. For some implementation it may offer little more than a
             * hint on the actual cardinality. Generally speaking it is likely best to drop down to the API of the
             * {@link Graph} implementation for any schema related queries.
             */
            public default VertexProperty.Cardinality getCardinality(final String key) {
                return VertexProperty.Cardinality.list;
            }

            /**
             * Determines if a {@link Vertex} can be added to the {@code Graph}.
             */
            @FeatureDescriptor(name = FEATURE_ADD_VERTICES)
            public default boolean supportsAddVertices() {
                return true;
            }

            /**
             * Determines if a {@link Vertex} can be removed from the {@code Graph}.
             */
            @FeatureDescriptor(name = FEATURE_REMOVE_VERTICES)
            public default boolean supportsRemoveVertices() {
                return true;
            }

            /**
             * Determines if a {@link Vertex} can support multiple properties with the same key.
             */
            @FeatureDescriptor(name = FEATURE_MULTI_PROPERTIES)
            public default boolean supportsMultiProperties() {
                return true;
            }

            /**
             * Determines if a {@link Vertex} can support non-unique values on the same key. For this value to be
             * {@code true}, then {@link #supportsMetaProperties()} must also return true. By default this method,
             * just returns what {@link #supportsMultiProperties()} returns.
             */
            @FeatureDescriptor(name = FEATURE_DUPLICATE_MULTI_PROPERTIES)
            public default boolean supportsDuplicateMultiProperties() {
                return supportsMultiProperties();
            }

            /**
             * Determines if a {@link Vertex} can support properties on vertex properties.  It is assumed that a
             * graph will support all the same data types for meta-properties that are supported for regular
             * properties.
             */
            @FeatureDescriptor(name = FEATURE_META_PROPERTIES)
            public default boolean supportsMetaProperties() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementation uses upsert functionality as opposed to insert
             * functionality for {@link #addVertex(String)}. This feature gives graph providers some flexibility as
             * to how graph mutations are treated. For graph providers, testing of this feature (as far as TinkerPop
             * is concerned) only covers graphs that can support user supplied identifiers as there is no other way
             * for TinkerPop to know what aspect of a vertex is unique to appropriately apply assertions. Graph
             * providers, especially those who support schema features, may have other methods for uniquely identifying
             * a vertex and should therefore resort to their own body of tests to validate this feature.
             */
            @FeatureDescriptor(name = FEATURE_UPSERT)
            public default boolean supportsUpsert() {
                return false;
            }

            /**
             * Gets features related to "properties" on a {@link Vertex}.
             */
            public default VertexPropertyFeatures properties() {
                return new VertexPropertyFeatures() {
                };
            }
        }

        /**
         * Features that are related to {@link Edge} operations.
         */
        public interface EdgeFeatures extends ElementFeatures {
            public static final String FEATURE_ADD_EDGES = "AddEdges";
            public static final String FEATURE_REMOVE_EDGES = "RemoveEdges";
            public static final String FEATURE_UPSERT = "Upsert";

            /**
             * Determines if an {@link Edge} can be added to a {@code Vertex}.
             */
            @FeatureDescriptor(name = FEATURE_ADD_EDGES)
            public default boolean supportsAddEdges() {
                return true;
            }

            /**
             * Determines if an {@link Edge} can be removed from a {@code Vertex}.
             */
            @FeatureDescriptor(name = FEATURE_REMOVE_EDGES)
            public default boolean supportsRemoveEdges() {
                return true;
            }

            /**
             * Determines if the {@code Graph} implementation uses upsert functionality as opposed to insert
             * functionality for {@link Vertex#addEdge(String, Vertex, Object...)}. This feature gives graph providers
             * some flexibility as to how graph mutations are treated. For graph providers, testing of this feature
             * (as far as TinkerPop is concerned) only covers graphs that can support user supplied identifiers as
             * there is no other way for TinkerPop to know what aspect of a edge is unique to appropriately apply
             * assertions. Graph providers, especially those who support schema features, may have other methods for
             * uniquely identifying a edge and should therefore resort to their own body of tests to validate this
             * feature.
             */
            @FeatureDescriptor(name = FEATURE_UPSERT)
            public default boolean supportsUpsert() {
                return false;
            }

            /**
             * Gets features related to "properties" on an {@link Edge}.
             */
            public default EdgePropertyFeatures properties() {
                return new EdgePropertyFeatures() {
                };
            }
        }

        /**
         * Features that are related to {@link Element} objects.  This is a base interface.
         */
        public interface ElementFeatures extends FeatureSet {
            public static final String FEATURE_USER_SUPPLIED_IDS = "UserSuppliedIds";
            public static final String FEATURE_NUMERIC_IDS = "NumericIds";
            public static final String FEATURE_STRING_IDS = "StringIds";
            public static final String FEATURE_UUID_IDS = "UuidIds";
            public static final String FEATURE_CUSTOM_IDS = "CustomIds";
            public static final String FEATURE_ANY_IDS = "AnyIds";
            public static final String FEATURE_ADD_PROPERTY = "AddProperty";
            public static final String FEATURE_REMOVE_PROPERTY = "RemoveProperty";

            /**
             * Determines if an {@link Element} allows properties to be added.  This feature is set independently from
             * supporting "data types" and refers to support of calls to {@link Element#property(String, Object)}.
             */
            @FeatureDescriptor(name = FEATURE_ADD_PROPERTY)
            public default boolean supportsAddProperty() {
                return true;
            }

            /**
             * Determines if an {@link Element} allows properties to be removed.
             */
            @FeatureDescriptor(name = FEATURE_REMOVE_PROPERTY)
            public default boolean supportsRemoveProperty() {
                return true;
            }

            /**
             * Determines if an {@link Element} can have a user defined identifier.  Implementations that do not support
             * this feature will be expected to auto-generate unique identifiers.  In other words, if the {@link Graph}
             * allows {@code graph.addVertex(id,x)} to work and thus set the identifier of the newly added
             * {@link Vertex} to the value of {@code x} then this feature should return true.  In this case, {@code x}
             * is assumed to be an identifier data type that the {@link Graph} will accept.
             */
            @FeatureDescriptor(name = FEATURE_USER_SUPPLIED_IDS)
            public default boolean supportsUserSuppliedIds() {
                return true;
            }

            /**
             * Determines if an {@link Element} has numeric identifiers as their internal representation. In other
             * words, if the value returned from {@link Element#id()} is a numeric value then this method
             * should be return {@code true}.
             * <p/>
             * Note that this feature is most generally used for determining the appropriate tests to execute in the
             * Gremlin Test Suite.
             */
            @FeatureDescriptor(name = FEATURE_NUMERIC_IDS)
            public default boolean supportsNumericIds() {
                return true;
            }

            /**
             * Determines if an {@link Element} has string identifiers as their internal representation. In other
             * words, if the value returned from {@link Element#id()} is a string value then this method
             * should be return {@code true}.
             * <p/>
             * Note that this feature is most generally used for determining the appropriate tests to execute in the
             * Gremlin Test Suite.
             */
            @FeatureDescriptor(name = FEATURE_STRING_IDS)
            public default boolean supportsStringIds() {
                return true;
            }

            /**
             * Determines if an {@link Element} has UUID identifiers as their internal representation. In other
             * words, if the value returned from {@link Element#id()} is a {@link UUID} value then this method
             * should be return {@code true}.
             * <p/>
             * Note that this feature is most generally used for determining the appropriate tests to execute in the
             * Gremlin Test Suite.
             */
            @FeatureDescriptor(name = FEATURE_UUID_IDS)
            public default boolean supportsUuidIds() {
                return true;
            }

            /**
             * Determines if an {@link Element} has a specific custom object as their internal representation.
             * In other words, if the value returned from {@link Element#id()} is a type defined by the graph
             * implementations, such as OrientDB's {@code Rid}, then this method should be return {@code true}.
             * <p/>
             * Note that this feature is most generally used for determining the appropriate tests to execute in the
             * Gremlin Test Suite.
             */
            @FeatureDescriptor(name = FEATURE_CUSTOM_IDS)
            public default boolean supportsCustomIds() {
                return true;
            }

            /**
             * Determines if an {@link Element} any Java object is a suitable identifier. TinkerGraph is a good
             * example of a {@link Graph} that can support this feature, as it can use any {@link Object} as
             * a value for the identifier.
             * <p/>
             * Note that this feature is most generally used for determining the appropriate tests to execute in the
             * Gremlin Test Suite. This setting should only return {@code true} if {@link #supportsUserSuppliedIds()}
             * is {@code true}.
             */
            @FeatureDescriptor(name = FEATURE_ANY_IDS)
            public default boolean supportsAnyIds() {
                return true;
            }

            /**
             * Determines if an identifier will be accepted by the {@link Graph}.  This check is different than
             * what identifier internally supports as defined in methods like {@link #supportsNumericIds()}.  Those
             * refer to internal representation of the identifier.  A {@link Graph} may accept an identifier that
             * is not of those types and internally transform it to a native representation.
             * <p/>
             * Note that this method only applies if {@link #supportsUserSuppliedIds()} is {@code true}. Those that
             * return {@code false} for that method can immediately return false for this one as it allows no ids
             * of any type (it generates them all).
             * <p/>
             * The default implementation will immediately return {@code false} if {@link #supportsUserSuppliedIds()}
             * is {@code false}.  If custom identifiers are supported then it will throw an exception.  Those that
             * return {@code true} for {@link #supportsCustomIds()} should override this method. If
             * {@link #supportsAnyIds()} is {@code true} then the identifier will immediately be allowed.  Finally,
             * if any of the other types are supported, they will be typed checked against the class of the supplied
             * identifier.
             */
            public default boolean willAllowId(final Object id) {
                if (!supportsUserSuppliedIds()) return false;
                if (supportsCustomIds())
                    throw new UnsupportedOperationException("The default implementation is not capable of validating custom ids - please override");

                return supportsAnyIds() || (supportsStringIds() && id instanceof String)
                        || (supportsNumericIds() && id instanceof Number) || (supportsUuidIds() && id instanceof UUID);
            }
        }

        /**
         * Features that are related to {@link Vertex} {@link Property} objects.
         */
        public interface VertexPropertyFeatures extends PropertyFeatures {
            public static final String FEATURE_REMOVE_PROPERTY = "RemoveProperty";
            public static final String FEATURE_USER_SUPPLIED_IDS = "UserSuppliedIds";
            public static final String FEATURE_NUMERIC_IDS = "NumericIds";
            public static final String FEATURE_STRING_IDS = "StringIds";
            public static final String FEATURE_UUID_IDS = "UuidIds";
            public static final String FEATURE_CUSTOM_IDS = "CustomIds";
            public static final String FEATURE_ANY_IDS = "AnyIds";

            /**
             * Determines if a {@link VertexProperty} allows properties to be removed.
             */
            @FeatureDescriptor(name = FEATURE_REMOVE_PROPERTY)
            public default boolean supportsRemoveProperty() {
                return true;
            }

            /**
             * Determines if a {@link VertexProperty} allows an identifier to be assigned to it.
             */
            @FeatureDescriptor(name = FEATURE_USER_SUPPLIED_IDS)
            public default boolean supportsUserSuppliedIds() {
                return true;
            }

            /**
             * Determines if an {@link VertexProperty} has numeric identifiers as their internal representation.
             */
            @FeatureDescriptor(name = FEATURE_NUMERIC_IDS)
            public default boolean supportsNumericIds() {
                return true;
            }

            /**
             * Determines if an {@link VertexProperty} has string identifiers as their internal representation.
             */
            @FeatureDescriptor(name = FEATURE_STRING_IDS)
            public default boolean supportsStringIds() {
                return true;
            }

            /**
             * Determines if an {@link VertexProperty} has UUID identifiers as their internal representation.
             */
            @FeatureDescriptor(name = FEATURE_UUID_IDS)
            public default boolean supportsUuidIds() {
                return true;
            }

            /**
             * Determines if an {@link VertexProperty} has a specific custom object as their internal representation.
             */
            @FeatureDescriptor(name = FEATURE_CUSTOM_IDS)
            public default boolean supportsCustomIds() {
                return true;
            }

            /**
             * Determines if an {@link VertexProperty} any Java object is a suitable identifier.  Note that this
             * setting can only return true if {@link #supportsUserSuppliedIds()} is true.
             */
            @FeatureDescriptor(name = FEATURE_ANY_IDS)
            public default boolean supportsAnyIds() {
                return true;
            }

            /**
             * Determines if an identifier will be accepted by the {@link Graph}.  This check is different than
             * what identifier internally supports as defined in methods like {@link #supportsNumericIds()}.  Those
             * refer to internal representation of the identifier.  A {@link Graph} may accept an identifier that
             * is not of those types and internally transform it to a native representation.
             * <p/>
             * Note that this method only applies if {@link #supportsUserSuppliedIds()} is {@code true}. Those that
             * return {@code false} for that method can immediately return false for this one as it allows no ids
             * of any type (it generates them all).
             * <p/>
             * The default implementation will immediately return {@code false} if {@link #supportsUserSuppliedIds()}
             * is {@code false}.  If custom identifiers are supported then it will throw an exception.  Those that
             * return {@code true} for {@link #supportsCustomIds()} should override this method. If
             * {@link #supportsAnyIds()} is {@code true} then the identifier will immediately be allowed.  Finally,
             * if any of the other types are supported, they will be typed checked against the class of the supplied
             * identifier.
             */
            public default boolean willAllowId(final Object id) {
                if (!supportsUserSuppliedIds()) return false;
                if (supportsCustomIds())
                    throw new UnsupportedOperationException("The default implementation is not capable of validating custom ids - please override");

                return supportsAnyIds() || (supportsStringIds() && id instanceof String)
                        || (supportsNumericIds() && id instanceof Number) || (supportsUuidIds() && id instanceof UUID);
            }
        }

        /**
         * Features that are related to {@link Edge} {@link Property} objects.
         */
        public interface EdgePropertyFeatures extends PropertyFeatures {
        }

        /**
         * A base interface for {@link Edge} or {@link Vertex} {@link Property} features.
         */
        public interface PropertyFeatures extends DataTypeFeatures {
            public static final String FEATURE_PROPERTIES = "Properties";

            /**
             * Determines if an {@link Element} allows for the processing of at least one data type defined by the
             * features.  In this case "processing" refers to at least "reading" the data type. If any of the
             * features on {@link PropertyFeatures} is true then this value must be true.
             */
            @FeatureDescriptor(name = FEATURE_PROPERTIES)
            public default boolean supportsProperties() {
                return supportsBooleanValues() || supportsByteValues() || supportsDoubleValues() || supportsFloatValues()
                        || supportsIntegerValues() || supportsLongValues() || supportsMapValues()
                        || supportsMixedListValues() || supportsSerializableValues()
                        || supportsStringValues() || supportsUniformListValues() || supportsBooleanArrayValues()
                        || supportsByteArrayValues() || supportsDoubleArrayValues() || supportsFloatArrayValues()
                        || supportsIntegerArrayValues() || supportsLongArrayValues() || supportsStringArrayValues();
            }
        }

        /**
         * Features for {@link Graph.Variables}.
         */
        public interface VariableFeatures extends DataTypeFeatures {
            public static final String FEATURE_VARIABLES = "Variables";

            /**
             * If any of the features on {@link VariableFeatures} is {@code true} then this value must be {@code true}.
             */
            @FeatureDescriptor(name = FEATURE_VARIABLES)
            public default boolean supportsVariables() {
                return supportsBooleanValues() || supportsByteValues() || supportsDoubleValues() || supportsFloatValues()
                        || supportsIntegerValues() || supportsLongValues() || supportsMapValues()
                        || supportsMixedListValues() || supportsSerializableValues()
                        || supportsStringValues() || supportsUniformListValues() || supportsBooleanArrayValues()
                        || supportsByteArrayValues() || supportsDoubleArrayValues() || supportsFloatArrayValues()
                        || supportsIntegerArrayValues() || supportsLongArrayValues() || supportsStringArrayValues();
            }
        }

        /**
         * Base interface for features that relate to supporting different data types.
         */
        public interface DataTypeFeatures extends FeatureSet {
            public static final String FEATURE_BOOLEAN_VALUES = "BooleanValues";
            public static final String FEATURE_BYTE_VALUES = "ByteValues";
            public static final String FEATURE_DOUBLE_VALUES = "DoubleValues";
            public static final String FEATURE_FLOAT_VALUES = "FloatValues";
            public static final String FEATURE_INTEGER_VALUES = "IntegerValues";
            public static final String FEATURE_LONG_VALUES = "LongValues";
            public static final String FEATURE_MAP_VALUES = "MapValues";
            public static final String FEATURE_MIXED_LIST_VALUES = "MixedListValues";
            public static final String FEATURE_BOOLEAN_ARRAY_VALUES = "BooleanArrayValues";
            public static final String FEATURE_BYTE_ARRAY_VALUES = "ByteArrayValues";
            public static final String FEATURE_DOUBLE_ARRAY_VALUES = "DoubleArrayValues";
            public static final String FEATURE_FLOAT_ARRAY_VALUES = "FloatArrayValues";
            public static final String FEATURE_INTEGER_ARRAY_VALUES = "IntegerArrayValues";
            public static final String FEATURE_LONG_ARRAY_VALUES = "LongArrayValues";
            public static final String FEATURE_SERIALIZABLE_VALUES = "SerializableValues";
            public static final String FEATURE_STRING_ARRAY_VALUES = "StringArrayValues";
            public static final String FEATURE_STRING_VALUES = "StringValues";
            public static final String FEATURE_UNIFORM_LIST_VALUES = "UniformListValues";

            /**
             * Supports setting of a boolean value.
             */
            @FeatureDescriptor(name = FEATURE_BOOLEAN_VALUES)
            public default boolean supportsBooleanValues() {
                return true;
            }

            /**
             * Supports setting of a byte value.
             */
            @FeatureDescriptor(name = FEATURE_BYTE_VALUES)
            public default boolean supportsByteValues() {
                return true;
            }

            /**
             * Supports setting of a double value.
             */
            @FeatureDescriptor(name = FEATURE_DOUBLE_VALUES)
            public default boolean supportsDoubleValues() {
                return true;
            }

            /**
             * Supports setting of a float value.
             */
            @FeatureDescriptor(name = FEATURE_FLOAT_VALUES)
            public default boolean supportsFloatValues() {
                return true;
            }

            /**
             * Supports setting of a integer value.
             */
            @FeatureDescriptor(name = FEATURE_INTEGER_VALUES)
            public default boolean supportsIntegerValues() {
                return true;
            }

            /**
             * Supports setting of a long value.
             */
            @FeatureDescriptor(name = FEATURE_LONG_VALUES)
            public default boolean supportsLongValues() {
                return true;
            }

            /**
             * Supports setting of a {@code Map} value.  The assumption is that the {@code Map} can contain
             * arbitrary serializable values that may or may not be defined as a feature itself.
             */
            @FeatureDescriptor(name = FEATURE_MAP_VALUES)
            public default boolean supportsMapValues() {
                return true;
            }

            /**
             * Supports setting of a {@code List} value.  The assumption is that the {@code List} can contain
             * arbitrary serializable values that may or may not be defined as a feature itself.  As this
             * {@code List} is "mixed" it does not need to contain objects of the same type.
             *
             * @see #supportsMixedListValues()
             */
            @FeatureDescriptor(name = FEATURE_MIXED_LIST_VALUES)
            public default boolean supportsMixedListValues() {
                return true;
            }

            /**
             * Supports setting of an array of boolean values.
             */
            @FeatureDescriptor(name = FEATURE_BOOLEAN_ARRAY_VALUES)
            public default boolean supportsBooleanArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of byte values.
             */
            @FeatureDescriptor(name = FEATURE_BYTE_ARRAY_VALUES)
            public default boolean supportsByteArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of double values.
             */
            @FeatureDescriptor(name = FEATURE_DOUBLE_ARRAY_VALUES)
            public default boolean supportsDoubleArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of float values.
             */
            @FeatureDescriptor(name = FEATURE_FLOAT_ARRAY_VALUES)
            public default boolean supportsFloatArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of integer values.
             */
            @FeatureDescriptor(name = FEATURE_INTEGER_ARRAY_VALUES)
            public default boolean supportsIntegerArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of string values.
             */
            @FeatureDescriptor(name = FEATURE_STRING_ARRAY_VALUES)
            public default boolean supportsStringArrayValues() {
                return true;
            }

            /**
             * Supports setting of an array of long values.
             */
            @FeatureDescriptor(name = FEATURE_LONG_ARRAY_VALUES)
            public default boolean supportsLongArrayValues() {
                return true;
            }

            /**
             * Supports setting of a Java serializable value.
             */
            @FeatureDescriptor(name = FEATURE_SERIALIZABLE_VALUES)
            public default boolean supportsSerializableValues() {
                return true;
            }

            /**
             * Supports setting of a string value.
             */
            @FeatureDescriptor(name = FEATURE_STRING_VALUES)
            public default boolean supportsStringValues() {
                return true;
            }

            /**
             * Supports setting of a {@code List} value.  The assumption is that the {@code List} can contain
             * arbitrary serializable values that may or may not be defined as a feature itself.  As this
             * {@code List} is "uniform" it must contain objects of the same type.
             *
             * @see #supportsMixedListValues()
             */
            @FeatureDescriptor(name = FEATURE_UNIFORM_LIST_VALUES)
            public default boolean supportsUniformListValues() {
                return true;
            }
        }

        /**
         * A marker interface to identify any set of Features. There is no need to implement this interface.
         */
        public interface FeatureSet {
        }

        /**
         * Implementers should not override this method. Note that this method utilizes reflection to check for
         * feature support.
         */
        default boolean supports(final Class<? extends FeatureSet> featureClass, final String feature)
                throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
            final Object instance;
            if (featureClass.equals(GraphFeatures.class))
                instance = this.graph();
            else if (featureClass.equals(VariableFeatures.class))
                instance = this.graph().variables();
            else if (featureClass.equals(VertexFeatures.class))
                instance = this.vertex();
            else if (featureClass.equals(VertexPropertyFeatures.class))
                instance = this.vertex().properties();
            else if (featureClass.equals(EdgeFeatures.class))
                instance = this.edge();
            else if (featureClass.equals(EdgePropertyFeatures.class))
                instance = this.edge().properties();
            else if (featureClass.equals(PropertyFeatures.class))
                throw new IllegalArgumentException(String.format(
                        "Do not reference PropertyFeatures directly in tests, utilize a specific instance: %s, %s",
                        EdgePropertyFeatures.class, VertexPropertyFeatures.class));
            else
                throw new IllegalArgumentException(String.format(
                        "Expecting featureClass to be a valid Feature instance and not %s", featureClass));

            return (Boolean) featureClass.getMethod("supports" + feature).invoke(instance);
        }
    }

    /**
     * Common exceptions to use with a graph.
     */
    public static class Exceptions {

        private static final boolean debug = Boolean.parseBoolean(java.lang.System.getenv().getOrDefault("gremlin.structure.debug", "false"));

        public static UnsupportedOperationException variablesNotSupported() {
            return new UnsupportedOperationException("Graph does not support graph variables");
        }

        public static UnsupportedOperationException transactionsNotSupported() {
            return new UnsupportedOperationException("Graph does not support transactions");
        }

        public static UnsupportedOperationException graphComputerNotSupported() {
            return new UnsupportedOperationException("Graph does not support graph computer");
        }

        public static IllegalArgumentException graphDoesNotSupportProvidedGraphComputer(final Class graphComputerClass) {
            return new IllegalArgumentException("Graph does not support the provided graph computer: " + graphComputerClass.getSimpleName());
        }

        public static UnsupportedOperationException vertexAdditionsNotSupported() {
            return new UnsupportedOperationException("Graph does not support adding vertices");
        }

        public static IllegalArgumentException vertexWithIdAlreadyExists(final Object id) {
            return new IllegalArgumentException(String.format("Vertex with id already exists: %s", id));
        }

        public static IllegalArgumentException edgeWithIdAlreadyExists(final Object id) {
            return new IllegalArgumentException(String.format("Edge with id already exists: %s", id));
        }

        public static IllegalArgumentException idArgsMustBeEitherIdOrElement() {
            return new IllegalArgumentException("id arguments must be either ids or Elements");
        }

        public static IllegalArgumentException argumentCanNotBeNull(final String argument) {
            return new IllegalArgumentException(String.format("The provided argument can not be null: %s", argument));
        }
    }

    /**
     * Defines the test suite that the implementer has decided to support and represents publicly as "passing".
     * Marking the {@link Graph} instance with this class allows that particular test suite to run.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Repeatable(OptIns.class)
    @Inherited
    public @interface OptIn {
        public static String SUITE_STRUCTURE_STANDARD = "org.apache.tinkerpop.gremlin.structure.StructureStandardSuite";
        public static String SUITE_STRUCTURE_INTEGRATE = "org.apache.tinkerpop.gremlin.structure.StructureIntegrateSuite";
        public static String SUITE_PROCESS_COMPUTER = "org.apache.tinkerpop.gremlin.process.ProcessComputerSuite";
        public static String SUITE_PROCESS_STANDARD = "org.apache.tinkerpop.gremlin.process.ProcessStandardSuite";

        /**
         * The test suite class to opt in to.
         */
        public String value();
    }

    /**
     * Holds a collection of {@link OptIn} enabling multiple {@link OptIn} to be applied to a
     * single suite.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Inherited
    public @interface OptIns {
        OptIn[] value();
    }

    /**
     * Defines a test in the suite that the implementer does not want to run.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Repeatable(OptOuts.class)
    @Inherited
    public @interface OptOut {
        /**
         * The test class to opt out of. This may be set to a base class of a test as in the case of the Gremlin
         * process class of tests from which Gremlin flavors extend.  If the actual test class is an inner class
         * of then use a "$" as a separator between the outer class and inner class.
         */
        public String test();

        /**
         * The specific name of the test method to opt out of or asterisk to opt out of all methods in a
         * {@link #test}.
         */
        public String method();

        /**
         * The reason the implementation is opting out of this test.
         */
        public String reason();

        /**
         * For parameterized tests specify the name of the test itself without its "square brackets".
         */
        public String specific() default "";

        /**
         * The list of {@link GraphComputer} implementations by class name that a test should opt-out from using (i.e. other
         * graph computers not in this list will execute the test).  This setting should only be included when
         * the test is one that uses the {@code TraversalEngine.COMPUTER} - it will otherwise be ignored.  By
         * default, an empty array is assigned and it is thus assumed that all computers are excluded when an
         * {@code OptOut} annotation is used, therefore this value must be overridden to be more specific.
         */
        public String[] computers() default {};

    }

    /**
     * Holds a collection of {@link OptOut} enabling multiple {@link OptOut} to be applied to a
     * single suite.
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    @Inherited
    public @interface OptOuts {
        OptOut[] value();
    }
}
