001/*
002 * (c) Copyright 2009 University of Bristol
003 * All rights reserved.
004 * [See end of file]
005 */
006package net.rootdev.javardfa.query;
007
008import org.apache.jena.graph.Node;
009import org.apache.jena.graph.Triple;
010import org.apache.jena.query.Query;
011import org.apache.jena.query.QueryExecution;
012import org.apache.jena.query.QueryExecutionFactory;
013import org.apache.jena.query.QuerySolution;
014import org.apache.jena.query.QuerySolutionMap;
015import org.apache.jena.query.ResultSet;
016import org.apache.jena.rdf.model.Model;
017import org.apache.jena.rdf.model.ModelFactory;
018import org.apache.jena.sparql.syntax.ElementTriplesBlock;
019import org.apache.jena.sparql.syntax.ElementVisitorBase;
020import org.apache.jena.sparql.syntax.ElementWalker;
021import java.io.FileNotFoundException;
022import java.io.IOException;
023import java.net.URL;
024import java.util.LinkedList;
025import java.util.List;
026import java.util.Map;
027import net.rootdev.javardfa.Parser;
028import net.rootdev.javardfa.ParserFactory;
029import net.rootdev.javardfa.ParserFactory.Format;
030import net.rootdev.javardfa.Setting;
031import org.slf4j.Logger;
032import org.slf4j.LoggerFactory;
033import org.xml.sax.SAXException;
034import org.xml.sax.XMLReader;
035
036/**
037 *
038 * Some useful functions concerning pages with variables
039 *
040 * @author pldms
041 */
042public class QueryUtilities {
043
044    final static Logger log = LoggerFactory.getLogger(QueryUtilities.class);
045    public final static QuerySolution NoResult = new QuerySolutionMap();
046
047    /**
048     * Grab simple (BGP) queries from an html document. Over named graphs currently.
049     *
050     * @param format document format
051     * @param source document id
052     * @return
053     */
054    public static Map<String, Query> makeQueries(Format format, String source) throws SAXException, IOException {
055        QueryCollector qc = new QueryCollector();
056        XMLReader reader = ParserFactory.createReaderForFormat(qc, format);
057        ((Parser) reader.getContentHandler()).enable(Setting.FormMode);
058        if (source.matches("file:/[^/][^/].*")) source = source.replaceFirst("file:/", "file:///");
059        reader.parse(source);
060        return qc.getQueries();
061    }
062
063    // TODO: currently this won't work! Need to add to a named graph
064    /**
065     * Simple method to help rebinding data to form. Currently too simple.
066     * @param model Contains data to rebind
067     * @param query Extracted from the form above
068     * @return Name / node bindings
069     */
070    public static QuerySolution extractBinding(Model model, Query query) {
071        QueryExecution qe = QueryExecutionFactory.create(query, model);
072        ResultSet res = qe.execSelect();
073        final QuerySolution toReturn = (res.hasNext()) ?
074            res.next() : NoResult; // I will never use null again
075        if (res.hasNext()) log.warn("More than one available binding");
076        qe.close();
077        return toReturn;
078    }
079
080    /**
081     * Given some bindings and a form create a model. Intended use is handling
082     * the result of form submission.
083     *
084     * @param query The form
085     * @param bindings Submitted bindings
086     * @return Bindings applied to the query
087     */
088    public static Model bind(Query query, Map<String, String> bindings) {
089        List<Triple> triples = pullTriples(query);
090        List<Triple> boundTriples = new LinkedList<Triple>();
091        Model model = ModelFactory.createDefaultModel();
092        for (Triple t: triples) {
093            Node s = bind(t.getSubject(), bindings);
094            Node p = bind(t.getPredicate(), bindings);
095            Node o = bind(t.getObject(), bindings);
096            Triple nt = Triple.create(s, p, o);
097            model.add(model.asStatement(nt));
098        }
099        return model;
100    }
101
102    /**
103     * Collect all triples from a query body
104     * @param query
105     * @return
106     */
107    private static List<Triple> pullTriples(Query query) {
108        List<Triple> triples = new LinkedList<Triple>();
109        ElementWalker.walk(query.getQueryPattern(), new TripleCollector(triples));
110        return triples;
111    }
112
113    private static Node bind(Node object, Map<String, String> bindings) {
114        throw new UnsupportedOperationException("Not yet implemented");
115    }
116
117    private static class TripleCollector extends ElementVisitorBase {
118        private final List<Triple> triples;
119
120        private TripleCollector(List<Triple> triples) {
121            this.triples = triples;
122        }
123
124        @Override
125        public void visit(ElementTriplesBlock el) {
126            triples.addAll(el.getPattern().getList());
127        }
128
129    }
130}
131
132/*
133 * (c) Copyright 2009 University of Bristol
134 * All rights reserved.
135 *
136 * Redistribution and use in source and binary forms, with or without
137 * modification, are permitted provided that the following conditions
138 * are met:
139 * 1. Redistributions of source code must retain the above copyright
140 *    notice, this list of conditions and the following disclaimer.
141 * 2. Redistributions in binary form must reproduce the above copyright
142 *    notice, this list of conditions and the following disclaimer in the
143 *    documentation and/or other materials provided with the distribution.
144 * 3. The name of the author may not be used to endorse or promote products
145 *    derived from this software without specific prior written permission.
146 *
147 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
148 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
149 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
150 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
151 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
152 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
153 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
154 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
155 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
156 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
157 */