Cypher查询具有端节点约束的最短路径

时间:2015-04-24 15:09:47

标签: neo4j cypher

我已经从java字节码生成了一个调用图,并且需要找到生成方法的类的最接近的父类。我有一个解决方案,我只想验证它不会变得更简单。

该图表具有以下关系和标签:

+---------[ :Class ] -[hasMethod]-> [ :Method ] --+
|            ^                        ^           |
+-[inherits]-+                        +-[invokes]-+

现在考虑将以下代码作为输入:

class Parent {
   protected void hello() {
   }
}

class Foo extends Parent {
   @Override
   protected void hello() {
   }
}

class Bar extends Foo {
   public void test() {
      hello();
   }
}

通过解析字节码,我得到了以下节点和关系(这里只显示了相关的字节码:

(Parent:Class)-[:hasMethod]-(:Method{name:"Parent#hello()V", 
   simpleName:"hello", signature:"()V"})
(Foo:Class)-[:inherits]->Parent
Foo-[:hasMethod]->(:Method{name: "Foo#hello()V", 
   simpleName:"hello", signature:"()V"})
(Bar:Class)-[:inherits]->Foo
Bar->[:hasMethod]->(test:Method{simpleName: "test"})
test->[:invokes]->(:Method{name: "Bar#hello()V",
  simpleName:"hello", signature: "()V"

我想找到在这种情况下将调用的最近父级的声明方法。我的解决方案如下:

match (m:Method) where not m<-[:hasMethod]-()
// method.name is Class#name(signature) 
with m, split(m.name,'#')[0] as className

// find a method with same name and signature
match (superMethod:Method{methodName:m.methodName, signature:m.signature}),

// which is declared in a superclass
p=(c:Class{name:className})-[:inherits*]->(super)-[:hasMethod]->superMethod

// and group them in a collection
with m, collect(p) as allPossibleSuperMethods

// and now keep the closest method (with the shortest path to it)
with m, reduce(path = null, p in allPossibleSuperMethods |
  case
    // the candidate is either better than nothing or shorter than previous
    when path is null or length(p) < length(path) then p
   // or we've got our winner already 
   else path
end) as superMethodPath

// and the last on the path is the closest declared method
with m,last(superMethodPath) as superMethod

// so we mark the replacement
create m-[:implementedBy]->superMethod

如您所见,任务是在非声明方法(没有hasMethod关系的方法)和父类的一个声明方法之间创建链接。问题是:它可以变得更简单吗?据我所知,shortestPath函数不能对目标节点有约束,如果省略事实,我们需要遍历两种不同的关系类型。

该示例也可在http://console.neo4j.org/?id=9cmwaf

的交互式版本中使用

查询的任务是返回单行--Foo#hello()

0 个答案:

没有答案