How can I use Traversal of Tinkerpop v3 instead of Frames of v2? - tinkerpop-frames

How can I write the following code unsing Tinkerpop v3?
public interface Cat {
#Relation(label="enemy")
public void addEnemy(Mouse mouse);
#Relation(label="enemy")
public Collection getEnemies();
}
FramesManager manager = new FramesManager(graph);
Cat tom = manager.frame(graph.getVertex(1), Cat.class);
Mouse jerry = manager.frame(graph.getVertex(2), Mouse.class);
tom.addEnemy(jerry);
I tried to find some example but I had no luck.
Thanks,
Celso

Related

How to limit parsing depth using Tinkerpop Frames

Hi I have an interface and a corresponding implementation class like:
public interface IActor extends VertexFrame {
#Property(ActorProps.nodeClass)
public String getNodeClass();
#Property(ActorProps.nodeClass)
public void setNodeClass(String str);
#Property(ActorProps.id)
public String getId();
#Property(ActorProps.id)
public void setId(String id);
#Property(ActorProps.name)
public String getName();
#Property(ActorProps.name)
public void setText(String text);
#Property(ActorProps.uuid)
public String getUuid();
#Property(ActorProps.uuid)
public void setUuid(String uuid);
#Adjacency(label = RelClasses.CoActors, direction = Direction.OUT)
public Iterable<IActor> getCoactors();
}
And I use OrientDB with it that looks something like that. I had similar implementation with Neo4j as well:
Graph graph = new OrientGraph("remote:localhost/actordb");
FramedGraph<Graph> manager = new FramedGraphFactory().create(graph);
IActor actor = manager.frame(((OrientGraph)graph).getVertexByKey("Actor.uuid",uuid), IActor.class);
Above works but the problem is that in this case or similar, because there is a relationship between two vertices of class Actor, there could be potentially a graph loop. Is there a way to define either by Annotation or some other way (e.g through Manager) to stop after x steps for a specific #Adjacency so this won't go forever? If #GremlinGroovy (https://github.com/tinkerpop/frames/wiki/Gremlin-Groovy) annotation is the answer could you please give an example ?
I'm not sure I understand the question/problem. (You say "potentially", but haven't actually proven that there's a problem!)
Is the problem that there is a loop in the Vertex/Frames, and (you think) loading the object will result in an infinite loop?
Have you been able to prove that there is a problem loading a Vertex/Frame with a loop? (show me the code/problem)
As I understand it, the Pipelines will lazy-load objects (only load then when required). The frames (I imagine) only load adjacent frames when requested. Basically, as far as I can tell, theres no problem.
Example (Groovy)
// create some framed vertices
Person nick = createPerson(name: 'Nick')
Person michail = createPerson(name: 'Michail')
// create a recursive loop
nick.addKnows(michail)
michail.addKnows(nick)
// handles recursion = true!
Person nick2 = framedGraph.getVertex(nick.asVertex().id, Person)
assert nick2.knows.knows.knows.knows.knows.name == 'Michail'

EPiServer 7 namespace for Locate() isn't resolving

I'm new to EPiServer, and am attempting to retrieve child news article pages from a news list that I created. Examples that I've found online used the Locate() method, but when I attempt to apply Locate to my code, it's not being found.
This is one of the articles that I looked at.
http://world.episerver.com/Blogs/Johan-Bjornfot/Dates1/2012/8/EPiServer7-Working-with-IContentRepositoryDataFactory/
Essentially, I just need to return a list of child articles for a list of news items, so it's possible that the approach that I'm attempting is not right in the first place.
At any rate, this is my current model with the using statements.
using EPiServer;
using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;
using EPiServer.ServiceLocation;
using EPiServer.SpecializedProperties;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EPiServerExercise.Models.Pages
{
[ContentType(DisplayName = "News List", GUID = "ac3287b1-4d78-4eb3-bad2-6b5c43530b33", Description = "")]
public class NewsList : BasePage
{
private IEnumerable<NewsArticle> getNewsArticles(NewsList currentPage)
{
//var contentLoader = ServiceLocator.Current.GetInstance<IContentLoader>
//IEnumerable<NewsArticle> newsArticles = new List<NewsArticle>();
//PageReference pageLink = currentPage.ParentLink;
//IEnumerable<NewsArticle> newsArticles = Locate.ContentRepository().GetChildren<IContent>(pageLink);
//IEnumerable<NewsArticle> newsArticles = ServiceLocationHelperExtensions.
//var serviceLocationHelper = ServiceLocator.Current.GetInstance();
//serviceLocationHelper.ContentLoader
}
}
}
What reference am I missing to get the Locate() method to resolve? We are using EPiServer 7 and MVC. Thanks for your help.
Update on 11/18/2014
This is the eventual solution that I put into the model. It's almost identical to what Vsevolod Goloviznin suggested. Thanks.
public string showNewsArticles()
{
IEnumerable<NewsArticle> newsArticles = getNewsArticles(this);
// Code to loop through the articles
}
private IEnumerable<NewsArticle> getNewsArticles(NewsList currentPage)
{
var repository = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();
IEnumerable<NewsArticle> newsArticles = repository.GetChildren<NewsArticle>(currentPage.ContentLink);
return newsArticles;
}
Looks like he just uses a factory to get IContentRepository and forgot to mention to. So to just get the same functionality you can use the ServiceLocator to get the IContentRepository and then get all children for your page:
var service = EPiServer.ServiceLocation.ServiceLocator.Current.GetInstance<IContentRepository>();
var pages = service.GetChildren<NewsArticle>(currentPage.ParentLink).ToList();

NEO4J Spatial: tips about batch inserter

This is my scenario: we are building a routing system by using neo4j and the spatial plugin. We start from the OSM file and we read this file and import nodes and relationships in our graph (a custom graph model)
Now, if we don't use the batch inserter of neo4j, in order to import a compressed OSM file (with compressed dimension of around 140MB, and normal dimensions around 2GB) it takes around 3 days on a dedicated server with the following characteristics: CentOS 6.5 64bit, quad core, 8GB RAM; pease note that the most time is related to the Neo4J Nodes and relationships creation; in-fact if we read the same file without doing anything with neo4j, the file is read in around 7 minutes (i'm sure about this becouse in our process we first read the file in order to store the correct osm nodes ids and then we read again the file in order to create the neo4j graph)
Obviously we need to improve the import proces so we are trying to use the batchInserter. So far, so good (I need to check how much it will perform by using the batchInserter but I guess it will be faster); so the first thing I did was: let's try to use the batch inserter in a simple test case (very similar to our code, but without modifying our code directly)
I list my software versions:
Neo4j: 2.0.2
Neo4jSpatial: 0.13-neo4j-2.0.1
Neo4jGraphCollections: 0.7.1-neo4j-2.0.1
Osmosis: 0.43.1
Since I'm using osmosis in order to read the osm file, I wrote the following Sink implementation:
public class BatchInserterSinkTest implements Sink
{
public static final Map<String, String> NEO4J_CFG = new HashMap<String, String>();
private static File basePath = new File("/home/angelo/Scrivania/neo4j");
private static File dbPath = new File(basePath, "db");
private GraphDatabaseService graphDb;
private BatchInserter batchInserter;
// private BatchInserterIndexProvider batchIndexService;
private SpatialDatabaseService spatialDb;
private SimplePointLayer spl;
static
{
NEO4J_CFG.put( "neostore.nodestore.db.mapped_memory", "100M" );
NEO4J_CFG.put( "neostore.relationshipstore.db.mapped_memory", "300M" );
NEO4J_CFG.put( "neostore.propertystore.db.mapped_memory", "400M" );
NEO4J_CFG.put( "neostore.propertystore.db.strings.mapped_memory", "800M" );
NEO4J_CFG.put( "neostore.propertystore.db.arrays.mapped_memory", "10M" );
NEO4J_CFG.put( "dump_configuration", "true" );
}
#Override
public void initialize(Map<String, Object> arg0)
{
batchInserter = BatchInserters.inserter(dbPath.getAbsolutePath(), NEO4J_CFG);
graphDb = new SpatialBatchGraphDatabaseService(batchInserter);
spatialDb = new SpatialDatabaseService(graphDb);
spl = spatialDb.createSimplePointLayer("testBatch", "latitudine", "longitudine");
//batchIndexService = new LuceneBatchInserterIndexProvider(batchInserter);
}
#Override
public void complete()
{
// TODO Auto-generated method stub
}
#Override
public void release()
{
// TODO Auto-generated method stub
}
#Override
public void process(EntityContainer ec)
{
Entity entity = ec.getEntity();
if (entity instanceof Node) {
Node osmNodo = (Node)entity;
org.neo4j.graphdb.Node graphNode = graphDb.createNode();
graphNode.setProperty("osmId", osmNodo.getId());
graphNode.setProperty("latitudine", osmNodo.getLatitude());
graphNode.setProperty("longitudine", osmNodo.getLongitude());
spl.add(graphNode);
} else if (entity instanceof Way) {
//do something with the way
} else if (entity instanceof Relation) {
//do something with the relation
}
}
}
Then I wrote the following test case:
public class BatchInserterTest
{
private static final Log logger = LogFactory.getLog(BatchInserterTest.class.getName());
#Test
public void batchInserter()
{
File file = new File("/home/angelo/Scrivania/MilanoPiccolo.osm");
try
{
boolean pbf = false;
CompressionMethod compression = CompressionMethod.None;
if (file.getName().endsWith(".pbf"))
{
pbf = true;
}
else if (file.getName().endsWith(".gz"))
{
compression = CompressionMethod.GZip;
}
else if (file.getName().endsWith(".bz2"))
{
compression = CompressionMethod.BZip2;
}
RunnableSource reader;
if (pbf)
{
reader = new crosby.binary.osmosis.OsmosisReader(new FileInputStream(file));
}
else
{
reader = new XmlReader(file, false, compression);
}
reader.setSink(new BatchInserterSinkTest());
Thread readerThread = new Thread(reader);
readerThread.start();
while (readerThread.isAlive())
{
try
{
readerThread.join();
}
catch (InterruptedException e)
{
/* do nothing */
}
}
}
catch (Exception e)
{
logger.error("Errore nella creazione di neo4j con batchInserter", e);
}
}
}
By executing this code, I get this exception:
Exception in thread "Thread-1" java.lang.ClassCastException: org.neo4j.unsafe.batchinsert.SpatialBatchGraphDatabaseService cannot be cast to org.neo4j.kernel.GraphDatabaseAPI
at org.neo4j.cypher.ExecutionEngine.<init>(ExecutionEngine.scala:113)
at org.neo4j.cypher.javacompat.ExecutionEngine.<init>(ExecutionEngine.java:53)
at org.neo4j.cypher.javacompat.ExecutionEngine.<init>(ExecutionEngine.java:43)
at org.neo4j.collections.graphdb.ReferenceNodes.getReferenceNode(ReferenceNodes.java:60)
at org.neo4j.gis.spatial.SpatialDatabaseService.getSpatialRoot(SpatialDatabaseService.java:76)
at org.neo4j.gis.spatial.SpatialDatabaseService.getLayer(SpatialDatabaseService.java:108)
at org.neo4j.gis.spatial.SpatialDatabaseService.containsLayer(SpatialDatabaseService.java:253)
at org.neo4j.gis.spatial.SpatialDatabaseService.createLayer(SpatialDatabaseService.java:282)
at org.neo4j.gis.spatial.SpatialDatabaseService.createSimplePointLayer(SpatialDatabaseService.java:266)
at it.eng.pinf.graph.batch.test.BatchInserterSinkTest.initialize(BatchInserterSinkTest.java:46)
at org.openstreetmap.osmosis.xml.v0_6.XmlReader.run(XmlReader.java:95)
at java.lang.Thread.run(Thread.java:744)
This is related to this code:
spl = spatialDb.createSimplePointLayer("testBatch", "latitudine", "longitudine");
So now I'm wondering: how can I use the batchInserter for my case? I have to add the created nodes to the SimplePointLayer....so how can I create it by using the batchInserter graph db service?
Is there any little simple sample?
Any tip is really really appreciated
cheers
Angelo
The OSMImporter class in the code has an example of using the batch inserter to import OSM data. The main thing is that the batch inserter is not really supported by neo4j spatial, so you need to do a few things manually. If you look at the class OSMImporter.OSMBatchWriter, you will see how it does things. It is not using the SimplePointLayer at all, since that does not support the batch inserter. It is creating the graph structure it wants directly. The simple point layer is quite simple, certainly much simpler than the OSM model created by the code I'm referencing, so I think you should be able to write a batch-inserter compatible version yourself without too much trouble.
What I would recommend is that you create the layer and nodes using the batch inserter to create the correct graph structure, then switch to the normal embedded API and use that to iterate through the nodes and add them to the spatial index.

Visibility ValueConverter Update Logic to MvvmCross v3

I updated an older android project from mvvmcross v2 to mvvmcross v3.
Got one more problem now.
The visibility doesn't work, its doing nothing.
Old solution looked like this (worked fine):
In Setup.cs
protected override IEnumerable<Type> ValueConverterHolders
{
get { return new[] { typeof(Converters) }; }
}
Converters.cs
using Cirrious.MvvmCross.Converters.Visibility;
namespace Test.Droid
{
public class Converters
{
public readonly MvxVisibilityConverter Visibility = new MvxVisibilityConverter();
}
}
Any .axml (change visibility of LinearLayout):
<LinearLayout style="#style/LinearLayoutSmall" local:MvxBind="{'Visibility':{'Path':'TestIsVisible','Converter':'Visibility'}}">
New solution (doesn't work):
In Setup.cs
protected override List<Type> ValueConverterHolders
{
get { return new List<Type> { typeof(Converters) }; }
}
Converters.cs
using Cirrious.MvvmCross.Plugins.Visibility;
namespace Test.Droid
{
public class Converters
{
public readonly MvxVisibilityValueConverter Visibility = new MvxVisibilityValueConverter();
}
}
Any .axml
<LinearLayout style="#style/LinearLayoutSmall" local:MvxBind="Visibility TestIsVisible, Converter=Visibility">
There's probably a problem with the swissbinding syntax or I'm using false classes?
Any help appreciated!
UPDATE
I forgot these lines:
public override void LoadPlugins(IMvxPluginManager pluginManager)
{
pluginManager.EnsurePluginLoaded<PluginLoader>();
pluginManager.EnsurePluginLoaded<Cirrious.MvvmCross.Plugins.Visibility.PluginLoader>();
base.LoadPlugins(pluginManager);
}
I guess its necessary but now I'm having following error:
(from the MvxPluginManager Class)...
I checked all references and the dll/project *.Visibility.Droid.dll is referenced in my mainproject and everywhere else...
Without running and debugging a complete sample of your code I can't see what the problem is. One guess is that it could be in the plugin setup for visibility, but that is only a guess. The debug trace for your app might reveal some information on this.
Alternatively, it might be easier to simply try setting up a new project and getting visibility working in that, then comparing that code back to your existing app.
Value Converters in v3 are documented in https://github.com/MvvmCross/MvvmCross/wiki/Value-Converters.
The preferred way of referencing them is simply to let MvvmCross find them by reflection - see the section on https://github.com/MvvmCross/MvvmCross/wiki/Value-Converters#referencing-value-converters-in-touch-and-droid
A sample app, including visibility, is in: https://github.com/MvvmCross/MvvmCross-Tutorials/tree/master/ValueConversion - e.g. https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/ValueConversion/ValueConversion.UI.Droid/Resources/Layout/View_Visibility.axml

"Proper" MVC - Should I be using a constructor or not?

If I have a model that works directly with my database (Personally using ASP.NET w\Entity Framework) should I be using a constructor to set variable?
Example:
public class songs
{
public IEnumerable<songs> allSongs {get; }
public songs()
{
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
VS
public class songs
{
public IEnumerable<songs> allSongs
{
get
{
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
public songs() {}
}
Technically both are correct, but which is more correct? The only time I can think of where there is only one correct answer is if the variable I'm setting either needs to always be updated or stay the same during an operation.
You shouldn't be accessing the data from a domain class.
You should create a SongRepository which interacts with your database. You inject the controller with this repository and when you want a list of songs you simply refer to that repository.
It might become a little tricky when songs is actually supposed to be it's own entity. However I'd strongly suggest you to implement the repository pattern.
The second approach is best when working with repositories.
Example layout:
public class SongController : Controller {
private SongRepository _songRepository;
public SongController(SongRepository repo) {
_songRepository = repo;
}
public ActionResult ShowSongs(){
return View(_songRepository.GetAllSongs());
}
}
public class SongRepository {
public IEnumerable<Song> GetAllSongs(){
using (var context = new entities())
{
allSongs = context.songs.orderBy(n => n.name).toList();
}
}
}
What if you only want to get 1 song? I'm sure you don't want to load all songs then.
If I may add, you should take a look around at existing projects or tutorials to see how things can be done. Note that I say can, what you'll read is by no means the way to do it. For example, #JeroenVannevel recommends the repository pattern, but there are plenty of people who recommend against it (when working with EF).
I recommend browsing the top questions in entity-framework, entity-framework-4, entity-framework-5 and entity-framework-6 before deciding on your data access strategy.

Resources