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