Unverified Commit 1844642a authored by Jeffrey Phillips Freeman's avatar Jeffrey Phillips Freeman 💥
Browse files

docs: broke out the Ferma features into its own page.

parent 969cc397
......@@ -24,127 +24,21 @@ benchmark program and run it for yourself!
## Feature Breakdown
Despite the superior performance of Ferma it also supports all the features provided by the alternatives out there, not
to mention several novel features. The following gives a quick breakdown of the features of the various frameworks. We
also include a bit later in the document some Ferma examples showing the various features in action. All of the examples
below use the domain model [found here](Ferma:Domain_Example).
| | **Ferma** | **Frames** | **Totorom** | **Peapod** |
|------------------------------------------------------------------------------------------------------------------|---------------|---------------|---------------|---------------|
| **[JPA-like Annotations](creating_annotated_domain_models)** | Supported | Supported | Not Supported | Supported |
| **[Type information encoded into graph](#type-information-encoded-into-graph)** | Supported | Supported | Supported | Supported |
| **[Framing of elements instantiated according to type hierarchy](#framing-instantiated-by-type-hierarchy)** | Supported | Supported | Supported | Supported |
| **[Element queried by type hierarchy](#element-queried-by-type-hierarchy)** | Supported | Not Supported | Not Supported | Partial \* |
| **[Turning off type resolution on a per call basis](#turning-off-type-resolution-per-call)** | Supported | Not Supported | Not Supported | Not Supported |
| **[Changing the encoded graph type already stored in the database](#changing-type-encoded-in-the-graph)** | Supported | Not Supported | Not Supported | Not Supported |
| **[Customizing the way type information is stored in the graph](#customizing-how-types-are-encoded)** | Supported | Not Supported | Not Supported | Not Supported |
| **Tinkerpop 2 support** | Supported | Supported | Supported | Not Supported |
| **Tinkerpop 3 support** | Not Supported | Not Supported | Not Supported | Supported |
Ferma also supports all the features provided by the alternatives out there, not to mention several novel features. The
following gives a quick breakdown of the features of the various frameworks. We also link to some Ferma examples showing
the various features in action.
| Feature | **Ferma** | **Frames** | **Totorom** | **Peapod** |
|-----------------------------------------------------------------------------------------------------------------------------|---------------|---------------|---------------|---------------|
| **[JPA-like Annotations](features.md#jpa-like-annotations)** | Supported | Supported | Not Supported | Supported |
| **[Type information encoded into graph](features.md#type-information-encoded-into-graph)** | Supported | Supported | Supported | Supported |
| **[Framing of elements instantiated according to type hierarchy](features.md#framing-instantiated-by-type-hierarchy)** | Supported | Supported | Supported | Supported |
| **[Element queried by type hierarchy](features.md#element-queried-by-type-hierarchy)** | Supported | Not Supported | Not Supported | Partial \* |
| **[Turning off type resolution on a per call basis](features.md#turning-off-type-resolution-per-call)** | Supported | Not Supported | Not Supported | Not Supported |
| **[Changing the encoded graph type already stored in the database](features.md#changing-type-encoded-in-the-graph)** | Supported | Not Supported | Not Supported | Not Supported |
| **[Customizing the way type information is stored in the graph](features.md#customizing-how-types-are-encoded)** | Supported | Not Supported | Not Supported | Not Supported |
| **Tinkerpop 2 support** | Supported | Supported | Supported | Not Supported |
| **Tinkerpop 3 support** | Supported | Not Supported | Not Supported | Supported |
\* While Peapod does support querying for all instances of a type, and its subtypes, it does not support a mechanism to
query for a specific type while excluding subtypes.
### Type information encoded into graph
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
Graph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Person.class);
Person person = fg.v().next(Program.class);
String personClassName = Person.class.getName();
String encodedClassName = person.getProperty(PolymorphicTypeResolver.TYPE_RESOLUTION_KEY)
assert(personClassName.equals(encodedClassName));
```
### Framing instantiated by type hierarchy
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//make sure the newly added node is actually a programmer
Person programmer = fg.v().next(Person.class);
assert(programmer instanceof Programmer);
```
### Element queried by type hierarchy
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
fg.addFramedVertex(Person.class);
//counts how many people (or subclasses thereof) in the graph.
assert(fg.v().has(Person.class).count() == 2);
//counts how many programmers are in the graph
assert(fg.v().has(Programmer.class).count() == 1);
```
### Turning off type resolution per call
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//With type resolution is active it should be a programmer
assert(fg.v().next(Person.class) instanceof Programmer);
//With type resolution bypassed it is no longer a programmer
assert(!(fg.v().nextExplicit(Person.class) instanceof Programmer));
```
### Changing type encoded in the graph
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//make sure the newly added node is actually a programmer
Person programmer = fg.v().next(Person.class);
assert(programmer instanceof Programmer);
//change the type resolution to person
programmer.setTypeResolution(Person.class);
//make sure the newly added node is actually a programmer
Person person = fg.v().next(Person.class);
assert(person instanceof Person);
assert(!(person instanceof Programmer));
```
### Customizing how types are encoded
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
final ReflectionCache cache = new ReflectionCache(types);
FrameFactory factory = new AnnotationFrameFactory(cache);
TypeResolver resolver = new PolymorphicTypeResolver(cache, "customTypeKey");
Graph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, factory, resolver);
fg.addFramedVertex(Person.class);
Person person = fg.v().next(Program.class);
String personClassName = Person.class.getName();
String encodedClassName = person.getProperty("customTypeKey")
assert(personClassName.equals(encodedClassName));
```
The following gives a quick breakdown of some of the features of the Ferma framework along with examples.
* [JPA-like Annotations](#jpa-like-annotations)
* [Type information encoded into graph](#type-information-encoded-into-graph)
* [Framing of elements instantiated according to type hierarchy](#framing-instantiated-by-type-hierarchy)
* [Element queried by type hierarchy](#element-queried-by-type-hierarchy)
* [Turning off type resolution on a per call basis](#turning-off-type-resolution-per-call)
* [Changing the encoded graph type already stored in the database](#changing-type-encoded-in-the-graph)
* [Customizing the way type information is stored in the graph](#customizing-how-types-are-encoded)
* Tinkerpop 2 support
* Tinkerpop 3 support
## JPA-like Annotations
```Java
public abstract class Person extends AbstractVertexFrame {
@Property("name")
public abstract String getName();
@Property("name")
public abstract void setName(String name);
@Adjacency(label = "knows")
public abstract List<Person> getKnowsPeople();
}
public abstract class Programmer extends Person {
}
public void testAnnotatedTyping() {
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
Person.class,
Programmer.class,
Knows.class}));
Graph graph = TinkerGraph.open();
//implies annotated mode
FramedGraph fg = new DelegatingFramedGraph(graph, true, types);
Person jeff = fg.addFramedVertex(Programmer.class);
jeff.setName("Jeff");
Person julia = fg.addFramedVertex(Person.class);
julia.setName("Julia");
julia.addKnows(jeff);
Person juliaAgain = fg.traverse((g) -> g.V().has("name", "Julia")).next(Person.class);
Person jeffAgain = juliaAgain.getKnowsPeople().get(0);
assert jeffAgain instanceof Programmer;
assert jeffAgain.getName().equals("Jeff");
}
```
## Type information encoded into graph
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
Graph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Person.class);
Person person = fg.traverse(g -> g.V()).next(Program.class);
String personClassName = Person.class.getName();
String encodedClassName = person.getProperty(PolymorphicTypeResolver.TYPE_RESOLUTION_KEY)
assert personClassName.equals(encodedClassName);
```
## Framing instantiated by type hierarchy
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//make sure the newly added node is actually a programmer
Person programmer = fg.traverse(g -> g.V()).next(Person.class);
assert programmer instanceof Programmer;
```
## Element queried by type hierarchy
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
fg.addFramedVertex(Person.class);
//counts how many people (or subclasses thereof) in the graph.
assert fg.traverse(g -> g.getTypeResolver().hasType(g.V(), Person.class)).toList(Person.class).size() == 2;
//counts how many programmers are in the graph
assert fg.traverse(g -> g.getTypeResolver().hasType(g.V(), Programmer.class)).toList(Person.class).size() == 1;
```
## Turning off type resolution per call
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//With type resolution is active it should be a programmer
assert fg.traverse(g -> g.V()).next(Person.class) instanceof Programmer;
//With type resolution bypassed it is no longer a programmer
assert !(fg.traverse(g -> g.V()).nextExplicit(Person.class) instanceof Programmer);
```
## Changing type encoded in the graph
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class,
Programmer.class}));
TinkerGraph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, types);
fg.addFramedVertex(Programmer.class);
//make sure the newly added node is actually a programmer
Person programmer = fg.traverse(g -> g.V()).next(Person.class);
assert programmer instanceof Programmer;
//change the type resolution to person
programmer.setTypeResolution(Person.class);
//make sure the newly added node is actually a programmer
Person person = fg.traverse(g -> g.V()).next(Person.class);
assert !(person instanceof Programmer);
```
## Customizing how types are encoded
```java
Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{Person.class}));
final ReflectionCache cache = new ReflectionCache(types);
FrameFactory factory = new AnnotationFrameFactory(cache);
TypeResolver resolver = new PolymorphicTypeResolver(cache, "customTypeKey");
Graph g = new TinkerGraph();
FramedGraph fg = new DelegatingFramedGraph(g, factory, resolver);
fg.addFramedVertex(Person.class);
Person person = fg.traverse(g -> g.V()).next(Programmer.class);
String personClassName = Person.class.getName();
String encodedClassName = person.getProperty("customTypeKey")
assert personClassName.equals(encodedClassName);
```
......@@ -11,6 +11,7 @@ site_url: 'http://syncleus.com/Ferma'
pages:
- Home: index.md
- Getting Started: getting_started.md
- Features: features.md
- Object Mapping: object_mapping.md
- Core Annotations:
- Overview: annotations/overview.md
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment