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