
com.nedap.archie.query.APathQuery Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
Basic utilities for use in the archie library
The newest version!
package com.nedap.archie.query;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.nedap.archie.paths.PathSegment;
import com.nedap.archie.adlparser.antlr.XPathLexer;
import com.nedap.archie.adlparser.antlr.XPathParser;
import com.nedap.archie.adlparser.antlr.XPathParser.*;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Pattern;
/**
* For now only accepts rather simple xpath-like expressions.
*
* The only queries fully supported at the moment are absolute queries with node ids, such as '/items[id1]/content[id2]/value'.
*
* Any expression after the ID-code, such as in '[id1 and name="ignored"] are currently ignored, but they parse and function
* as long as you add the id-code as first part of the expression.
*
* Created by pieter.bos on 19/10/15.
*/
public class APathQuery {
private List pathSegments = new ArrayList<>();
public APathQuery(String query) {
if(!query.startsWith("/") && !query.contains("/") && !query.contains("[")) {
pathSegments.add(new PathSegment(query));
} else if(!query.equals("/")) {
XPathLexer lexer = new XPathLexer(new ANTLRInputStream(query));
XPathParser parser = new XPathParser(new CommonTokenStream(lexer));
LocationPathContext locationPathContext = parser.locationPath();
AbsoluteLocationPathNorootContext absoluteLocationPathNorootContext = locationPathContext.absoluteLocationPathNoroot();
//if (absoluteLocationPathNorootContext == null) {
// throw new UnsupportedOperationException("relative xpath expressions not yet supported: " + query);
// }
if (absoluteLocationPathNorootContext != null && !absoluteLocationPathNorootContext.getTokens(XPathLexer.ABRPATH).isEmpty()) {
throw new UnsupportedOperationException("absolute path starting with // not yet supported");
}
RelativeLocationPathContext relativeLocationPathContext;
if(absoluteLocationPathNorootContext == null) {
relativeLocationPathContext = locationPathContext.relativeLocationPath();
} else {
relativeLocationPathContext = absoluteLocationPathNorootContext.relativeLocationPath();
}
if (!relativeLocationPathContext.getTokens(XPathLexer.ABRPATH).isEmpty()) {
throw new UnsupportedOperationException("relative path with // between steps not yet supported");
}
Pattern isDigit = Pattern.compile("\\d+");
List stepContexts = relativeLocationPathContext.step();
for (StepContext stepContext : stepContexts) {
String nodeName = stepContext.nodeTest().getText();
List predicateContexts = stepContext.predicate();
PathSegment pathSegment = new PathSegment(nodeName);
for (PredicateContext predicateContext : predicateContexts) {
//TODO: this is not a full parser. We really need one. Find one because writing an XPath parser seems like a thing that's been done before.
AndExprContext andExpressionContext = predicateContext.expr().orExpr().andExpr(0);
for (EqualityExprContext equalityExprContext : andExpressionContext.equalityExpr()) {
if (equalityExprContext.relationalExpr().size() == 1) { //do not yet support equals or not equals operator, ignore for now
String expression = equalityExprContext.getText();
if (isDigit.matcher(expression).matches()) {
pathSegment.setIndex(Integer.parseInt(expression));
} else if(expression.matches("\".*\"") || expression.matches("'.*'")) {
pathSegment.setNodeId(expression.substring(1, expression.length()-1));
} else {
pathSegment.setNodeId(expression);
}
}
}
}
pathSegments.add(pathSegment);
}
}
}
public List getPathSegments() {
return pathSegments;
}
public String toString(){
if (pathSegments.size() == 0) {
return "/";
}
return Joiner.on("").join(pathSegments);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy