package org.aksw.jena_sparql_api.stmt; import java.util.ArrayList; import java.util.List; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.aksw.jena_sparql_api.concepts.Relation; import org.apache.jena.query.Syntax; import org.apache.jena.sparql.core.Prologue; import org.apache.jena.sparql.core.Var; import org.apache.jena.sparql.syntax.Element; /** * There are multiple ways to represent a relation: * - as a path of property uris (TODO we could extend this with a propery path language), "foaf:knows" * - as two variables, followed by a '|' and a graph pattern, e.g. "?s ?o | ?s foaf:knows ?o" * * * @author raven * */ public class SparqlRelationParserImpl implements SparqlRelationParser { private Function<String, Element> elementParser; public SparqlRelationParserImpl() { this(new SparqlElementParserImpl()); } public SparqlRelationParserImpl(Function<String, Element> elementParser) { this.elementParser = elementParser; } @Override public Relation apply(String input) { Relation result = parse(input, elementParser); return result; } public static String VAR_PATTERN_STR = "\\?(\\w|_)+"; public static Pattern VAR_PATTERN = Pattern.compile(VAR_PATTERN_STR); //public static Pattern VAR_PATTERN = Pattern.compile("\\s*(" + VAR_PATTERN_STR + "\\s+" + VAR_PATTERN_STR + ")\\s*"); public static Relation parse(String relationStr, Function<String, Element> elementParser) { String[] splits = relationStr.split("\\|", 2); if(splits.length != 2) { throw new RuntimeException("Invalid string: " + relationStr); } String varsStr = splits[0]; Matcher m = VAR_PATTERN.matcher(varsStr); List<Var> vars = new ArrayList<Var>(); while(m.find()) { String varName = m.group(1); Var v = Var.alloc(varName); vars.add(v); } if(vars.size() != 2) { throw new RuntimeException("Exactly 2 variables expected, instead got: " + varsStr); } Var sourceVar = vars.get(0); Var targetVar = vars.get(1); String elementStr = splits[1]; Element element = elementParser.apply(elementStr); Relation result = new Relation(element, sourceVar, targetVar); return result; } public static SparqlRelationParserImpl create(Syntax syntax, Prologue prologue) { SparqlElementParser elementParser = SparqlElementParserImpl.create(syntax, prologue); SparqlRelationParserImpl result = new SparqlRelationParserImpl(elementParser); return result; } }