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 */