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.datatypes.TypeMapper;
009import org.apache.jena.graph.BlankNodeId;
010import org.apache.jena.graph.Node;
011import org.apache.jena.graph.NodeFactory;
012import org.apache.jena.graph.Triple;
013import org.apache.jena.query.Query;
014import org.apache.jena.rdf.model.AnonId;
015import org.apache.jena.sparql.core.BasicPattern;
016import org.apache.jena.sparql.core.Var;
017import org.apache.jena.sparql.syntax.Element;
018import org.apache.jena.sparql.syntax.ElementGroup;
019import org.apache.jena.sparql.syntax.ElementNamedGraph;
020import org.apache.jena.sparql.syntax.Template;
021import org.apache.jena.vocabulary.RDF;
022import java.util.*;
023import java.util.Map.Entry;
024import net.rootdev.javardfa.StatementSink;
025import org.slf4j.Logger;
026import org.slf4j.LoggerFactory;
027
028public class QueryCollector implements StatementSink {
029
030    final static Logger log = LoggerFactory.getLogger(QueryCollector.class);
031    private static final Node FormType = NodeFactory.createURI("http://www.w3.org/1999/xhtml/vocab/#form");
032    private static final TypeMapper TMapper = TypeMapper.getInstance();
033    private final Map<String, Query> queries;
034    private List<Triple> currentQuery;
035    private String currentQueryName;
036    private final Map<String, String> prefixMapping;
037
038    public QueryCollector() {
039        queries = new HashMap();
040        prefixMapping = new HashMap();
041    }
042
043    public Map<String, Query> getQueries() {
044        return Collections.unmodifiableMap(queries);
045    }
046
047    public void addLiteral(String arg0, String arg1, String arg2, String arg3,
048            String arg4) {
049        //log.info("Add literal");
050        Node subject = getNode(arg0);
051        Node predicate = getNode(arg1);
052        Node object = getLiteralNode(arg2, arg3, arg4);
053        addTriple(subject, predicate, object);
054    }
055
056    public void addObject(String arg0, String arg1, String arg2) {
057        //log.info("Add object");
058        Node subject = getNode(arg0);
059        Node predicate = getNode(arg1);
060        Node object = getNode(arg2);
061        addTriple(subject, predicate, object);
062    }
063
064    private void addTriple(Node subject, Node predicate, Node object) {
065        //log.info("Adding triple: " + subject + " " + predicate + " " + object);
066        if (RDF.type.asNode().equals(predicate) &&
067                FormType.equals(object)) {
068            if (currentQueryName != null) {
069                queries.put(currentQueryName, createQuery(currentQuery));
070            }
071            currentQueryName = subject.getURI();
072            currentQuery = new LinkedList<Triple>();
073            return;
074        }
075        if (currentQueryName == null) {
076            return; // good idea? not sure...
077        }
078        currentQuery.add(Triple.create(subject, predicate, object));
079    }
080
081    private Node getLiteralNode(String arg2, String arg3, String arg4) {
082        if (arg3 == null && arg4 == null) {
083            return NodeFactory.createLiteral(arg2);
084        } else if (arg4 == null) { // has lang
085            return NodeFactory.createLiteral(arg2, arg3, false);
086        } else { // has datatype
087            return NodeFactory.createLiteral(arg2, null, TMapper.getSafeTypeByName(arg4));
088        }
089    }
090
091    private Node getNode(String arg0) {
092        if (arg0.startsWith("_:")) // BNode
093        {
094            return NodeFactory.createBlankNode(BlankNodeId.create(arg0.substring(2)));
095        }
096        if (arg0.startsWith("?")) // Var
097        {
098            return Var.alloc(arg0.substring(1));
099        } else {
100            return NodeFactory.createURI(arg0);
101        }
102    }
103
104    public void end() {
105        if (currentQueryName != null) {
106            queries.put(currentQueryName, createQuery(currentQuery));
107        }
108    }
109
110    public void start() {
111    }
112
113    public Query createQuery(List<Triple> triples) {
114        log.info("Create query");
115        Query query = new Query();
116        ElementGroup body = new ElementGroup();
117        for (Triple t : triples) {
118            body.addTriplePattern(t);
119        }
120        // TODO make this switchable.
121        Element pattern = new ElementNamedGraph(Var.alloc("graph"), body);
122        query.setQueryPattern(pattern);
123        query.addProjectVars(Collections.singleton("s"));
124        //query.setQuerySelectType();
125        Template templ = new Template(BasicPattern.wrap(triples));
126        query.setQuerySelectType();
127        query.setQueryResultStar(true);
128        query.setConstructTemplate(templ);
129        for (Entry<String, String> e: prefixMapping.entrySet())
130            query.setPrefix(e.getKey(), e.getValue());
131        return query;
132    }
133
134    public void addPrefix(String prefix, String uri) {
135        prefixMapping.put(prefix, uri);
136    }
137
138    public void setBase(String base) {}
139}
140
141/*
142 * (c) Copyright 2009 University of Bristol
143 * All rights reserved.
144 *
145 * Redistribution and use in source and binary forms, with or without
146 * modification, are permitted provided that the following conditions
147 * are met:
148 * 1. Redistributions of source code must retain the above copyright
149 *    notice, this list of conditions and the following disclaimer.
150 * 2. Redistributions in binary form must reproduce the above copyright
151 *    notice, this list of conditions and the following disclaimer in the
152 *    documentation and/or other materials provided with the distribution.
153 * 3. The name of the author may not be used to endorse or promote products
154 *    derived from this software without specific prior written permission.
155 *
156 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
157 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
158 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
159 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
160 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
161 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
162 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
163 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
164 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
165 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
166 */