--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+
+/**
+ *
+ * @author jakub
+ */
+public class Filter implements GraphPattern {
+ private final String filter;
+
+ public Filter(String filter) {
+ this.filter = filter;
+ }
+
+ @Override
+ public void print(PrettyPrinter pr) {
+ pr.startl("FILTER ").put(filter).put(".").endl();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import org.z3950.zing.cql.utils.Printable;
+
+/**
+ *
+ * @author jakub
+ */
+public interface Form extends Printable {
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import org.z3950.zing.cql.utils.Printable;
+
+/**
+ *
+ * @author jakub
+ */
+public interface GraphPattern extends Printable {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ * @author jakub
+ */
+public class GraphPatternSet implements GraphPattern {
+ private final List<GraphPattern> patterns = new LinkedList<GraphPattern>();
+
+ public GraphPatternSet(GraphPattern... patterns) {
+ for (GraphPattern pattern : patterns)
+ this.patterns.add(pattern);
+ }
+
+ public GraphPatternSet pattern(GraphPattern pattern) {
+ patterns.add(pattern);
+ return this;
+ }
+
+ @Override
+ public void print(PrettyPrinter sw) {
+ sw.put("{").endl();
+ for (GraphPattern tp : patterns) {
+ tp.print(sw.levelUp());
+ }
+ sw.putl("}");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+
+/**
+ *
+ * @author jakub
+ */
+public class Optional extends GraphPatternSet {
+
+ public Optional(GraphPattern pattern) {
+ super(pattern);
+ }
+
+ @Override
+ public void print(PrettyPrinter sw) {
+ sw.startl("OPTIONAL ");
+ super.print(sw);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+/**
+ *
+ * @author jakub
+ */
+public class Prefix {
+ private final String name;
+ private final String url;
+
+ public Prefix(String name, String url) {
+ this.name = name;
+ this.url = url;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import java.util.Map;
+import java.util.TreeMap;
+import org.z3950.zing.cql.utils.Printable;
+
+/**
+ *
+ * @author jakub
+ */
+public class Query implements Printable {
+ private final Map<String, Prefix> prefixes = new TreeMap<String, Prefix>();
+ private Form form;
+ private Where where;
+
+ public Query() {
+ }
+
+ public Query(Form form, Where where) {
+ this.form = form;
+ this.where = where;
+ }
+
+
+ public Prefix prefix(String name) {
+ return prefixes.get(name);
+ }
+
+ public Query prefix(String name, String url) {
+ prefixes.put(name, new Prefix(name, url));
+ return this;
+ }
+
+ public Query prefix(Prefix prefix) {
+ prefixes.put(prefix.getName(), prefix);
+ return this;
+ }
+
+ public Where where() {
+ return where;
+ }
+
+ public Query where(Where where) {
+ this.where = where;
+ return this;
+ }
+
+ public Form form() {
+ return form;
+ }
+
+ public Query form(Form form) {
+ this.form = form;
+ return this;
+ }
+
+ @Override
+ public void print(PrettyPrinter sw) {
+ for (Prefix prefix : prefixes.values()) {
+ sw.startl("PREFIX ")
+ .put(prefix.getName()).put(": ")
+ .put("<").put(prefix.getUrl()).put(">").endl();
+ }
+ form.print(sw);
+ where.print(sw);
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.CQLDefaultNodeVisitor;
+import org.z3950.zing.cql.CQLRelation;
+import org.z3950.zing.cql.CQLTermNode;
+
+/**
+ *
+ * @author jakub
+ */
+public class SPARQLNodeVisitor extends CQLDefaultNodeVisitor {
+ private SelectQuery query = new SelectQuery(new Select(), new Where());
+ private int objectCounter = 1;
+
+ //some initial configuration
+ {
+ query.prefix("bf", "http://bibframe.org/vocab/");
+ query.select().var("*");
+ query.where().pattern(new TriplePattern("?work", "a", "bf:Work"));
+ }
+
+ @Override
+ public void onRelation(CQLRelation relation) {
+ if (!relation.getBase().equals("="))
+ throw new IllegalArgumentException("Can only handle '=' relations");
+ }
+
+ @Override
+ public void onTermNode(CQLTermNode node) {
+ //map index to predicate
+ String obj = getNextObject();
+ query.where().pattern(new TriplePattern("?work", node.getIndex(), obj));
+ query.where().pattern(new Filter("contains(lcase("+obj+"), \""+node.getTerm().toLowerCase()+"\")"));
+ }
+
+ private String getNextObject() {
+ return "?o" + objectCounter++;
+ }
+
+ public Query getQuery() {
+ return query;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ * @author jakub
+ */
+public class Select implements Form {
+ private final List<String> variables = new LinkedList<String>();
+
+ public Select var(String name) {
+ variables.add(name);
+ return this;
+ }
+
+ @Override
+ public void print(PrettyPrinter sw) {
+ sw.startl("SELECT");
+ for (String var : variables) {
+ sw.put(" ");
+ sw.put(var);
+ }
+ sw.endl();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+/**
+ * API helper for select queries
+ * @author jakub
+ */
+public class SelectQuery extends Query {
+
+ public SelectQuery(Select select, Where where) {
+ form(select);
+ where(where);
+ }
+
+
+ public Select select() {
+ return (Select) form();
+ }
+
+ public SelectQuery select(Select select) {
+ form(select);
+ return this;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.CQLNode;
+
+/**
+ *
+ * @author jakub
+ */
+public class Sparqler {
+
+ public static String toSPARQL(CQLNode query) {
+ return null;
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+
+/**
+ *
+ * @author jakub
+ */
+public class TriplePattern implements GraphPattern {
+ private final String subject;
+ private final String predicate;
+ private final String object;
+
+ public TriplePattern(String subjet, String predicate, String object) {
+ this.subject = subjet;
+ this.predicate = predicate;
+ this.object = object;
+ }
+
+ @Override
+ public void print(PrettyPrinter wr) {
+ wr.startl(subject).put(" ")
+ .put(predicate).put(" ")
+ .put(object).put(" .").endl();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import org.z3950.zing.cql.utils.PrettyPrinter;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ *
+ * @author jakub
+ */
+public class Where extends GraphPatternSet {
+
+ public Where(GraphPattern... patterns) {
+ super(patterns);
+ }
+
+ @Override
+ public void print(PrettyPrinter sw) {
+ sw.startl("WHERE ");
+ super.print(sw);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.utils;
+
+/**
+ *
+ * @author jakub
+ */
+public class PrettyPrinter {
+ private final static String INDENT = " ";
+ private final StringBuilder sb;
+ private final int level;
+
+ public PrettyPrinter() {
+ sb = new StringBuilder();
+ level = 0;
+ }
+
+ private PrettyPrinter(StringBuilder sb, int level) {
+ this.sb = sb;
+ this.level = level;
+ }
+
+ public PrettyPrinter put(String append) {
+ sb.append(append);
+ return this;
+ }
+
+ public PrettyPrinter endl() {
+ sb.append('\n');
+ return this;
+ }
+
+ public PrettyPrinter startl(String append) {
+ indent(level);
+ return put(append);
+ }
+
+ public PrettyPrinter putl(String line) {
+ return startl(line).endl();
+ }
+
+ public PrettyPrinter levelUp() {
+ //create new instance with a higher levelUp, backed by the same builder
+ return new PrettyPrinter(sb, level+1);
+ }
+
+ public PrettyPrinter indent(int level) {
+ while (level-- > 0) {
+ sb.append(INDENT);
+ }
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return sb.toString();
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.utils;
+
+/**
+ *
+ * @author jakub
+ */
+public interface Printable {
+ void print(PrettyPrinter pr);
+
+}
--- /dev/null
+/*
+ * Copyright (c) 1995-2014, Index Data
+ * All rights reserved.
+ * See the file LICENSE for details.
+ */
+
+package org.z3950.zing.cql.sparql;
+
+import java.io.IOException;
+import static java.lang.System.out;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.z3950.zing.cql.CQLNode;
+import org.z3950.zing.cql.CQLParseException;
+import org.z3950.zing.cql.CQLParser;
+import org.z3950.zing.cql.utils.PrettyPrinter;
+
+/**
+ *
+ * @author jakub
+ */
+public class QueryTest {
+
+ @Test
+ public void testSimpleQuery() {
+ Query query = new Query().prefix("bf", "http://bibframe.org/vocab/")
+ .form(new Select().var("?title")).where(
+ new Where(new TriplePattern("?work", "bf:title", "?title")));
+ String expected =
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ + "SELECT ?title\n"
+ + "WHERE {\n"
+ + " ?work bf:title ?title .\n"
+ + "}\n";
+ PrettyPrinter writer = new PrettyPrinter();
+ query.print(writer);
+ String sparql = writer.toString();
+ out.println(sparql);
+ assertEquals(expected, sparql);
+ }
+
+ @Test
+ public void testComplexQuery() {
+ Query query = new Query().prefix("bf", "http://bibframe.org/vocab/")
+ .form(new Select().var("?wtitle").var("?ititle"))
+ .where(
+ new Where(
+ new TriplePattern("?work", "bf:title", "?title"),
+ new Optional(new TriplePattern("?ins", "?bf:instanceOf", "?work")))
+ );
+ String expected =
+ "PREFIX bf: <http://bibframe.org/vocab/>\n"
+ + "SELECT ?wtitle ?ititle\n"
+ + "WHERE {\n"
+ + " ?work bf:title ?title .\n"
+ + " OPTIONAL {\n"
+ + " ?ins ?bf:instanceOf ?work .\n"
+ + " }\n"
+ + "}\n";
+ PrettyPrinter pp = new PrettyPrinter();
+ query.print(pp);
+ String sparql = pp.toString();
+ out.println(sparql);
+ assertEquals(expected, sparql);
+ }
+
+ @Test
+ public void testCQLConversionTitle() throws CQLParseException, IOException {
+ CQLParser p = new CQLParser();
+ CQLNode query = p.parse("bf:title = \"al gore\"");
+ SPARQLNodeVisitor visitor = new SPARQLNodeVisitor();
+ query.traverse(visitor);
+ Query sparql = visitor.getQuery();
+ PrettyPrinter pp = new PrettyPrinter();
+ sparql.print(pp);
+ String expected =
+ "PREFIX bf: <http://bibframe.org/vocab/>\n" +
+ "SELECT *\n" +
+ "WHERE {\n" +
+ " ?work a bf:Work .\n" +
+ " ?work bf:title ?o1 .\n" +
+ " FILTER contains(lcase(?o1), \"al gore\").\n" +
+ "}\n";
+ out.println(pp);
+ assertEquals(expected, pp.toString());
+ }
+
+ @Test
+ public void testCQLConversionTitleAuthor() throws CQLParseException, IOException {
+ CQLParser p = new CQLParser();
+ CQLNode query = p.parse("bf:title = \"al gore\" and \"bf:creator/bf:label\" = \"Stefoff, Rebecca\"");
+ SPARQLNodeVisitor visitor = new SPARQLNodeVisitor();
+ query.traverse(visitor);
+ Query sparql = visitor.getQuery();
+ PrettyPrinter pp = new PrettyPrinter();
+ sparql.print(pp);
+ String expected =
+ "PREFIX bf: <http://bibframe.org/vocab/>\n" +
+ "SELECT *\n" +
+ "WHERE {\n" +
+ " ?work a bf:Work .\n" +
+ " ?work bf:title ?o1 .\n" +
+ " FILTER contains(lcase(?o1), \"al gore\").\n" +
+ " ?work bf:creator/bf:label ?o2 .\n" +
+ " FILTER contains(lcase(?o2), \"stefoff, rebecca\").\n" +
+ "}\n";
+ out.println(pp);
+ assertEquals(expected, pp.toString());
+ }
+
+}