Giter Club home page Giter Club logo

ferma's Introduction

Build status Coverage Dependencies Codacy Javadocs Maven Central Gitter

An ORM / OGM for the Apache TinkerPop™ graph stack.

Licensed under the Apache Software License v2

The Ferma project was originally created as an alternative to the TinkerPop2 Frames project. Which at the time lacked features needed by the community, and its performance was cripplingly slow. Today Ferma is a robust framework that takes on a role similar to an Object-relational Model (ORM) library for traditional databases. Ferma is often referred to as a Object-graph Model (OGM) library, and maps Java objects to elements in a graph such as a Vertex or an Edge. In short it allows a schema to be defined using java interfaces and classes which provides a level of abstraction for interacting with the underlying graph.

Ferma 3.x Supports TinkerPop3. For TinkerPop2 support use Ferma version 2.x.

Annotated classes in Ferma have their abstract methods implemented using code generation during start-up with Byte Buddy, avoiding the need for proxy classes. This in turn significantly improves performance when compared with TinkerPop Frames and other frameworks. Ferma offers many features including several annotation types to reduce the need for boilerplate code as well as handling Java typing transparently. This ensures whatever the type of the object is when you persist it to the graph the same Java type will be used when instantiating a class off of the graph.

Ferma is designed to easily replace TinkerPop Frames in existing code, as such, the annotations provided by Ferma are a super-set of those originally provided by TinkerPop Frames.

Ferma is built directly on top of TinkerPop and allows access to all of the internals. This ensures all the TinkerPop features are available to the end-user. The TinkerPop stack provides several tools which can be used to work with the Ferma engine.

  • Gremlin, a database agnostic query language for Graph Databases.
  • Gremlin Server, a server that provides an interface for executing Gremlin on remote machines.
  • a data-flow framework for splitting, merging, filtering, and transforming of data
  • Graph Computer, a framework for running algorithms against a Graph Database.
  • Support for both OLTP and OLAP engines.
  • TinkerGraph a Graph Database and the reference implementation for TinkerPop.
  • Native Gephi integration for visualizing graphs.
  • Interfaces for most major Graph Compute Engines including Hadoop M/R. Spark, and Giraph.

Ferma also supports any of the many databases compatible with TinkerPop including the following.

The official Ferma source repository is hosted on QOTO GitLab with an up-to-date mirror maintained at Github.

For documentation refer to our project page as well as the latest Javadocs.

For support please use Gitter or the official Ferma mailing list and Discourse forum.

Please file bugs and feature requests on the QOTO GitLab.

Dependency

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

<dependency>
    <groupId>com.syncleus.ferma</groupId>
    <artifactId>ferma</artifactId>
    <version>3.3.2</version>
</dependency>

Getting Started

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.

Untyped Mode Example

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.

public class Person extends AbstractVertexFrame {
  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) {
    return addFramedEdge("knows", friend, Knows.class);
  }
}

public class Knows extends AbstractEdgeFrame {
  public void setYears(int years) {
    setProperty("years", years);
  }

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

And here is how you interact with the framed elements:

public void testUntyped() {
  Graph graph = TinkerGraph.open();

  // implies untyped mode
  FramedGraph fg = new DelegatingFramedGraph(graph);

  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);

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


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

Simple Mode Example

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.

Say we extend the Person class with the Programmer class.

public class Programmer extends Person {
}

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

public void testSimpleTyping() {
  Graph graph = TinkerGraph.open();

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

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

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

  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);

  Assert.assertEquals(Programmer.class, jeff.getClass());
  Assert.assertEquals(Person.class, julia.getClass());
}

Annotated Mode Example

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 runtime.

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

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();

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

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

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

public abstract class Knows extends AbstractEdgeFrame {
  @Property("years")
  public abstract void setYears(int years);

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

  @InVertex
  public abstract Person getIn();

  @OutVertex
  public abstract Person getOut();
}

public abstract class Programmer extends Person {
}

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.

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.assertTrue(Programmer.class.isAssignableFrom(jeffAgain.getClass()));
  Assert.assertTrue(Person.class.isAssignableFrom(juliaAgain.getClass()));
}

Obtaining the Source

The official source repository for Ferma is located in the Syncleus Github repository and can be cloned using the following command.

git clone https://git.qoto.org/Ferma/Ferma.git

Building

Documentation

Install dependencies

pip install mkdocs mkdocs-material pymdown-extensions

Build documentation

mkdocs build

Deploy to Github

mkdocs gh-deploy

ferma's People

Contributors

alvanson avatar bryncooke avatar freemo avatar grv87 avatar joshsh avatar jotschi avatar jsight avatar mohataher avatar patrick-beuks avatar porunov avatar tjad avatar trojek avatar veskoo93 avatar wsalembi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ferma's Issues

kind.newInstance() deprecated since Java 9

I notice in com.syncleus.ferma.framefactories.DefaultFrameFactory, it calls kind.newInstance() which is deprecated since Java 9.

Also, the message "Could not instantiate kind: " + kind.getName() wasn't that helpful in establishing that the framework is looking for a default no-args constructor.

Sort/Order By?

I'm just trying to use Ferma now (together with OrientDB), and I'm trying to find a way to sort through a result. I think there's a way using the .traverse() method, but the documentation doesn't seem to have almost any examples or information for such a thing.

How can I do that?

Allow @GraphElement to take a value

Would it be possible to extend the GraphElement annotation to take in a String value (default "") that can be used to define a label of the Element/Edge/Vertex being created. If blank the simple class name could be used as a fallback.

Strange behavior of class casting.

Hello guys.
I have found some unexpected behaviour of using framed graph.
Let's assume we have 2 classes A and B. Each of them have the same property name.
In the graph are two objects: object A with name = a, and object B with name = b.
But if I am trying to traverse over graph to grab object with name = b and get object of kind A using method next... I am getting object A.
Here is code:

package ferma;

import com.syncleus.ferma.AbstractVertexFrame;
import com.syncleus.ferma.DelegatingFramedGraph;
import com.syncleus.ferma.FramedGraph;
import com.syncleus.ferma.annotations.Property;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
import org.junit.Assert;
import org.junit.Test;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

public class RowTest {

    public static abstract class Person extends AbstractVertexFrame {

        @Property("name")
        public abstract String getName();

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

    }

    public static abstract class Animal extends AbstractVertexFrame {

        @Property("name")
        public abstract String getName();

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

        @Property("kind")
        public abstract String getKind();

        @Property("kind")
        public abstract void setKind(String kind);

    }


    @Test
    public void name() {
        Set<Class<? extends AbstractVertexFrame>> types = new HashSet<>(Arrays.asList(
            Person.class,
            Animal.class
        ));

        Graph graph = TinkerGraph.open();
        FramedGraph fg = new DelegatingFramedGraph<>(graph, true, types);

        Person person = fg.addFramedVertex(Person.class);
        String jeff = "Jeff";
        person.setName(jeff);

        Animal animal = fg.addFramedVertex(Animal.class);
        animal.setKind("dog");
        String lessi = "lessi";
        animal.setName(lessi);

        Person personLessi = fg.traverse(input -> input.V().has("name", lessi)).next(Person.class);

        Assert.assertEquals(personLessi.getName(), lessi);

        System.out.println(personLessi.getClass());
        System.out.println(personLessi);

    }
}

// Result:
//    class ferma.RowTest$Person$ByteBuddy$0BUlWIhG
//    {
//    "id": 3,
//    "elementClass": "vertex",
//    "ferma_type": "ferma.RowTest$Animal",
//    "kind": "dog",
//    "name": "lessi"
//    }

Is it expected behavior? I did not found any information about this in the documentation.

I am using ferma version 3.2.1

Feature request: Adding label to a vertex

I am using Ferma with JanusGraph. JanusGraph allows to set a label to a vertex. It would be awesome if Ferma could assign labels to vertices. Right now Ferma always assigns vertex label to all vertices.

OrientDB 2.1.x Transaction/Concurrency Compatibility

OrientDB's transaction handling requires some workarounds to be applied in order to be used in combination with Ferma.

  • OrientGraph instances are not threadsafe.
  • A new transaction has to be created for each thread.
  • OrientDB Elements (eg.: OrientVertex) are not threafsafe. Thus the element has to be reloaded when switching threads of passing a ferma element from one thread to another.

I created my own vertex frame which internally deals with some of those requirements:

public class OrientVertexFrame extends AbstractVertexFrame {

    private Object id;
        // ThreadLocal which will hold the base element reference for each thread and 
       // reload the element if required.
    public ThreadLocal<Element> threadLocalElement = ThreadLocal.withInitial(() -> ((WrappedVertex)getGraph().getVertex(id)).getBaseElement());

        // ThreadLocal which will hold the current active graph (eg.: Transaction)
    public static ThreadLocal<FramedGraph> threadLocalGraph = new ThreadLocal<>();

    @Override
    protected void init(FramedGraph graph, Element element) {
        super.init(graph, element);
        this.id = element.getId();
    }

    @Override
    public Vertex getElement() {
        Element vertex = threadLocalElement.get();

        // Unwrap wrapped vertices
        if (vertex instanceof WrappedElement) {
            vertex = (Vertex) ((WrappedElement) vertex).getBaseElement();
        }
        return (Vertex)vertex;
    }

    @Override
    public FramedGraph getGraph() {
        return new DelegatingFramedGraph<>(threadLocalGraph.get(), true, false);
    }
}

Transactions should set the thread local and restore it within the duration of the transaction. I created an autoclosable which handles those transactions and updates to the threadlocal.

Client driver version on ferma 3

The error "The Client driver version is different than Server version: client=37, server=36. You could not use the full features of the newer version. Assure to have the same versions on both" comes up.

Can i use the client of version=36 in ferma 3?

Update checklist in CONTRIBUTING.md

The checklist currently used in the CONTRIBUTING.md file was pulled over from another project. While it is mostly accurate it should be updated to be specific to Ferma.

Specifically this section could be improved upon:

* Make sure any references to the version number in the readme is updated
  * Version number in dependency maven snippet.
  * Add new version to javadoc version list.

Any plans to integrate with Spring Data and support Datastax DSE Graph?

I am curious if it would be possible to have a Spring Data integration of all the Gremlin graph databases - something like: https://github.com/gjrwebber/spring-data-gremlin but using Tinkerpop 3+. I was expecting a less verbose annotation style without the need to create new classes (framed vertices/edges) like it is done with neo4j ogm: https://github.com/neo4j/neo4j-ogm. It would be nice if spring-data-gremlin is merged in spring projects like neo4j one: https://github.com/spring-projects/spring-data-neo4j

I am also curious if Datastax DSE Graph could be supported out of the box from Ferma.

Thanks!

Not persisting to JanusGraph

I am trying to use ferma ORM for my project . Current problem is, I am not able to persist my entities to JanusGraph DB.
Here is my code Required :
Entity Class




public abstract class Person extends AbstractVertexFrame {
    private String id;
    private String name;
    private int age;
    private String mobile;

    @Property("age")
    public abstract int getAge();

    @Property("age")
    public abstract void setAge(int age) ;

    @Property("mobile")
    public abstract String getMobile();

    @Property("mobile")
    public abstract void setMobile(String mobile) ;

    public String getId() {
        return id;
    }

    @Property("name")
    public abstract String getName() ;

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

    public String toString(){
        return this.name+" has Id"+this.getId();
    }
}

This is how I create/initialize my DelegatedFramedGraph bean:

@Bean
    FramedGraph framedGraph(JanusGraph graph,GremlinBeanPostProcessor gremlinBeanPostProcessor){
        return new DelegatingFramedGraph(graph,true,gremlinBeanPostProcessor.getEntityClasses());
    }

JanusGraph is initialized :

@Bean
    JanusGraph graph(JanusGremlinGraphFactory janusGremlinGraphFactory){
        JanusGraph janusGraph = null;
        janusGraph = janusGremlinGraphFactory.openGraph();
        return janusGraph;
    }

    @Bean
    JanusGremlinGraphFactory janusGremlinGraphFactory(){
        JanusGremlinGraphFactory jggf;
        jggf = new JanusGremlinGraphFactory();
        jggf.setConfiguration(getConfiguration());
        return jggf;
    }

When I try to persist it:

 @Autowired
    private FramedGraph framedGraph;

public String savePerson(String name,int age,String mobile){
        Person person =  framedGraph.addFramedVertex(Person.class);
        person.setName(name);
        person.setAge(age);
        person.setMobile(mobile);
        System.out.println(person.getName()+"and person id is"+person.getId());
        return person.toString();
    }

Nothing is stored to JanusGraph, not sure where is the problem.

Can somebody help me ?

Ability to add keyValues on Edge and Vertex Creation

I've got a bug with fields which are mandatory for classes.

I'm trying to create an Edge on an existing vertex using

        edgeHasCalculs= COP_Vertex.addEdgeToExistingVStoreLocation(storeVertex, calculs.INITIALIZER_EHasCalculs);
        edgeHasCalculs.setTypeCalcul(classOf[VCOP].getSimpleName);
        edgeHasCalculs.setTimespan(timespan);
        edgeHasCalculs.setEnd_Date(endDate.toDate());

It fails at the first line, because of :
"The field 'EHasCalculs.Timespan' is mandatory, but not found on record: EHasCalculs{out:#-1:-2,in:#21:2}"

I would need to be able to specify the keyValues on creation of the baseEdge so that when it goes in the delegatingFrameGraph, the classInitializer or an other way be able to specify keyValues in this function.

public <T> T addFramedEdge(final VertexFrame source, final VertexFrame destination, final String label, final ClassInitializer<T> initializer, final Object... keyValues) {

        final Edge baseEdge = source.getElement().addEdge(label, destination.getElement(), keyValues);
        final T framedEdge = frameNewElement(baseEdge, initializer);
        return framedEdge;

    }

I'm using the annotation methods:

@Incidence(label = "EHasCalculs", direction = Direction.OUT)
	public abstract <E extends AbstractEdgeFrame> E addEdgeToExistingVStoreLocation(VStoreLocation son, ClassInitializer<? extends E> edgeInitializer);

Thanks

project status

Hi guys, what is the status of this project? Is this something that is still living? thanks

  • Good job BTW -

Ability to add labels on Vertex

Labels are a integral part of tinkerpop graphs, with the option to add vertexes with g.addV(label).

With this issue I am asking on input on ways to make it a more integral part in this project. In the text below I go over why it is that I would like to see it added. The current way of doing it and some possible solutions to implement it.

Labels are used to distinguish between vertexes. While it is not needed for Ferma as you can use the class structure to distinguish between vertexes, it would be nice to have a easy way to set them so that programs that rely on the graph output can use these.

Currently you have to do it with framedGraph.addFramedVertex(new DefaultClassInitializer<>(className), T.label, labelName); and the recetlly added (#56) framedGraph.addFramedVertex(className, T.label, labelName);

I have made an attempt to have a better way to add these with annotations on the vertex class as labels are generally used to distinguish between types of nodes. This one is visible in a pull request on my own repo. But I am not yet convinced that this is the way to go. (this implementation is just a proof of concept and still needs a bit of work. Like checking if no label is given as argument when adding the vertex)

Some other ways that i have thought of was to add the function framedGraph.addV(className, labelName); To more closely mirror the Tinkerpop implementation.

The last options would be a breaking change that would split the current @GraphElement into two separate annotations, one being @GraphVertex and the other @GraphEdge, where GraphVertex has a optional label.

I would love to hear thoughts on this subject as I have to use labels in a project that I am currently working on. I therefore also have some time to spare to implement this into this library.

Change Vertex Label

Is there a way to change the vertex label "vertex" to an own String? I looked into the API but all I found was how to change the label for an edge.

Update Ferma to use Tinkerpop v3

We need to start preparing Ferma to use Tinkerpop v3 as the backend. If we can get someone to update the code in a new branch to be fully compatible with the Tinkerpop v3 release, and all the unit tests passing we should be golden!

[BOUNTY $50] Create a Ferma-examples project

Create a Ferma-examples project including various usage examples. There should be a collection of very simple hello-world example projects showing off all of Ferma's features. There should also be an example project for each major graph DB and how Ferma can work with it. Ideally these should run in-memory through maven but when this isnt possible perhaps throw in some vagrant images as well.

How to handle detached elements with Ferma?

TinkerPop supports re-attaching DetachedElement back to graph. It's possible to achieve something similar using ferma ?
We using ferma in rest api so user can get some graph elements, modify them and send back so we need to update our graph element. Currently do doing it manually but possibility to re-attaching elements to graph can be very useful.

Adding a custom Annotation

In order to register a custom Annotation, it is necessary to create an annotation method handler and add it to the AnnotationFrameFactory's methodHandlers map.
The issue is that AnnotationFrameFactory's methodHandlers is private, hence it is not accessible.
Changing it to "protected" it allows to extend AnnotationFrameFactory and add the custom annotation handler right inside the constructor.

Dependency reflections 0.9.12 doesn't add scanners on empty urls

In reflections version 0.9.12 there is a bug which may indirectly be a problem when Ferma is used with JanusGraph.
Here in JanusGraph we retrieve PreInitializeConfigOptions even if there is no scanUrls.
https://github.com/JanusGraph/janusgraph/blob/677a57aa985a7ea47af70d0eaba30171d765c79d/janusgraph-core/src/main/java/org/janusgraph/core/util/ReflectiveConfigOptionLoader.java#L248

This works fine till reflections version 0.9.12 which introduces the next bug: ronmamo/reflections#273

The thing is that the method getTypesAnnotatedWith should return empty collection but instead it breaks existing contract and returns a wrong exception.

I think, it would be good to downgrade reflections to 0.9.11 till the bug isn't fixed. After that, it would be better to avoid 0.9.12 version and upgrade directly to the version where it is fixed (i.e. 0.9.13 or later).

Required argument type in AbstractVertexFrame.traverse() does not allow for anonymous traversals

In the Node.java reproduced below, using Ferma 3.0.2 and tinkergraph-gremlin 3.2.3 on OpenJDK 8u121-b13, attempting to use Node.traverse() with an anonymous traversal (__.out("parent")) results in the following compile-time error (change the call to traverse1() back to traverse() first):

Node.java:[56,46] error: incompatible types: no instance(s) of type variable(s) A exist so that GraphTraversal<A,Vertex> conforms to Traversal<?,CAP#1>

Changing the argument type of traverse() from Function<GraphTraversal<? extends Vertex, ? extends Vertex>, GraphTraversal<?, ?>> to Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>> seems to correct the issue. Following the types through the current TinkerPop API, input.V(getElement().id()) returns type GraphTraversal<Vertex, Vertex> so I believe it is sufficient to require traverser to have type Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>>.

I imagine a similar issue exists with AbstractEdgeFrame.

Node.java:

package com.syncleus.ferma.issues;

import com.syncleus.ferma.AbstractVertexFrame;
import com.syncleus.ferma.DelegatingFramedGraph;
import com.syncleus.ferma.FramedGraph;
import com.syncleus.ferma.Traversable;
import com.syncleus.ferma.annotations.Adjacency;
import com.syncleus.ferma.annotations.Property;
import javax.annotation.Nullable;
import java.util.function.Function;
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.process.traversal.dsl.graph.__;
import org.apache.tinkerpop.gremlin.structure.Direction;
import org.apache.tinkerpop.gremlin.structure.Graph;
import org.apache.tinkerpop.gremlin.structure.Vertex;
import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;

public abstract class Node extends AbstractVertexFrame {

    public static void main(String[] args) {
        // create new graph
        Graph graph = TinkerGraph.open();
        FramedGraph fg = new DelegatingFramedGraph(graph, true, true);
        // add five nodes (vertices)
        Node[] nodes = new Node[5];
        for (int i = 0; i < nodes.length; i++) {
            nodes[i] = fg.addFramedVertex(Node.class);
            nodes[i].setName("Node" + i);
        }
        // Node0 <- Node1 <- ... <- Node4
        for (int i = 1; i < nodes.length; i++) {
            nodes[i].setParent(nodes[i - 1]);
        }
        // ask Node3 for its grandparent (Node1)
        System.out.println(nodes[3].getGrandParent());
    }

    @Property("name")
    public abstract String getName();

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

    @Adjacency(label = "parent", direction = Direction.OUT)
    public abstract Node getParent();

    public void setParent(Node parent) {
        // node can only have one parent
        setLinkOut(parent, "parent");
    }

    public Node getGrandParent() {
        // with traverse(): Node.java:[55,46] error: incompatible types: no instance(s) of type variable(s) A exist so that GraphTraversal<A,Vertex> conforms to Traversal<?,CAP#1>
        return traverse1((v) -> v.repeat(__.out("parent")).times(2)).next(Node.class);
    }

    public <T extends Traversable<?, ?>> T traverse1(final Function<GraphTraversal<Vertex, Vertex>, GraphTraversal<?, ?>> traverser) {
        return this.getGraph().traverse(new Function<GraphTraversalSource, GraphTraversal<?, ?>>() {
            @Nullable
            @Override
            public GraphTraversal<?, ?> apply(@Nullable final GraphTraversalSource input) {
                return traverser.apply(input.V(getElement().id()));
            }
        });
    }

}

ClassCastException: Employee$ByteBuddy$Yxytgyif cannot be cast to com.syncleus.ferma.AbstractElementFrame

A basic vertex creation in Ferma 3.0.2 generates a ClassCastException:

java.lang.ClassCastException: com.syncleus.ferma.annotations.FermaTest$Employee$ByteBuddy$Yxytgyif cannot be cast to com.syncleus.ferma.AbstractElementFrame

	at com.syncleus.ferma.DelegatingFramedGraph.frameElement(DelegatingFramedGraph.java:243)
	at com.syncleus.ferma.DelegatingFramedGraph.frameNewElement(DelegatingFramedGraph.java:249)
	at com.syncleus.ferma.DelegatingFramedGraph.addFramedVertex(DelegatingFramedGraph.java:313)
	at com.syncleus.ferma.DelegatingFramedGraph.addFramedVertex(DelegatingFramedGraph.java:319)
	at com.syncleus.ferma.annotations.FermaTest.testCreation(FermaTest.java:54)

This is the test class. The cause is not the inner class because it doesn't work as seperate class either.

public class FermaTest {

    public static abstract class Employee implements VertexFrame {
        @Property("name")
        public abstract String getName();

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

    }

    @Test
    public void testCreation() {
        Set<Class<?>> types = new HashSet<>(Arrays.asList(new Class<?>[]{Employee.class}));
        Graph g = TinkerGraph.open();

        //implies annotated mode
        FramedGraph fg = new DelegatingFramedGraph(g, true, types);

        Employee e1 = fg.addFramedVertex(Employee.class);
        e1.setName("Jeff");
    }
}

AWS Neptune Support?

[HELP WANTED]

Amazon's graph db "Neptune" is now available. I'm looking to use Ferma as an OGM for an upcoming project. Amazon says Neptune supports Property Graphs by way of Apache TinkerPop. Does that mean by proxy Ferma will work with Neptune? I don't see it listed as an officially support graph db. If not what would it take to add support for it?

addFramedEdge is not setting type resolution key property

Used method:

  <T> T addFramedEdge(final VertexFrame source, final VertexFrame destination, final String label, Class<T> kind);

Version: 2.1.0-SNAPSHOT

I will take a look at this when i find the time and add a testcase that reproduces this problem.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.