getting_started.md 5.96 KB
Newer Older
1
2
3
4
5
Ferma provides three levels of type resolution: untyped, simple, and annotated. In untyped mode Ferma doesn't handle
typing at all, instead the type must be explicitly indicated whenever querying. In simple mode Ferma provides type
context encoded as graph element properties which ensures the same type comes out that goes in to a graph. In annotated
mode all the features of simple mode are provided as well as enabling the use of annotations on abstract methods to
instruct Ferma to dynamically construct byte code to implement the abstract methods at start up.
6
7
8
9
10
11
12
13
14

## Dependency

To include Ferma in your project of choice include the following Maven dependency into your build.

```xml
<dependency>
    <groupId>com.syncleus.ferma</groupId>
    <artifactId>ferma</artifactId>
15
    <version>3.3.1</version>
16
17
18
19
20
</dependency>
```

## Untyped Mode Example

21
22
In untyped mode there is no automatic typing. Whatever class is explicitly indicated is the type that will be
instantiated when performing queries. Lets start with a simple example domain.
23
24

```java
25
public class Person extends AbstractVertexFrame {
26
27
28
29
30
31
32
33
34
35
36
37
38
  public String getName() {
    return getProperty("name");
  }

  public void setName(String name) {
    setProperty("name", name);
  }

  public List<? extends Knows> getKnowsList() {
    return traverse((v) -> v.outE("knows")).toList(Knows.class);
  }

  public Knows addKnows(Person friend) {
39
    return addFramedEdge("knows", friend, Knows.class);
40
41
42
  }
}

43
public class Knows extends AbstractEdgeFrame {
44
45
46
47
48
49
50
51
52
53
54
55
56
57
  public void setYears(int years) {
    setProperty("years", years);
  }

  public int getYears() {
    return getProperty("years");
  }
}
```

And here is how you interact with the framed elements:

```java
public void testUntyped() {
58
  Graph graph = TinkerGraph.open();
59
60

  // implies untyped mode
61
  FramedGraph fg = new DelegatingFramedGraph(graph);
62
63
64
65
66
67
68
69
70

  Person p1 = fg.addFramedVertex(Person.class);
  p1.setName("Jeff");

  Person p2 = fg.addFramedVertex(Person.class);
  p2.setName("Julia");
  Knows knows = p1.addKnows(p2);
  knows.setYears(15);

71
  Person jeff = fg.traverse((g) -> g.V().has("name", "Jeff")).next(Person.class);
72
73
74
75
76
77
78
79


  Assert.assertEquals("Jeff", jeff.getName());
}
```

## Simple Mode Example

80
81
82
83
In simple mode you must provide concrete classes, no abstract or interfaces allowed, and the class should always extend
from a FramedVertex or FramedEdge. Simple mode doesn't provide any annotations either. The purpose of simple mode is to
provide type resolution. Basically the type of object you use when adding to the graph is the same type you get out when
reading from the graph.
84
85
86
87
88
89
90

Say we extend the Person class with the Programmer class.

```java
public class Programmer extends Person {
}
```
91

92
Using simple mode will save the type of Java class the element was created with for use later:
93

94
95
```java
public void testSimpleTyping() {
96
  Graph graph = TinkerGraph.open();
97
98

  // implies simple mode
99
100
  FramedGraph fg = new DelegatingFramedGraph(graph, true, false);

101
102
  Person p1 = fg.addFramedVertex(Programmer.class);
  p1.setName("Jeff");
103

104
105
  Person p2 = fg.addFramedVertex(Person.class);
  p2.setName("Julia");
106

107
108
  Person jeff = fg.traverse((g) -> g.V().has("name", "Jeff")).next(Person.class);
  Person julia = fg.traverse((g) -> g.V().has("name", "Julia")).next(Person.class);
109

110
111
112
113
114
115
116
  Assert.assertEquals(Programmer.class, jeff.getClass());
  Assert.assertEquals(Person.class, julia.getClass());
}
```

## Annotated Mode Example

117
118
119
120
121
In annotated mode you can either provide concrete classes, abstract classes, or even interfaces. Abstract classes and
concrete classes must extend from FramedVertex or FramedEdge, however, interfaces do not have this restriction.
Annotated mode also provides a set of annotations which must be used to define any abstract methods that are to be
implemented by the engine. Annotated mode provides the same type resolution as provided by simple mode with a bit more
power to determine parent-child relationships at run time.
122
123
124
125

The same example as above done with annotations would look something like this.

```java
126
public abstract class Person extends AbstractVertexFrame {
127
128
129
130
131
132
  @Property("name")
  public abstract String getName();

  @Property("name")
  public abstract void setName(String name);

133
134
  @Adjacency(label = "knows")
  public abstract List<Person> getKnowsPeople();
135

136
137
  @Incidence(label = "knows")
  public abstract List<Knows> getKnows();
138

139
  @Incidence(label = "knows")
140
141
  public abstract Knows addKnows(Person friend);

142
143
  public List<? extends Person> getFriendsNamedBill() {
      return this.traverse(input -> input.out("knows").has("name", "bill")).toList(Person.class);
144
145
146
  }
}

147
public abstract class Knows extends AbstractEdgeFrame {
148
149
150
151
152
153
154
155
156
157
  @Property("years")
  public abstract void setYears(int years);

  @Property("years")
  public abstract int getYears();

  @InVertex
  public abstract Person getIn();

  @OutVertex
158
  public abstract Person getOut();
159
160
161
162
163
164
}

public abstract class Programmer extends Person {
}
```

165
166
167
If we pass a collection of Class objects to the FramedGraph constructor then the annotated type resolver will be used.
In this mode you want to tell the engine what classes you will be using so it can handle type resolution properly and
construct the byte code for any abstract annotated methods.
168
169
170
171

```java
public void testAnnotatedTyping() {
  Set<Class<?>> types = new HashSet<Class<?>>(Arrays.asList(new Class<?>[]{
172
173
174
175
                Person.class,
                Programmer.class,
                Knows.class}));
  Graph graph = TinkerGraph.open();
176
177

  //implies annotated mode
178
  FramedGraph fg = new DelegatingFramedGraph(graph, true, types);
179

180
181
  Person jeff = fg.addFramedVertex(Programmer.class);
  jeff.setName("Jeff");
182

183
184
185
  Person julia = fg.addFramedVertex(Person.class);
  julia.setName("Julia");
  julia.addKnows(jeff);
186

187
188
  Person juliaAgain = fg.traverse((g) -> g.V().has("name", "Julia")).next(Person.class);
  Person jeffAgain = juliaAgain.getKnowsPeople().get(0);
189

190
191
  Assert.assertTrue(Programmer.class.isAssignableFrom(jeffAgain.getClass()));
  Assert.assertTrue(Person.class.isAssignableFrom(juliaAgain.getClass()));
192
193
}
```