001/** 002 * Copyright (C) 2007 - 2016, Jens Lehmann 003 * <p> 004 * This file is part of DL-Learner. 005 * <p> 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 * <p> 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 * <p> 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.util.filters; 020 021import org.apache.jena.graph.Node; 022import org.apache.jena.vocabulary.RDF; 023import org.dllearner.algorithms.qtl.QueryTreeUtils; 024import org.dllearner.algorithms.qtl.datastructures.NodeInv; 025import org.dllearner.algorithms.qtl.datastructures.impl.RDFResourceTree; 026import org.dllearner.algorithms.qtl.util.Entailment; 027 028import java.util.Collection; 029import java.util.HashSet; 030import java.util.Set; 031import java.util.SortedSet; 032 033/** 034 * A query tree filter that removes edges whose existence is supposed to be 035 * semantically meaningless from user perspective. 036 * 037 * @author Lorenz Buehmann 038 * 039 */ 040public class PredicateExistenceFilter extends AbstractTreeFilter<RDFResourceTree> { 041 042 private Set<Node> existentialMeaninglessProperties = new HashSet<>(); 043 044 public PredicateExistenceFilter() {} 045 046 public PredicateExistenceFilter(Set<Node> existentialMeaninglessProperties) { 047 this.existentialMeaninglessProperties = existentialMeaninglessProperties; 048 } 049 050 /** 051 * @param existentialMeaninglessProperties the existential meaningless properties 052 */ 053 public void setExistentialMeaninglessProperties(Set<Node> existentialMeaninglessProperties) { 054 this.existentialMeaninglessProperties = existentialMeaninglessProperties; 055 } 056 057 public boolean isMeaningless(Node predicate) { 058 return existentialMeaninglessProperties.contains(predicate); 059 } 060 061 @Override 062 public RDFResourceTree apply(RDFResourceTree tree) { 063 RDFResourceTree newTree = new RDFResourceTree(tree, false); 064 065// if (tree.isLiteralNode() && !tree.isLiteralValueNode()) { 066// newTree = new RDFResourceTree(tree.getDatatype()); 067// } else { 068// newTree = new RDFResourceTree(0); 069// newTree.setData(tree.getData()); 070// } 071// newTree.setAnchorVar(tree.getAnchorVar()); 072 073 for (Node edge : tree.getEdges()) { 074 // get the label if it's an incoming edge 075 Node edgeLabel = edge instanceof NodeInv ? ((NodeInv) edge).getNode() : edge; 076 077 // properties that are marked as "meaningless" 078 if (isMeaningless(edgeLabel)) { 079 // if the edge is meaningless 080 // 1. process all children 081 for (RDFResourceTree child : tree.getChildren(edge)) { 082 // add edge if child is resource, literal or a nodes that has to be kept 083 if (child.isResourceNode() || child.isLiteralValueNode() || nodes2Keep.contains(child.getAnchorVar())) { 084 RDFResourceTree newChild = apply(child); 085 newTree.addChild(newChild, edge); 086 } else { 087 // else recursive call and then check if there is no more child attached, i.e. it's just a leaf with a variable as label 088 RDFResourceTree newChild = apply(child); 089 SortedSet<Node> childEdges = newChild.getEdges(); 090 if (!childEdges.isEmpty() && !(childEdges.size() == 1 && childEdges.contains(RDF.type.asNode()))) { 091 newTree.addChild(newChild, edge); 092 } 093 } 094 } 095 } else { 096 // all other properties 097 for (RDFResourceTree child : tree.getChildren(edge)) { 098 RDFResourceTree newChild = apply(child); 099 newTree.addChild(newChild, edge); 100 } 101 } 102 } 103 104 // we have to run the subsumption check one more time to prune the tree 105 QueryTreeUtils.prune(newTree, null, Entailment.RDFS); 106 return newTree; 107 } 108}