package com.dooapp.gaedo.blueprints;
import com.dooapp.gaedo.blueprints.transformers.LiteralTransformer;
import com.dooapp.gaedo.blueprints.transformers.Literals;
import com.dooapp.gaedo.finders.repository.ServiceRepository;
import com.dooapp.gaedo.properties.Property;
import com.tinkerpop.blueprints.pgm.CloseableSequence;
import com.tinkerpop.blueprints.pgm.Index;
import com.tinkerpop.blueprints.pgm.IndexableGraph;
import com.tinkerpop.blueprints.pgm.Vertex;
public class GraphUtils {
/**
* Helper function locating first matching vertex with the given property value
* @param graph
* @param property
* @param object
* @return
*/
public static Vertex locateVertex(IndexableGraph graph, String property, Object value) {
CloseableSequence<Vertex> matching = graph.getIndex(Index.VERTICES, Vertex.class).get(property, value);
if(matching.hasNext()) {
return matching.next();
} else {
return null;
}
}
/**
* Get vertex for which the given declared property has the given declared value
* @param graph source graph
* @param p property to get associated vertex for
* @param value property value
* @return vertex corresponding to property, or null if none found
*/
public static Vertex locateVertex(IndexableGraph graph, Properties p, Object value) {
return locateVertex(graph, p.name(), value);
}
/**
* Generate edge name from property infos
* @param p source property
* @return an edge name (by default property container class name + "." + property name
*/
public static String getEdgeNameFor(Property p) {
return p.getDeclaringClass().getSimpleName()+"."+p.getName();
}
/**
* Create a vertex out of a basic object. if object is of a simple type, we'll use value as id. Elsewhere, we will generate an id for object
* @param database database in which vertex will be stored
* @param value
* @return
*/
public static Vertex getVertexForBasicObject(IndexableGraph database, Object value) {
Vertex returned = null;
// Now distinct behaviour between known objects and unknown ones
Class<? extends Object> valueClass = value.getClass();
if(Literals.containsKey(valueClass)) {
LiteralTransformer transformer = Literals.get(valueClass);
returned = transformer.getVertexFor(database, valueClass.cast(value));
} else {
throw new ObjectIsNotARealLiteralException(value, valueClass);
// TODO do not forget to set id property
}
returned.setProperty(Properties.type.name(), valueClass.getName());
return returned;
}
/**
* Create an object instance from a literal vertex compatible with this service contained class
* @param classLoader class loader used to find class
* @param key vertex containing object id
* @param repository service repository, used to disambiguate subclass of literal and managed class
* @return a fresh instance, with only id set
*/
public static Object createInstance(ClassLoader classLoader, Vertex key, ServiceRepository repository) {
String effectiveType = key.getProperty(Properties.type.name()).toString();
try {
Class effectiveClass = classLoader.loadClass(effectiveType);
if(Literals.containsKey(effectiveClass) && !repository.containsKey(effectiveClass)) {
LiteralTransformer transformer = Literals.get(effectiveClass);
return transformer.loadObject(effectiveClass, key);
} else {
return effectiveClass.newInstance();
}
} catch(Exception e) {
throw new UnableToCreateException(effectiveType, e);
}
}
/**
* Get an id for any object, provided one property can be used to define an id on it
* @param database source database
* @param declaredClass class which the object is a declared member of. it may not be its effective class, but its anyway the class we manage it with
* @param object used object
* @param idProperty id property
* @return a composite id made of id container class, and the result of {@link LiteralTransformer#getVertexId(com.tinkerpop.blueprints.pgm.Graph, Object)}
*/
public static String getIdVertexId(IndexableGraph database, Class<?> declaredClass, Object object, Property idProperty) {
Object objectId = idProperty.get(object);
return getIdPropertyValue(database, declaredClass, idProperty, objectId);
}
/**
* Get the value of the vertex id for the given object
* @param database used graph
* @param declaredClass declared object class
* @param idProperty gives the declared type of id (which may differ from primitive types, where user may give an integer instead of a long, as an example)
* @param objectId object id value
* @return the value used by {@link Properties#vertexId} to identify the vertex associated to that object
*/
public static String getIdPropertyValue(IndexableGraph database, Class<?> declaredClass, Property idProperty, Object objectId) {
return declaredClass.getCanonicalName()+":"+Literals.get(idProperty.getType()).getVertexId(database, objectId);
}
}