<commit_before>////
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
////
[[graph]]
The Graph
=========

image::gremlin-standing.png[width=125]

Features
--------

A `Feature` implementation describes the capabilities of a `Graph` instance. This interface is implemented by graph
system providers for two purposes:

. It tells users the capabilities of their `Graph` instance.
. It allows the features they do comply with to be tested against the Gremlin Test Suite - tests that do not comply are "ignored").

The following example in the Gremlin Console shows how to print all the features of a `Graph`:

[gremlin-groovy]
----
graph = TinkerGraph.open()
graph.features()
----

A common pattern for using features is to check their support prior to performing an operation:

[gremlin-groovy]
----
graph.features().graph().supportsTransactions()
graph.features().graph().supportsTransactions() ? g.tx().commit() : "no tx"
----

TIP: To ensure provider agnostic code, always check feature support prior to usage of a particular function.  In that
way, the application can behave gracefully in case a particular implementation is provided at runtime that does not
support a function being accessed.

WARNING: Assignments of a `GraphStrategy` can alter the base features of a `Graph` in dynamic ways, such that checks
against a `Feature` may not always reflect the behavior exhibited when the `GraphStrategy` is in use.

[[vertex-properties]]
Vertex Properties
-----------------

image:vertex-properties.png[width=215,float=left] TinkerPop3 introduces the concept of a `VertexProperty<V>`. All the
properties of a `Vertex` are a `VertexProperty`. A `VertexProperty` implements `Property` and as such, it has a
key/value pair. However, `VertexProperty` also implements `Element` and thus, can have a collection of key/value
pairs. Moreover, while an `Edge` can only have one property of key "name" (for example), a `Vertex` can have multiple
"name" properties. With the inclusion of vertex properties, two features are introduced which ultimately advance the
graph modelers toolkit:

. Multiple properties (*multi-properties*): a vertex property key can have multiple values (i.e. a vertex can have
multiple "name" properties).
. Properties on properties (*meta-properties*): a vertex property can have properties (i.e. a vertex property can
have key/value data associated with it).

A collection of use cases are itemized below:

. *Permissions*: Vertex properties can have key/value ACL-type permission information associated with them.
. *Auditing*: When a vertex property is manipulated, it can have key/value information attached to it saying who the
creator, deletor, etc. are.
. *Provenance*: The "name" of a vertex can be declared by multiple users.

A running example using vertex properties is provided below to demonstrate and explain the API.

[gremlin-groovy]
----
graph = TinkerGraph.open()
g = graph.traversal(standard())
v = g.addV('name','marko','name','<NAME>').next()
g.V(v).properties().count()
g.V(v).properties('name').count() <1>
g.V(v).properties()
g.V(v).properties('name')
g.V(v).properties('name').hasValue('marko')
g.V(v).properties('name').hasValue('marko').property('acl','private') <2>
g.V(v).properties('name').hasValue('<NAME>')
g.V(v).properties('name').hasValue('marko a. rodriguez').property('acl','public')
g.V(v).properties('name').has('acl','public').value()
g.V(v).properties('name').has('acl','public').drop() <3>
g.V(v).properties('name').has('acl','public').value()
g.V(v).properties('name').has('acl','private').value()
g.V(v).properties()
g.V(v).properties().properties() <4>
g.V(v).properties().property('date',2014) <5>
g.V(v).properties().property('creator','stephen')
g.V(v).properties().properties()
g.V(v).properties('name').valueMap()
g.V(v).property('name','okram') <6>
g.V(v).properties('name')
g.V(v).values('name') <7>
----

<1> A vertex can have zero or more properties with the same key associated with it.
<2> A vertex property can have standard key/value properties attached to it.
<3> Vertex property removal is identical to property removal.
<4> It is property to get the properties of a vertex property.
<5> A vertex property can have any number of key/value properties attached to it.
<6> `property(...)` will remove all existing key'd properties before adding the new single property (see `VertexProperty.Cardinality`).
<7> If only the value of a property is needed, then `values()` can be used.

If the concept of vertex properties is difficult to grasp, then it may be best to think of vertex properties in terms
of "literal vertices." A vertex can have an edge to a "literal vertex" that has a single value key/value -- e.g.
"value=okram." The edge that points to that literal vertex has an edge-label of "name." The properties on the edge
represent the literal vertex's properties. The "literal vertex" can not have any other edges to it (only one from the
associated vertex).

[[the-crew-toy-graph]]
TIP: A toy graph demonstrating all of the new TinkerPop3 graph structure features is available at
`TinkerFactory.createTheCrew()` and `data/tinkerpop-crew*`. This graph demonstrates multi-properties and meta-properties.

.TinkerPop Crew
image::the-crew-graph.png[width=685]

[gremlin-groovy,theCrew]
----
g.V().as('a').
      properties('location').as('b').
      hasNot('endTime').as('c').
      select('a','b','c').by('name').by(value).by('startTime') // determine the current location of each person
g.V().has('name','gremlin').inE('uses').
      order().by('skill',incr).as('a').
      outV().as('b').
      select('a','b').by('skill').by('name') // rank the users of gremlin by their skill level
----

Graph Variables
---------------

TinkerPop3 introduces the concept of `Graph.Variables`. Variables are key/value pairs associated with the graph
itself -- in essence, a `Map<String,Object>`. These variables are intended to store metadata about the graph. Example
use cases include:

 * *Schema information*: What do the namespace prefixes resolve to and when was the schema last modified?
 * *Global permissions*: What are the access rights for particular groups?
 * *System user information*: Who are the admins of the system?

An example of graph variables in use is presented below:

[gremlin-groovy]
----
graph = TinkerGraph.open()
graph.variables()
graph.variables().set('systemAdmins',['stephen','peter','pavel'])
graph.variables().set('systemUsers',['matthias','marko','josh'])
graph.variables().keys()
graph.variables().get('systemUsers')
graph.variables().get('systemUsers').get()
graph.variables().remove('systemAdmins')
graph.variables().keys()
----

IMPORTANT: Graph variables are not intended to be subject to heavy, concurrent mutation nor to be used in complex
computations. The intention is to have a location to store data about the graph for administrative purposes.

[[transactions]]
Graph Transactions
------------------

image:gremlin-coins.png[width=100,float=right] A link:http://en.wikipedia.org/wiki/Database_transaction[database transaction]
represents a unit of work to execute against the database.  Transactions are controlled by an implementation of the
`Transaction` interface and that object can be obtained from the `Graph` interface using the `tx()` method.  It is
important to note that the `Transaction` object does not represent a "transaction" itself.  It merely exposes the
methods for working with transactions (e.g. committing, rolling back, etc).

Most `Graph` implementations that `supportsTransactions` will implement an "automatic" `ThreadLocal` transaction,
which means that when a read or write occurs after the `Graph` is instantiated a transaction is automatically
started within that thread.  There is no need to manually call a method to "create" or "start" a transaction.  Simply
modify the graph as required and call `graph.tx().commit()` to apply changes or `graph.tx().rollback()` to undo them.
When the next read or write action occurs against the graph, a new transaction will be started within that current
thread of execution.

When using transactions in this fashion, especially in web application (e.g. REST server), it is important to ensure
that transaction do not leak from one request to the next.  In other words, unless a client is somehow bound via
session to process every request on the same server thread, ever request must be committed or rolled back at the end
of the request.  By ensuring that the request encapsulates a transaction, it ensures that a future request processed
on a server thread is starting in a fresh transactional state and will not have access to the remains of one from an
earlier request. A good strategy is to rollback a transaction at the start of a request, so that if it so happens that
a transactional leak does occur between requests somehow, a fresh transaction is assured by the fresh request.

TIP: The `tx()` method is on the `Graph` interface, but it is also available on the `TraversalSource` spawned from a
`Graph`.  Calls to `TraversalSource.tx()` are proxied through to the underlying `Graph` as a convenience.

Configuring
~~~~~~~~~~~

Determining when a transaction starts is dependent upon the behavior assigned to the `Transaction`.  It is up to the
`Graph` implementation to determine the default behavior and unless the implementation doesn't allow it, the behavior
itself can be altered via these `Transaction` methods:

[source,java]
----
public Transaction onReadWrite(final Consumer<Transaction> consumer);

public Transaction onClose(final Consumer<Transaction> consumer);
----

Providing a `Consumer` function to `onReadWrite` allows definition of how a transaction starts when a read or a write
occurs. `Transaction.READ_WRITE_BEHAVIOR` contains pre-defined `Consumer` functions to supply to the `onReadWrite`
method.  It has two options:

* `AUTO` - automatic transactions where the transaction is started implicitly to the read or write operation
* `MANUAL` - manual transactions where it is up to the user to explicitly open a transaction, throwing an exception
if the transaction is not open

Providing a `Consumer` function to `onClose` allows configuration of how a transaction is handled when
`Transaction.close()` is called.  `Transaction.CLOSE_BEHAVIOR` has several pre-defined options that can be supplied to
this method:

* `COMMIT` - automatically commit an open transaction
* `ROLLBACK` - automatically rollback an open transaction
* `MANUAL` - throw an exception if a transaction is open, forcing the user to explicitly close the transaction

Once there is an understanding for how transactions are configured, most of the rest of the `Transaction` interface
is self-explanatory. Note that <<neo4j-gremlin,Neo4j-Gremlin>> is used for the examples to follow as TinkerGraph does
not support transactions.

[source,groovy]
----
gremlin> graph = Neo4jGraph.open('/tmp/neo4j')
==>neo4jgraph[EmbeddedGraphDatabase [/tmp/neo4j]]
gremlin> graph.features()
==>FEATURES
> GraphFeatures<commit_msg>Update reference docs to denote the ThreadLocal nature of the transaction settings.<commit_after>////
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to You under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License.  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
////
[[graph]]
The Graph
=========

image::gremlin-standing.png[width=125]

Features
--------

A `Feature` implementation describes the capabilities of a `Graph` instance. This interface is implemented by graph
system providers for two purposes:

. It tells users the capabilities of their `Graph` instance.
. It allows the features they do comply with to be tested against the Gremlin Test Suite - tests that do not comply are "ignored").

The following example in the Gremlin Console shows how to print all the features of a `Graph`:

[gremlin-groovy]
----
graph = TinkerGraph.open()
graph.features()
----

A common pattern for using features is to check their support prior to performing an operation:

[gremlin-groovy]
----
graph.features().graph().supportsTransactions()
graph.features().graph().supportsTransactions() ? g.tx().commit() : "no tx"
----

TIP: To ensure provider agnostic code, always check feature support prior to usage of a particular function.  In that
way, the application can behave gracefully in case a particular implementation is provided at runtime that does not
support a function being accessed.

WARNING: Assignments of a `GraphStrategy` can alter the base features of a `Graph` in dynamic ways, such that checks
against a `Feature` may not always reflect the behavior exhibited when the `GraphStrategy` is in use.

[[vertex-properties]]
Vertex Properties
-----------------

image:vertex-properties.png[width=215,float=left] TinkerPop3 introduces the concept of a `VertexProperty<V>`. All the
properties of a `Vertex` are a `VertexProperty`. A `VertexProperty` implements `Property` and as such, it has a
key/value pair. However, `VertexProperty` also implements `Element` and thus, can have a collection of key/value
pairs. Moreover, while an `Edge` can only have one property of key "name" (for example), a `Vertex` can have multiple
"name" properties. With the inclusion of vertex properties, two features are introduced which ultimately advance the
graph modelers toolkit:

. Multiple properties (*multi-properties*): a vertex property key can have multiple values (i.e. a vertex can have
multiple "name" properties).
. Properties on properties (*meta-properties*): a vertex property can have properties (i.e. a vertex property can
have key/value data associated with it).

A collection of use cases are itemized below:

. *Permissions*: Vertex properties can have key/value ACL-type permission information associated with them.
. *Auditing*: When a vertex property is manipulated, it can have key/value information attached to it saying who the
creator, deletor, etc. are.
. *Provenance*: The "name" of a vertex can be declared by multiple users.

A running example using vertex properties is provided below to demonstrate and explain the API.

[gremlin-groovy]
----
graph = TinkerGraph.open()
g = graph.traversal(standard())
v = g.addV('name','marko','name','<NAME>').next()
g.V(v).properties().count()
g.V(v).properties('name').count() <1>
g.V(v).properties()
g.V(v).properties('name')
g.V(v).properties('name').hasValue('marko')
g.V(v).properties('name').hasValue('marko').property('acl','private') <2>
g.V(v).properties('name').hasValue('<NAME>')
g.V(v).properties('name').hasValue('<NAME>').property('acl','public')
g.V(v).properties('name').has('acl','public').value()
g.V(v).properties('name').has('acl','public').drop() <3>
g.V(v).properties('name').has('acl','public').value()
g.V(v).properties('name').has('acl','private').value()
g.V(v).properties()
g.V(v).properties().properties() <4>
g.V(v).properties().property('date',2014) <5>
g.V(v).properties().property('creator','stephen')
g.V(v).properties().properties()
g.V(v).properties('name').valueMap()
g.V(v).property('name','okram') <6>
g.V(v).properties('name')
g.V(v).values('name') <7>
----

<1> A vertex can have zero or more properties with the same key associated with it.
<2> A vertex property can have standard key/value properties attached to it.
<3> Vertex property removal is identical to property removal.
<4> It is property to get the properties of a vertex property.
<5> A vertex property can have any number of key/value properties attached to it.
<6> `property(...)` will remove all existing key'd properties before adding the new single property (see `VertexProperty.Cardinality`).
<7> If only the value of a property is needed, then `values()` can be used.

If the concept of vertex properties is difficult to grasp, then it may be best to think of vertex properties in terms
of "literal vertices." A vertex can have an edge to a "literal vertex" that has a single value key/value -- e.g.
"value=okram." The edge that points to that literal vertex has an edge-label of "name." The properties on the edge
represent the literal vertex's properties. The "literal vertex" can not have any other edges to it (only one from the
associated vertex).

[[the-crew-toy-graph]]
TIP: A toy graph demonstrating all of the new TinkerPop3 graph structure features is available at
`TinkerFactory.createTheCrew()` and `data/tinkerpop-crew*`. This graph demonstrates multi-properties and meta-properties.

.TinkerPop Crew
image::the-crew-graph.png[width=685]

[gremlin-groovy,theCrew]
----
g.V().as('a').
      properties('location').as('b').
      hasNot('endTime').as('c').
      select('a','b','c').by('name').by(value).by('startTime') // determine the current location of each person
g.V().has('name','gremlin').inE('uses').
      order().by('skill',incr).as('a').
      outV().as('b').
      select('a','b').by('skill').by('name') // rank the users of gremlin by their skill level
----

Graph Variables
---------------

TinkerPop3 introduces the concept of `Graph.Variables`. Variables are key/value pairs associated with the graph
itself -- in essence, a `Map<String,Object>`. These variables are intended to store metadata about the graph. Example
use cases include:

 * *Schema information*: What do the namespace prefixes resolve to and when was the schema last modified?
 * *Global permissions*: What are the access rights for particular groups?
 * *System user information*: Who are the admins of the system?

An example of graph variables in use is presented below:

[gremlin-groovy]
----
graph = TinkerGraph.open()
graph.variables()
graph.variables().set('systemAdmins',['stephen','peter','pavel'])
graph.variables().set('systemUsers',['matthias','marko','josh'])
graph.variables().keys()
graph.variables().get('systemUsers')
graph.variables().get('systemUsers').get()
graph.variables().remove('systemAdmins')
graph.variables().keys()
----

IMPORTANT: Graph variables are not intended to be subject to heavy, concurrent mutation nor to be used in complex
computations. The intention is to have a location to store data about the graph for administrative purposes.

[[transactions]]
Graph Transactions
------------------

image:gremlin-coins.png[width=100,float=right] A link:http://en.wikipedia.org/wiki/Database_transaction[database transaction]
represents a unit of work to execute against the database.  Transactions are controlled by an implementation of the
`Transaction` interface and that object can be obtained from the `Graph` interface using the `tx()` method.  It is
important to note that the `Transaction` object does not represent a "transaction" itself.  It merely exposes the
methods for working with transactions (e.g. committing, rolling back, etc).

Most `Graph` implementations that `supportsTransactions` will implement an "automatic" `ThreadLocal` transaction,
which means that when a read or write occurs after the `Graph` is instantiated a transaction is automatically
started within that thread.  There is no need to manually call a method to "create" or "start" a transaction.  Simply
modify the graph as required and call `graph.tx().commit()` to apply changes or `graph.tx().rollback()` to undo them.
When the next read or write action occurs against the graph, a new transaction will be started within that current
thread of execution.

When using transactions in this fashion, especially in web application (e.g. REST server), it is important to ensure
that transaction do not leak from one request to the next.  In other words, unless a client is somehow bound via
session to process every request on the same server thread, ever request must be committed or rolled back at the end
of the request.  By ensuring that the request encapsulates a transaction, it ensures that a future request processed
on a server thread is starting in a fresh transactional state and will not have access to the remains of one from an
earlier request. A good strategy is to rollback a transaction at the start of a request, so that if it so happens that
a transactional leak does occur between requests somehow, a fresh transaction is assured by the fresh request.

TIP: The `tx()` method is on the `Graph` interface, but it is also available on the `TraversalSource` spawned from a
`Graph`.  Calls to `TraversalSource.tx()` are proxied through to the underlying `Graph` as a convenience.

Configuring
~~~~~~~~~~~

Determining when a transaction starts is dependent upon the behavior assigned to the `Transaction`.  It is up to the
`Graph` implementation to determine the default behavior and unless the implementation doesn't allow it, the behavior
itself can be altered via these `Transaction` methods:

[source,java]
----
public Transaction onReadWrite(final Consumer<Transaction> consumer);

public Transaction onClose(final Consumer<Transaction> consumer);
----

Providing a `Consumer` function to `onReadWrite` allows definition of how a transaction starts when a read or a write
occurs. `Transaction.READ_WRITE_BEHAVIOR` contains pre-defined `Consumer` functions to supply to the `onReadWrite`
method.  It has two options:

* `AUTO` - automatic transactions where the transaction is started implicitly to the read or write operation
* `MANUAL` - manual transactions where it is up to the user to explicitly open a transaction, throwing an exception
if the transaction is not open

Providing a `Consumer` function to `onClose` allows configuration of how a transaction is handled when
`Transaction.close()` is called.  `Transaction.CLOSE_BEHAVIOR` has several pre-defined options that can be supplied to
this method:

* `COMMIT` - automatically commit an open transaction
* `ROLLBACK` - automatically rollback an open transaction
* `MANUAL` - throw an exception if a transaction is open, forcing the user to explicitly close the transaction

IMPORTANT: As transactions are `ThreadLocal` in nature, so are the transaction configurations for `onReadWrite` and
`onClose`.

Once there is an understanding for how transactions are configured, most of the rest of the `Transaction` interface
is self-explanatory. Note that <<neo4j-gremlin,Neo4j-Gremlin>> is used for the examples to follow as TinkerGraph does
not support transactions.

[source,groovy]
----
gremlin> graph = Neo4jGraph.open('/tmp/neo4j')
==>neo4jgraph[EmbeddedGraphDatabase [/tmp/neo4j]]
gremlin> graph.features()
==>FEATURES
> GraphFeatures
{'fraction_non_alphanumeric': 0.10636764456503307, 'fraction_numerical': 0.0036459216550788535, 'mean_word_length': 4.847545860188399, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 58, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6930428', 'n_tokens_mistral': 6288, 'n_tokens_neox': 6095, 'n_words': 2918}