First work on SPARQL stuff
authorAdam Dickmeiss <adam@indexdata.dk>
Tue, 4 Nov 2014 14:02:49 +0000 (15:02 +0100)
committerAdam Dickmeiss <adam@indexdata.dk>
Tue, 4 Nov 2014 14:02:49 +0000 (15:02 +0100)
include/yaz/Makefile.am
include/yaz/sparql.h [new file with mode: 0644]
src/Makefile.am
src/sparql.c [new file with mode: 0644]
test/.gitignore
test/Makefile.am
test/test_sparql.c [new file with mode: 0644]
win/makefile

index 0c5ab8a..c5ac591 100644 (file)
@@ -24,7 +24,7 @@ pkginclude_HEADERS= backend.h base64.h \
  zes-psched.h zes-admin.h zes-pset.h zes-update.h zes-update0.h \
  zoom.h z-charneg.h charneg.h soap.h srw.h zgdu.h matchstr.h json.h \
  file_glob.h dirent.h thread_id.h gettimeofday.h shptr.h thread_create.h \
- spipe.h stemmer.h url.h
+ spipe.h stemmer.h url.h sparql.h
 
 EXTRA_DIST = yaz-version.h.in
 
diff --git a/include/yaz/sparql.h b/include/yaz/sparql.h
new file mode 100644 (file)
index 0000000..755909a
--- /dev/null
@@ -0,0 +1,77 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data.
+ * All rights reserved.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Index Data nor the names of its contributors
+ *       may be used to endorse or promote products derived from this
+ *       software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** \file
+    \brief Header for RPN to CQL tranform
+*/
+
+#ifndef SPARQL_H_INCLUDED
+#define SPARQL_H_INCLUDED
+
+#include <yaz/wrbuf.h>
+#include <yaz/z-core.h>
+#include <yaz/nmem.h>
+
+YAZ_BEGIN_CDECL
+
+typedef struct yaz_sparql_s *yaz_sparql_t;
+
+YAZ_EXPORT
+yaz_sparql_t yaz_sparql_create(void);
+
+YAZ_EXPORT
+void yaz_sparql_destroy(yaz_sparql_t s);
+
+YAZ_EXPORT
+int yaz_sparql_add_pattern(yaz_sparql_t s, const char *pattern,
+                           const char *value);
+
+YAZ_EXPORT
+int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
+                               WRBUF addinfo,
+                               void (*pr)(const char *buf,
+                                          void *client_data),
+                               void *client_data,
+                               Z_RPNQuery *q);
+
+YAZ_EXPORT
+int yaz_sparql_from_rpn_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
+                              Z_RPNQuery *q);
+
+YAZ_END_CDECL
+
+#endif
+/* CQL_H_INCLUDED */
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 3f431f0..5b7fc5f 100644 (file)
@@ -111,7 +111,7 @@ libyaz_la_SOURCES= $(GEN_FILES) \
   iconv_encode_marc8.c iconv_encode_iso_8859_1.c iconv_encode_wchar.c \
   iconv_decode_marc8.c iconv_decode_iso5426.c iconv_decode_danmarc.c sc.c \
   json.c xml_include.c file_glob.c dirent.c mutex-p.h mutex.c condvar.c \
-  thread_id.c gettimeofday.c thread_create.c spipe.c url.c
+  thread_id.c gettimeofday.c thread_create.c spipe.c url.c sparql.c
 
 libyaz_la_LDFLAGS=-version-info $(YAZ_VERSION_INFO)
 
diff --git a/src/sparql.c b/src/sparql.c
new file mode 100644 (file)
index 0000000..a62a80d
--- /dev/null
@@ -0,0 +1,127 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data
+ * See the file LICENSE for details.
+ */
+/**
+ * \file sparql.c
+ * \brief SPARQL
+ */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <yaz/sparql.h>
+#include <yaz/tokenizer.h>
+
+struct sparql_entry {
+    char *pattern;
+    char *value;
+    struct sparql_entry *next;
+};
+
+struct yaz_sparql_s {
+    NMEM nmem;
+    struct sparql_entry *conf;
+    struct sparql_entry **last;
+};
+
+yaz_sparql_t yaz_sparql_create(void)
+{
+    NMEM nmem = nmem_create();
+    yaz_sparql_t s = (yaz_sparql_t) nmem_malloc(nmem, sizeof *s);
+
+    s->nmem = nmem;
+    s->conf = 0;
+    s->last = &s->conf;
+    return s;
+}
+
+void yaz_sparql_destroy(yaz_sparql_t s)
+{
+    if (s)
+        nmem_destroy(s->nmem);
+}
+
+int yaz_sparql_add_pattern(yaz_sparql_t s, const char *pattern,
+                           const char *value)
+{
+    struct sparql_entry *e;
+    assert(s);
+
+    e = (struct sparql_entry *) nmem_malloc(s->nmem, sizeof(*e));
+    e->pattern = nmem_strdup(s->nmem, pattern);
+    e->value = nmem_strdup(s->nmem, value);
+    e->next = 0;
+    *s->last = e;
+    s->last = &e->next;
+    return 0;
+}
+
+int yaz_sparql_from_rpn_wrbuf(yaz_sparql_t s, WRBUF addinfo, WRBUF w,
+                              Z_RPNQuery *q)
+{
+    return yaz_sparql_from_rpn_stream(s, addinfo, wrbuf_vp_puts, w, q);
+}
+
+int yaz_sparql_from_rpn_stream(yaz_sparql_t s,
+                               WRBUF addinfo,
+                               void (*pr)(const char *buf,
+                                          void *client_data),
+                               void *client_data,
+                               Z_RPNQuery *q)
+{
+    struct sparql_entry *e;
+    yaz_tok_cfg_t cfg = yaz_tok_cfg_create();
+    int errors = 0;
+
+    for (e = s->conf; e; e = e->next)
+    {
+        if (!strcmp(e->pattern, "prefix"))
+        {
+            yaz_tok_parse_t p = yaz_tok_parse_buf(cfg, e->value);
+            int token;
+
+            token = yaz_tok_move(p);
+            if (token != YAZ_TOK_STRING)
+                errors++;
+            else
+            {
+                const char *tok_str = yaz_tok_parse_string(p);
+                pr("PREFIX ", client_data);
+                pr(tok_str, client_data);
+                pr(" ", client_data);
+
+                token = yaz_tok_move(p);
+                if (token != YAZ_TOK_STRING)
+                    errors++;
+                else
+                {
+                    tok_str = yaz_tok_parse_string(p);
+                    if (*tok_str == '<')
+                        pr(tok_str, client_data);
+                    else
+                    {
+                        pr("<", client_data);
+                        pr(tok_str, client_data);
+                        pr(">", client_data);
+                    }
+                }
+                pr("\n", client_data);
+            }
+        }
+    }
+    yaz_tok_cfg_destroy(cfg);
+
+    return errors ? -1 : 0;
+}
+
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 7f2149a..9b28c92 100644 (file)
@@ -15,6 +15,7 @@ test_wrbuf
 test_log
 test_soap1
 test_soap2
+test_sparql
 test_odrstack
 test_logthread
 test_xmlquery
@@ -49,4 +50,4 @@ test_zgdu
 *.diff
 *.hex*
 *.revert*
-*.trs
\ No newline at end of file
+*.trs
index 905526d..d009b4f 100644 (file)
@@ -11,7 +11,7 @@ check_PROGRAMS = test_ccl test_comstack test_cql2ccl \
  test_record_conv test_rpn2cql test_rpn2solr test_retrieval \
  test_shared_ptr test_soap1 test_soap2 test_solr test_sortspec \
  test_timing test_tpath test_wrbuf \
- test_xmalloc test_xml_include test_xmlquery test_zgdu
+ test_xmalloc test_xml_include test_xmlquery test_zgdu test_sparql
 
 check_SCRIPTS = test_marc.sh test_marccol.sh test_cql2xcql.sh \
        test_cql2pqf.sh test_icu.sh
@@ -100,4 +100,5 @@ test_file_glob_SOURCES = test_file_glob.c
 test_shared_ptr_SOURCES = test_shared_ptr.c
 test_libstemmer_SOURCES = test_libstemmer.c
 test_embed_record_SOURCES = test_embed_record.c
+test_sparql_SOURCES = test_sparql.c
 test_zgdu_SOURCES = test_zgdu.c
diff --git a/test/test_sparql.c b/test/test_sparql.c
new file mode 100644 (file)
index 0000000..75c1c21
--- /dev/null
@@ -0,0 +1,97 @@
+/* This file is part of the YAZ toolkit.
+ * Copyright (C) Index Data
+ * See the file LICENSE for details.
+ */
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <string.h>
+#include <yaz/sparql.h>
+#include <yaz/log.h>
+#include <yaz/test.h>
+#include <yaz/pquery.h>
+
+static int test_query(yaz_sparql_t s, const char *pqf, const char *expect)
+{
+    YAZ_PQF_Parser parser = yaz_pqf_create();
+    ODR odr = odr_createmem(ODR_ENCODE);
+    Z_RPNQuery *rpn = yaz_pqf_parse(parser, odr, pqf);
+    int ret = 0;
+    WRBUF addinfo = wrbuf_alloc();
+    WRBUF w = wrbuf_alloc();
+
+    if (rpn)
+    {
+        int r = yaz_sparql_from_rpn_wrbuf(s, addinfo, w, rpn);
+        if (expect)
+        {
+            if (!r)
+            {
+                if (!strcmp(expect, wrbuf_cstr(w)))
+                    ret = 1;
+                else
+                {
+                    yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
+                    yaz_log(YLOG_WARN, " expect: %s", expect);
+                    yaz_log(YLOG_WARN, " got:    %s", wrbuf_cstr(w));
+                }
+            }
+            else
+            {
+                yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
+                yaz_log(YLOG_WARN, " expect: %s", expect);
+                yaz_log(YLOG_WARN, " got error: %d:%s", r, wrbuf_cstr(addinfo));
+            }
+        }
+        else
+        {
+            if (r)
+                ret = 1;
+            else
+            {
+                yaz_log(YLOG_WARN, "test_sparql: pqf=%s", pqf);
+                yaz_log(YLOG_WARN, " expect error");
+                yaz_log(YLOG_WARN, " got:    %s", wrbuf_cstr(w));
+            }
+        }
+    }
+    wrbuf_destroy(w);
+    wrbuf_destroy(addinfo);
+    odr_destroy(odr);
+    yaz_pqf_destroy(parser);
+    return ret;
+}
+
+static void tst1(void)
+{
+    yaz_sparql_t s = yaz_sparql_create();
+
+    yaz_sparql_add_pattern(s, "prefix",
+                           "rdf: http://www.w3.org/1999/02/22-rdf-syntax-ns");
+    yaz_sparql_add_pattern(s, "prefix",
+                           "bf: <http://bibframe.org/vocab/>");
+    YAZ_CHECK(test_query(
+                  s, "computer",
+                  "PREFIX rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns>\n"
+                  "PREFIX bf: <http://bibframe.org/vocab/>\n"));
+
+    yaz_sparql_destroy(s);
+}
+
+int main(int argc, char **argv)
+{
+    YAZ_CHECK_INIT(argc, argv);
+    YAZ_CHECK_LOG();
+    tst1();
+    YAZ_CHECK_TERM;
+}
+/*
+ * Local variables:
+ * c-basic-offset: 4
+ * c-file-style: "Stroustrup"
+ * indent-tabs-mode: nil
+ * End:
+ * vim: shiftwidth=4 tabstop=8 expandtab
+ */
+
index 9d9395d..9e8fc88 100644 (file)
@@ -555,6 +555,7 @@ MISC_OBJS= \
    $(OBJDIR)\file_glob.obj \
    $(OBJDIR)\thread_id.obj \
    $(OBJDIR)\dirent.obj \
+   $(OBJDIR)\sparql.obj \
    $(OBJDIR)\url.obj
 
 Z3950_OBJS= \