001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * 004 * This file is part of DL-Learner. 005 * 006 * DL-Learner is free software; you can redistribute it and/or modify 007 * it under the terms of the GNU General Public License as published by 008 * the Free Software Foundation; either version 3 of the License, or 009 * (at your option) any later version. 010 * 011 * DL-Learner is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 014 * GNU General Public License for more details. 015 * 016 * You should have received a copy of the GNU General Public License 017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 018 */ 019package org.dllearner.algorithms.qtl.impl; 020 021import com.google.common.collect.ComparisonChain; 022import com.google.common.collect.Sets; 023import org.apache.jena.graph.Node; 024import org.apache.jena.rdf.model.Model; 025import org.apache.jena.rdf.model.RDFNode; 026import org.apache.jena.rdf.model.Resource; 027import org.apache.jena.rdf.model.Statement; 028import org.apache.jena.sparql.util.NodeComparator; 029import org.apache.jena.sparql.vocabulary.FOAF; 030import org.apache.jena.util.iterator.ExtendedIterator; 031import org.dllearner.algorithms.qtl.QueryTreeUtils; 032import org.dllearner.algorithms.qtl.datastructures.impl.RDFResourceTree; 033import org.dllearner.algorithms.qtl.util.StopURIsDBpedia; 034import org.dllearner.algorithms.qtl.util.StopURIsOWL; 035import org.dllearner.algorithms.qtl.util.StopURIsRDFS; 036import org.dllearner.algorithms.qtl.util.filters.NamespaceDropStatementFilter; 037import org.dllearner.algorithms.qtl.util.filters.ObjectDropStatementFilter; 038import org.dllearner.algorithms.qtl.util.filters.PredicateDropStatementFilter; 039import org.dllearner.kb.sparql.ConciseBoundedDescriptionGenerator; 040import org.dllearner.kb.sparql.ConciseBoundedDescriptionGeneratorImpl; 041import org.dllearner.kb.sparql.SparqlEndpoint; 042 043import java.util.*; 044import java.util.function.Predicate; 045 046/** 047 * A base factory for query trees. 048 * 049 * @author Lorenz Bühmann 050 * 051 */ 052public class QueryTreeFactoryBase implements QueryTreeFactory { 053 054 private int nodeId; 055 private final Comparator<Statement> comparator = new StatementComparator(); 056 057 private int maxDepth = 3; 058 059 private Set<Predicate<Statement>> dropFilters = new HashSet<>(); 060 061 public QueryTreeFactoryBase() { 062 } 063 064 /* (non-Javadoc) 065 * @see org.dllearner.algorithms.qtl.impl.QueryTreeFactory#setMaxDepth(int) 066 */ 067 @Override 068 public void setMaxDepth(int maxDepth) { 069 this.maxDepth = maxDepth; 070 } 071 072 @Override 073 public int maxDepth() { 074 return maxDepth; 075 } 076 077 /* (non-Javadoc) 078 * @see org.dllearner.algorithms.qtl.impl.QueryTreeFactory#getQueryTree(org.apache.jena.rdf.model.Resource, org.apache.jena.rdf.model.Model, int) 079 */ 080 @Override 081 public RDFResourceTree getQueryTree(Resource resource, Model model, int maxDepth) { 082 return createTree(resource, model, maxDepth); 083 } 084 085 /* (non-Javadoc) 086 * @see org.dllearner.algorithms.qtl.impl.QueryTreeFactory#addDropFilters(org.apache.jena.util.iterator.Filter) 087 */ 088 @SafeVarargs 089 @Override 090 public final void addDropFilters(Predicate<Statement>... dropFilters) { 091 this.dropFilters.addAll(Arrays.asList(dropFilters)); 092 } 093 094 private RDFResourceTree createTree(Resource resource, Model model, int maxDepth) { 095 nodeId = 0; 096 Map<Resource, SortedSet<Statement>> resource2Statements = new HashMap<>(); 097 098 fillMap(resource, model, resource2Statements); 099 100 RDFResourceTree tree = new RDFResourceTree(resource.asNode()); 101 fillTree(resource, tree, resource2Statements, 0, maxDepth); 102 103 return tree; 104 } 105 106 private void fillMap(Resource s, Model model, Map<Resource, SortedSet<Statement>> resource2Statements) { 107 108 // get all statements with subject s 109 ExtendedIterator<Statement> it = model.listStatements(s, null, (RDFNode) null); 110 111 // filter statement if necessary 112 if (!dropFilters.isEmpty()) { 113 Iterator<Predicate<Statement>> iter = dropFilters.iterator(); 114 Predicate<Statement> keepFilter = iter.next(); 115 it = it.filterKeep(keepFilter); 116 while (iter.hasNext()) {it = it.filterKeep(iter.next()); 117// keepFilter = keepFilter.and(iter.next()); 118 } 119// it = it.filterKeep(keepFilter); 120 } 121 122 SortedSet<Statement> statements = resource2Statements.computeIfAbsent(s, k -> new TreeSet<>(comparator)); 123 124 while (it.hasNext()) { 125 Statement st = it.next(); 126 statements.add(st); 127 if ((st.getObject().isResource()) && !resource2Statements.containsKey(st.getObject().asResource())) { 128 fillMap(st.getObject().asResource(), model, resource2Statements); 129 } 130 } 131 } 132 133 private void fillTree(Resource root, RDFResourceTree tree, Map<Resource, SortedSet<Statement>> resource2Statements, 134 int currentDepth, int maxDepth) { 135 currentDepth++; 136 if (resource2Statements.containsKey(root)) { 137 RDFResourceTree subTree; 138 139 for (Statement st : resource2Statements.get(root)) { 140 Node predicate = st.getPredicate().asNode(); 141 RDFNode object = st.getObject(); 142 143 if (object.isLiteral()) { 144 subTree = new RDFResourceTree(nodeId++, object.asNode()); 145 tree.addChild(subTree, predicate); 146 } else if (object.isURIResource()) { 147 subTree = new RDFResourceTree(nodeId++, object.asNode()); 148 tree.addChild(subTree, predicate); 149// System.out.println(root + "::" + object + "::" + (currentDepth < maxDepth)); 150 if (currentDepth < maxDepth) { 151 fillTree(object.asResource(), subTree, resource2Statements, currentDepth, maxDepth); 152 } 153 } else if (object.isAnon()) { 154 subTree = new RDFResourceTree(nodeId++); 155 tree.addChild(subTree, predicate); 156 if (currentDepth < maxDepth) { 157 fillTree(object.asResource(), subTree, resource2Statements, currentDepth, maxDepth); 158 } 159 } 160 } 161 } 162 currentDepth--; 163 } 164 165 static class StatementComparator implements Comparator<Statement> { 166 167 final NodeComparator nodeComparator = new NodeComparator(); 168 169 @Override 170 public int compare(Statement s1, Statement s2) { 171 return ComparisonChain.start() 172 .compare(s1.getPredicate().asNode(), s2.getPredicate().asNode(), nodeComparator) 173 .compare(s1.getObject().asNode(), s2.getObject().asNode(), nodeComparator) 174 .result(); 175 } 176 } 177 178 public static String encode(String s) { 179 char[] htmlChars = s.toCharArray(); 180 StringBuilder encodedHtml = new StringBuilder(); 181 for (char htmlChar : htmlChars) { 182 switch (htmlChar) { 183 case '<': 184 encodedHtml.append("<"); 185 break; 186 case '>': 187 encodedHtml.append(">"); 188 break; 189 case '&': 190 encodedHtml.append("&"); 191 break; 192 case '\'': 193 encodedHtml.append("'"); 194 break; 195 case '"': 196 encodedHtml.append("""); 197 break; 198 case '\\': 199 encodedHtml.append("\"); 200 break; 201 case (char) 133: 202 encodedHtml.append("…"); 203 break; 204 default: 205 encodedHtml.append(htmlChar); 206 break; 207 } 208 } 209 return encodedHtml.toString(); 210 } 211 212 213 214 public static void main(String[] args) throws Exception { 215 QueryTreeFactory factory = new QueryTreeFactoryBase(); 216 factory.setMaxDepth(2); 217 factory.addDropFilters( 218 new PredicateDropStatementFilter(Sets.union(Sets.union(StopURIsDBpedia.get(), StopURIsRDFS.get()), StopURIsOWL.get())), 219 new ObjectDropStatementFilter(StopURIsOWL.get()), 220 new NamespaceDropStatementFilter( 221 Sets.newHashSet( 222 "http://dbpedia.org/property/", 223 "http://purl.org/dc/terms/", 224 "http://dbpedia.org/class/yago/", 225 FOAF.getURI() 226 ) 227 ) 228 ); 229 ConciseBoundedDescriptionGenerator cbdGen = new ConciseBoundedDescriptionGeneratorImpl( 230 SparqlEndpoint.getEndpointDBpedia()); 231 String resourceURI = "http://dbpedia.org/resource/Athens"; 232 Model cbd = cbdGen.getConciseBoundedDescription(resourceURI, 2); 233 RDFResourceTree queryTree = factory.getQueryTree(resourceURI, cbd); 234 System.out.println(queryTree.getStringRepresentation()); 235 System.out.println(QueryTreeUtils.toSPARQLQuery(queryTree)); 236 } 237 238}