001/**
002 * Copyright (c) 2011, The University of Southampton and the individual contributors.
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without modification,
006 * are permitted provided that the following conditions are met:
007 *
008 *   *  Redistributions of source code must retain the above copyright notice,
009 *      this list of conditions and the following disclaimer.
010 *
011 *   *  Redistributions in binary form must reproduce the above copyright notice,
012 *      this list of conditions and the following disclaimer in the documentation
013 *      and/or other materials provided with the distribution.
014 *
015 *   *  Neither the name of the University of Southampton nor the names of its
016 *      contributors may be used to endorse or promote products derived from this
017 *      software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
020 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
021 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
022 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
023 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
024 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
025 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
026 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
027 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
028 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029 */
030package org.openimaj.text.nlp.namedentity;
031
032import java.util.ArrayList;
033import java.util.HashSet;
034
035import com.hp.hpl.jena.query.QuerySolution;
036
037/**
038 * Given an endpoint, resolve transitive relationships of a root entity.
039 * Practically speaking this is a class is mainly used to allow for RDF rule:
040 * rdfs11 and rdfs9 (see: http://www.w3.org/TR/rdf-mt/)
041 * 
042 * @author Laurence Willmore (lgw1e10@ecs.soton.ac.uk)
043 * @author Sina Samangooei (ss@ecs.soton.ac.uk)
044 */
045public class SparqlTransitiveClosure {
046
047        private final SparqlQueryPager pager;
048
049        /**
050         * @param endPoint
051         *            instantiate a {@link SparqlQueryPager} ready to explore
052         *            transitive relationships
053         */
054        public SparqlTransitiveClosure(String endPoint) {
055                super();
056                pager = new SparqlQueryPager(endPoint);
057        }
058
059        /**
060         * Given a root entity, return a hash set of all transitive relationships up
061         * until a leaf nodes
062         * 
063         * @param rootEntity
064         * @param transitiveRelationship
065         * @param leafRelationship
066         * @return a set of transitive relationships
067         */
068        public HashSet<String> getAllTransitiveLeavesOf(String rootEntity, String transitiveRelationship,
069                        String leafRelationship)
070        {
071                return scoureTheTree(rootEntity, transitiveRelationship, leafRelationship);
072        }
073
074        private HashSet<String> scoureTheTree(String rootEntity, String transitiveRelationship, String leafRelationship) {
075                final ArrayList<QuerySolution> subNodes = getSubNodes(rootEntity, transitiveRelationship);
076                final HashSet<String> result = getLeaves(rootEntity, leafRelationship);
077                for (final QuerySolution soln : subNodes) {
078                        result.addAll(scoureTheTree(soln.getResource("subject").getURI(), transitiveRelationship, leafRelationship));
079                }
080                return result;
081        }
082
083        private HashSet<String> getLeaves(String rootEntity, String leafRelationship) {
084                final HashSet<String> result = new HashSet<String>();
085                final ArrayList<QuerySolution> pageResults = pager.pageQuery(YagoQueryUtils.factSubjectsQuery(rootEntity,
086                                leafRelationship));
087                // System.out.println("--------"+rootEntity+"------------");
088                for (final QuerySolution soln : pageResults) {
089                        result.add(soln.getResource("subject").getURI());
090                        // System.out.println(soln.getResource("subject").getURI());
091                }
092                return result;
093        }
094
095        private ArrayList<QuerySolution> getSubNodes(String rootEntity, String transitiveRelationship) {
096                final ArrayList<QuerySolution> result = pager.pageQuery(YagoQueryUtils.factSubjectsQuery(rootEntity,
097                                transitiveRelationship));
098                return result;
099        }
100
101        /**
102         * a subclasof test
103         * 
104         * @param args
105         */
106        public static void main(String[] args) {
107                final SparqlTransitiveClosure st = new SparqlTransitiveClosure(YagoQueryUtils.YAGO_SPARQL_ENDPOINT);
108                final HashSet<String> res = st.getAllTransitiveLeavesOf(YagoQueryUtils.WORDNET_COMPANY_URI, "rdfs:subClassOf",
109                                "rdf:type");
110                System.out.println(res.size());
111        }
112
113}