As the title say, is there a way to find the children of children node when listen or visit a node in ANTLR.
For example: (use grammars-v4-java lexer and parse rule)
First, I take a java file to grammar tree.
grun Java compilationUnit -gui Example.java
// Example.java
public class Example {
String name = "test";
void call(){
String name1 = "test";
}
}
and the grammar tree is
Then I try to use java to extends the baseListerner to listen enterClassDeclaration node. So I can get the ClassDeclarationContext node. I want to find the ClassDeclarationContext node's children of children that the child type is LocalDeclarationContext.
In this example:
public class MyListener extends JavaParserBaseListener {
#Override
public void enterClassDeclaration(JavaParser.ClassDeclarationContext ctx) {
// find the children of children by ctx
List<ParserRuleContext> contexts = findChildContextBy(ctx, LocalVariableDeclarationContext.class);
super.enterClassDeclaration(ctx);
}
}
The variable contexts should has two elements. name and name1
I do not want to find the children one layer by one layer. emmm, Is there have a convenient way?
For a given parse tree it's easy to look up specific child nodes (at any nesting level) using ANTLR4's XPath implementation.
You can trigger that search from either the full parse tree return by the called parser rule or within a listener/visitor method for the particular subtree, for example:
List<ParseTreeMatch> matches = XPath.findAll(ctx, "//localVariableDeclaration", parser);
The return matches are instances of LocalVariableDeclarationContext (if any matched).
Note: the linked page describe two search utilities, parse tree matching and XPath, which can be used individually or together.
Related
I have a XML file resulted from an input java file. I also have xPath expressions for the XML file.
I need a function that receives one xPath expression and return its java element (in the abstract syntax tree). I tried the below code:
First extract XML element based on the input xPath expression.
XPath xPath = XPathFactory.newInstance().newXPath();
String query = "//unit[1]/unit[1]/class[1]/block[1]/function[6]"; //a method
Node node = (Node) xPath.compile(query).evaluate(XmlDocument, XPathConstants.NODE);
However, I do not know how to link extracted XML node to Java element in the source code.
PS:
The reslut should be a node in the abstract syntax tree. I have AST created by spoon. Therefore, in the above example, I want to extract related CtMethodImpl.
node.getTextContent() is not the answer as it is possible that there is more than one instance with the similar text content.
To the best of my knowledge there is no 'direct' way of doing this.
This: "//unit[1]/unit[1]/class[1]/block[1]/function[6]" is what we call a signature in the sense that it uniquely identifies an element (somehow).
What I would do is to create a spoon processor and go through the entire AST checking each element to see if it matches the signature.
public class ProcessorExample <E extends CtElement> extends AbstractProcessor<E> {
HashMap<String, Node> nodes;
//Sets your XML Nodes here, sorted by signature
public void setNodes(HashMap<String, Node> nodes) {
this.nodes = nodes;
}
#Override
public void process(E element) {
if (nodes.containsKey(signature(element))) {
Node n = nodes.get(signature(element));
//YOU FOUND IT!
}
}
private String signature(E element) {
//YOU MUST PROVIDE THIS IMPLEMENTATION
//TO MATCH YOUR "//unit[1]/unit[1]/class[1]/block[1]/function[6]"
//KIND OF SIGNATURE
return null;
}
}
I would like to know a simple method to write this SPARQL query in Java Code:
select ?input
?string
(strlen(?match)/strlen(?string) as ?percent)
where {
values ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
values (?input ?pattern ?replacement) {
("cat" "^x[^cat]*([c]?)[^at]*([a]?)[^t]*([t]?).*$" "$1$2$3")
("Londn" "^x[^Londn]*([L]?)[^ondn]*([o]?)[^ndn]*([n]?)[^dn]*([d]?)[^n]*([n]?).*$" "$1$2$3$4$5")
}
bind( replace( concat('x',?string), ?pattern, ?replacement) as ?match )
}
order by ?pattern desc(?percent)
This code is contained in the discussion To use iSPARQL to compare values using similarity measures.
The purpose of this code is to find the resources similar to a given word on DBPedia.
This method takes into consideration that I know in advance the strings and the length of it. I would like to know how I can write this query in a parameterized method that, regardless of the word and the length of it, it returns to me the similarity measures.
Update: ARQ - Writing Property Functions is now part of the standard Jena documentation.
It looks like you'd enjoy having a syntactic extension to SPARQL that performs the more complex portions of your query. For example:
SELECT ?input ?string ?percent WHERE
{
VALUES ?string { "London" "Londn" "London Fog" "Lando" "Land Ho!"
"concatenate" "catnap" "hat" "cat" "chat" "chart" "port" "part" }
VALUES ?input { "cat" "londn" }
?input <urn:ex:fn#matches> (?string ?percent) .
}
ORDER BY DESC(?percent)
In this example, it's assumed that <urn:ex:fn#matches> is a property function that will automatically perform the matching operation and calculate the similarity.
The Jena documentation does a great job explaining how to write a custom filter function,
but (as of 07/08/2014) does little to explain how to implement a custom property function.
I will make the assumption that you can convert your answer into java code for the purpose of calculating string similarity, and focus on the implementation of a property function that can house your code.
Implementing a Property Function
Every property function is associated with a particular Context. This allows you to limit the availability of the function to be global or associated with a particular dataset.
Assuming you have an implementation of PropertyFunctionFactory (shown later), you can register the function as follows:
Registration
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ARQ.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ARQ.getContext(), reg);
The only difference between global and dataset-specific registration is where the Context object comes from:
final Dataset ds = DatasetFactory.createMem();
final PropertyFunctionRegistry reg = PropertyFunctionRegistry.chooseRegistry(ds.getContext());
reg.put("urn:ex:fn#matches", new MatchesPropertyFunctionFactory);
PropertyFunctionRegistry.set(ds.getContext(), reg);
MatchesPropertyFunctionFactory
public class MatchesPropertyFunctionFactory implements PropertyFunctionFactory {
#Override
public PropertyFunction create(final String uri)
{
return new PFuncSimpleAndList()
{
#Override
public QueryIterator execEvaluated(final Binding parent, final Node subject, final Node predicate, final PropFuncArg object, final ExecutionContext execCxt)
{
/* TODO insert your stuff to perform testing. Note that you'll need
* to validate that things like subject/predicate/etc are bound
*/
final boolean nonzeroPercentMatch = true; // XXX example-specific kludge
final Double percent = 0.75; // XXX example-specific kludge
if( nonzeroPercentMatch ) {
final Binding binding =
BindingFactory.binding(parent,
Var.alloc(object.getArg(1)),
NodeFactory.createLiteral(percent.toString(), XSDDatatype.XSDdecimal));
return QueryIterSingleton.create(binding, execCtx);
}
else {
return QueryIterNullIterator.create(execCtx);
}
}
};
}
}
Because the property function that we create takes a list as an argument, we use PFuncSimpleAndList as an abstract implementation. Aside from that, most of the magic that happens inside these property functions is the creation of Bindings, QueryIterators, and performing validation of the input arguments.
Validation/Closing Notes
This should be more than enough to get you going on writing your own property function, if that is where you'd like to house your string-matching logic.
What hasn't been shown is input validation. In this answer, I assume that subject and the first list argument (object.getArg(0)) are bound (Node.isConcrete()), and that the second list argument (object.getArg(1)) is not (Node.isVariable()). If your method isn't called in this manner, things would explode. Hardening the method (putting many if-else blocks with condition checks) or supporting alternative use-cases (ie: looking up values for object.getArg(0) if it is a variable) are left to the reader (because it's tedious to demonstrate, easily testable, and readily apparent during implementation).
My graph contains nodes called points and lines.
There is a relationship type called "NEXT", which connects two points and has a property called lineID (a long). A line node consists simply of an ID and a reference to a "root" point. To traverse a line is to start with its root node and follow the NEXT relationships whose lineID matches the id of the line being traversed. To clarify, if we're traversing a line with ID 123, whose root point has id 321, the Cypher traversal would be:
START n = node(321)
MATCH (n)-[rel:NEXT*{lineID:123}]->(x)
RETURN collect(rel)
A line, then, is essentially a linked list of Next relationships with matching lineID properties. That said, I don't want to persist this list as a property of lines - I want the list to be constructed by a traversal when a line is loaded.
What are my options for implementing this in spring-data-neo4j? Specifically, should "lines" exist as NodeEntitys, and if so what should they contain?
#NodeEntity
class Line {
#RelatedTo(type="ROOT")
Point root;
#RelatedToVia(type="NEXT")
Iterable<Item> list;
doesn't quite fit, because the line is not related via Next relationships to the item, the root point is. It also fails to address the fact that those NEXT relationships need to have a lineID property matching the line's ID (which becomes important because some points exist on multiple lines - i.e. they have multiple NEXT relationships with different lineID's). I have a hunch that the solution will involve annotating the list as a #GraphTraversal, but I don't understand how that would work.
I'm doing this largely as an exercise to wrap my head around data modeling in SDN, in the context of wrapping my head around Neo4j and graph databases in general. If the question I'm asking reveals a flaw in my understanding of any of these things, I'd be very appreciative if someone could point it out.
This should be a suitable model for your entities:
#NodeEntity
class Point {
#GraphId
protected Long id;
#RelatedToVia(type="NEXT")
Set<Edge> edges;
}
#NodeEntity
class Line {
#GraphId
protected Long id;
#RelatedTo(type="ROOT")
Point root;
}
#RelationshipEntity
public class Edge {
#GraphId
protected Long id;
#StartNode private Point from;
#EndNode private Point to;
#RelatedTo(type="LINE")
Line line;
}
It easily allows both programmatic navigation in Java as in:
Set edges = line.getPoint().getEdges();
for (Edge edge: edges) {
if (edge.getLine().getId() == id) {
...
}
}
or Cypher queries like the one you listed.
Given two XML documents, I would like to programmatically identify where the documents differ, and extract the locations of the differences as a list of XPath expressions.
I would like to do it using Java.
I would also like the definition of 'difference' to be somewhat configurable (i.e. similar vs identical - in terms of whitespace/formatting, empty simple elements etc.)
I assume that I can use something akin to XMLUnit, but if I understand correctly as a testing tool XMLUnit only identifies that there is a difference, but does not expose the details in a way that can be used programmatically.
Actually, it looks like it can be done using XMLUnit, by overriding the DifferenceListener.
final List<String> xpaths = new ArrayList<String>();
DifferenceListener myDifferenceListener = new DifferenceListener() {
public void skippedComparison(Node arg0, Node arg1) {
// Do nothing
}
public int differenceFound(Difference pDifference) {
xpaths.add(pDifference.getControlNodeDetail().getXpathLocation());
return RETURN_ACCEPT_DIFFERENCE;
}
};
Diff myDiff = new Diff(xmlDoc1, xmlDoc2);
myDiff.overrideDifferenceListener(myDifferenceListener);
myDiff.similar();
return paths;
How can I represent a tree structure like below, in java?
"root"
| |
"leaf1" "leaf2"
| |
"leaf3" "leaf4"
|
"leaf5"
Are there any built-in or custom classes anyone can refer me to?
EDIT: I need to be able to easily traverse through nodes.
There is no generic tree type in the Java class libraries, or in either Guava or Apache Commons Collections.
The easiest solution is to implement the tree type yourself to do exactly what you require. The core functionality of a tree is trivial ... modulo that the details depend heavily on what the tree needs to contain and how your use-case requires it to behave.
(If you want to understand why there is no generic tree type, try to get your head around the discussion on this Guava issue - http://code.google.com/p/guava-libraries/issues/detail?id=174)
Following is simple binary tree, that would solve your purpose.
http://www.java2s.com/Code/Java/Collections-Data-Structure/BinaryTree.htm
Try this [very general though]:
public class Tree {
private Node root;
public Tree(String rootData) {
root = new Node();
root.data = rootData;
root.children = new ArrayList<Node>();
}
private class Node {
private String data;
private Node parent;
private List<Node> children;
}
}
It might not be part of the Collections API, but Swing's JTree TreeModel is certainly a generic tree implementation: https://docs.oracle.com/javase/7/docs/api/javax/swing/tree/TreeModel.html
Just make your own Node class:
Node {
T value;
Node left;
Node right;
}
For a more complex implementation see Java's N-ary tree DefaultMutableTreeNode