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.pattern; 020 021import org.semanticweb.owlapi.model.*; 022import org.semanticweb.owlapi.vocab.OWLFacet; 023import uk.ac.manchester.cs.owl.owlapi.OWLClassImpl; 024import uk.ac.manchester.cs.owl.owlapi.OWLDatatypeImpl; 025import uk.ac.manchester.cs.owl.owlapi.OWLNamedIndividualImpl; 026 027import javax.annotation.Nonnull; 028import java.util.*; 029import java.util.concurrent.atomic.AtomicInteger; 030import java.util.function.Function; 031import java.util.stream.Collectors; 032 033public class OWLClassExpressionRenamer implements OWLClassExpressionVisitor, OWLPropertyExpressionVisitor, OWLIndividualVisitor, OWLDataRangeVisitor, OWLDataVisitor { 034 035 private static final String NS = "http://dl-learner.org/pattern/"; 036 037 /* 038 Some constants here used for abstraction 039 */ 040 041 private static final int MIN_INTEGER_VALUE = 0; 042 private static final int MAX_INTEGER_VALUE = 9; 043 private static final double MIN_DOUBLE_VALUE = 0d; 044 private static final double MAX_DOUBLE_VALUE = 9d; 045 private static final float MIN_FLOAT_VALUE = 0f; 046 private static final float MAX_FLOAT_VALUE = 9f; 047 048 049 private OWLDataFactory df; 050 private Map<OWLEntity, OWLEntity> renaming; 051 private OWLObject renamedOWLObject; 052// private OWLClassExpressionOrderingComparator comparator = new OWLClassExpressionOrderingComparator(); 053 private OWLObjectComparator comparator = new OWLObjectComparator(); 054 private Queue<String> classVarQueue = new LinkedList<>(); 055 private Queue<String> propertyVarQueue = new LinkedList<>(); 056 private Queue<String> individualVarQueue = new LinkedList<>(); 057 058 private OWLLiteralRenamer literalRenamer; 059 060 private boolean normalizeCardinalities = true; 061 private boolean normalizeHasValue = true; 062 private boolean normalizeOneOf = true; 063 064 private AtomicInteger clsCounter = new AtomicInteger(1); 065 066 private boolean multipleClasses = false; 067 068 069 public OWLClassExpressionRenamer(OWLDataFactory df, Map<OWLEntity, OWLEntity> renaming) { 070 this.df = df; 071 this.renaming = renaming; 072 073 literalRenamer = new OWLLiteralRenamer(df); 074 075 reset(); 076 } 077 078 public void reset() { 079 classVarQueue = new LinkedList<>(); 080 propertyVarQueue = new LinkedList<>(); 081 individualVarQueue = new LinkedList<>(); 082 083 for(int i = 65; i <= 90; i++){ 084 classVarQueue.add(String.valueOf((char)i)); 085 } 086 for(int j = 2; j <=5; j++){ 087 for(int i = 65; i <= 90; i++){ 088 classVarQueue.add(String.valueOf((char)i) + "_" + j); 089 } 090 } 091 for(int i = 97; i <= 111; i++){ 092 individualVarQueue.add(String.valueOf((char)i)); 093 } 094 for(int i = 112; i <= 122; i++){ 095 propertyVarQueue.add(String.valueOf((char)i)); 096 } 097 } 098 099 public void setMultipleClasses(boolean multipleClasses) { 100 this.multipleClasses = multipleClasses; 101 } 102 103 public OWLClassExpression rename(OWLClassExpression expr){ 104 renamedOWLObject = null; 105 expr.accept(this); 106 return (OWLClassExpression) renamedOWLObject; 107 } 108 109 @SuppressWarnings("unchecked") 110 public <T extends OWLPropertyExpression> T rename(T expr){ 111 renamedOWLObject = null; 112 expr.accept(this); 113 return (T) renamedOWLObject; 114 } 115 116 public OWLIndividual rename(OWLIndividual ind){ 117 renamedOWLObject = null; 118 ind.accept(this); 119 return (OWLIndividual) renamedOWLObject; 120 } 121 122 public OWLDataRange rename(OWLDataRange range){ 123 renamedOWLObject = null; 124 range.accept(this); 125 return (OWLDataRange) renamedOWLObject; 126 } 127 128 public OWLLiteral rename(OWLLiteral lit){ 129 renamedOWLObject = null; 130 renamedOWLObject = literalRenamer.rename(lit); 131 return (OWLLiteral) renamedOWLObject; 132 } 133 134 @Override 135 public void visit(OWLObjectIntersectionOf desc) { 136 List<OWLClassExpression> operands = desc.getOperandsAsList(); 137// Collections.sort(operands, comparator); 138 Set<OWLClassExpression> renamedOperands = new HashSet<>();//new TreeSet<>(comparator); 139 for(OWLClassExpression expr : operands){ 140 renamedOperands.add(rename(expr)); 141 } 142 renamedOWLObject = df.getOWLObjectIntersectionOf(renamedOperands); 143 } 144 145 @Override 146 public void visit(OWLObjectUnionOf desc) { 147 List<OWLClassExpression> operands = desc.getOperandsAsList(); 148 Collections.sort(operands, comparator); 149 SortedSet<OWLClassExpression> renamedOperands = new TreeSet<>(comparator); 150 for(OWLClassExpression expr : operands){ 151 renamedOperands.add(rename(expr)); 152 } 153 renamedOWLObject = df.getOWLObjectUnionOf(renamedOperands); 154 } 155 156 @Override 157 public void visit(OWLDataHasValue desc) { 158 OWLDataPropertyExpression property = desc.getProperty(); 159 property = rename(property); 160 OWLLiteral value = desc.getFiller(); 161 value = rename(value); 162 renamedOWLObject = df.getOWLDataHasValue(property, value); 163 } 164 165 @Override 166 public void visit(OWLObjectComplementOf desc) { 167 OWLClassExpression operand = desc.getOperand(); 168 operand = rename(operand); 169 renamedOWLObject = df.getOWLObjectComplementOf(operand); 170 } 171 172 @Override 173 public void visit(OWLObjectSomeValuesFrom desc) { 174 OWLObjectPropertyExpression property = desc.getProperty(); 175 property = rename(property); 176 OWLClassExpression filler = desc.getFiller(); 177 filler = rename(filler); 178 renamedOWLObject = df.getOWLObjectSomeValuesFrom(property, filler); 179 } 180 181 @Override 182 public void visit(OWLObjectAllValuesFrom desc) { 183 OWLObjectPropertyExpression property = desc.getProperty(); 184 property = rename(property); 185 OWLClassExpression filler = desc.getFiller(); 186 filler = rename(filler); 187 renamedOWLObject = df.getOWLObjectAllValuesFrom(property, filler); 188 } 189 190 @Override 191 public void visit(OWLObjectHasValue desc) { 192 OWLObjectPropertyExpression property = desc.getProperty(); 193 property = rename(property); 194 OWLIndividual value = desc.getFiller(); 195 value = rename(value); 196 renamedOWLObject = df.getOWLObjectHasValue(property, value); 197 } 198 199 @Override 200 public void visit(OWLObjectMinCardinality desc) { 201 OWLObjectPropertyExpression property = desc.getProperty(); 202 property = rename(property); 203 OWLClassExpression filler = desc.getFiller(); 204 filler = rename(filler); 205 int cardinality = desc.getCardinality(); 206 if(normalizeCardinalities){ 207 cardinality = 1; 208 } 209 renamedOWLObject = df.getOWLObjectMinCardinality(cardinality, property, filler); 210 } 211 212 @Override 213 public void visit(OWLObjectExactCardinality desc) { 214 OWLObjectPropertyExpression property = desc.getProperty(); 215 property = rename(property); 216 OWLClassExpression filler = desc.getFiller(); 217 filler = rename(filler); 218 int cardinality = desc.getCardinality(); 219 if(normalizeCardinalities){ 220 cardinality = 1; 221 } 222 renamedOWLObject = df.getOWLObjectExactCardinality(cardinality, property, filler); 223 } 224 225 @Override 226 public void visit(OWLObjectMaxCardinality desc) { 227 OWLObjectPropertyExpression property = desc.getProperty(); 228 property = rename(property); 229 OWLClassExpression filler = desc.getFiller(); 230 filler = rename(filler); 231 int cardinality = desc.getCardinality(); 232 if(normalizeCardinalities){ 233 cardinality = 1; 234 } 235 renamedOWLObject = df.getOWLObjectMaxCardinality(cardinality, property, filler); 236 } 237 238 @Override 239 public void visit(OWLObjectHasSelf desc) { 240 OWLObjectPropertyExpression property = desc.getProperty(); 241 property = rename(property); 242 renamedOWLObject = df.getOWLObjectHasSelf(property); 243 } 244 245 @Override 246 public void visit(OWLObjectOneOf desc) { 247 Set<OWLIndividual> individuals = desc.getIndividuals(); 248 Set<OWLIndividual> renamedIndividuals = new TreeSet<>(); 249 for (OWLIndividual ind : individuals) { 250 renamedIndividuals.add(rename(ind)); 251 } 252 renamedOWLObject = df.getOWLObjectOneOf(renamedIndividuals); 253 } 254 255 @Override 256 public void visit(OWLDataSomeValuesFrom desc) { 257 OWLDataPropertyExpression property = desc.getProperty(); 258 property = rename(property); 259 OWLDataRange filler = desc.getFiller(); 260 filler = rename(filler); 261 renamedOWLObject = df.getOWLDataSomeValuesFrom(property, filler); 262 } 263 264 @Override 265 public void visit(OWLDataAllValuesFrom desc) { 266 OWLDataPropertyExpression property = desc.getProperty(); 267 property = rename(property); 268 OWLDataRange filler = desc.getFiller(); 269 filler = rename(filler); 270 renamedOWLObject = df.getOWLDataAllValuesFrom(property, filler); 271 } 272 273 @Override 274 public void visit(OWLDataMinCardinality desc) { 275 OWLDataPropertyExpression property = desc.getProperty(); 276 property = rename(property); 277 OWLDataRange filler = desc.getFiller(); 278 filler = rename(filler); 279 int cardinality = desc.getCardinality(); 280 if(normalizeCardinalities){ 281 cardinality = 1; 282 } 283 renamedOWLObject = df.getOWLDataMinCardinality(cardinality, property, filler); 284 } 285 286 @Override 287 public void visit(OWLDataExactCardinality desc) { 288 OWLDataPropertyExpression property = desc.getProperty(); 289 property = rename(property); 290 OWLDataRange filler = desc.getFiller(); 291 filler = rename(filler); 292 int cardinality = desc.getCardinality(); 293 if(normalizeCardinalities){ 294 cardinality = 1; 295 } 296 renamedOWLObject = df.getOWLDataExactCardinality(cardinality, property, filler); 297 } 298 299 @Override 300 public void visit(OWLDataMaxCardinality desc) { 301 OWLDataPropertyExpression property = desc.getProperty(); 302 property = rename(property); 303 OWLDataRange filler = desc.getFiller(); 304 filler = rename(filler); 305 int cardinality = desc.getCardinality(); 306 if(normalizeCardinalities){ 307 cardinality = 1; 308 } 309 renamedOWLObject = df.getOWLDataMaxCardinality(cardinality, property, filler); 310 } 311 312 @Override 313 public void visit(OWLObjectInverseOf desc) { 314 OWLObjectPropertyExpression inverse = desc.getInverse(); 315 inverse = rename(inverse); 316 renamedOWLObject = df.getOWLObjectInverseOf(inverse); 317 } 318 319 Function<OWLEntity, OWLEntity> classRenamingFn = k -> df.getOWLClass(getIRI("A_" + clsCounter.getAndIncrement())); 320 321 public void setClassRenamingFn(Function<OWLEntity, OWLEntity> classRenamingFn) { 322 this.classRenamingFn = classRenamingFn; 323 } 324 325 @Override 326 public void visit(OWLClass desc) { 327 if(desc.isTopEntity()){ 328 renamedOWLObject = desc; 329 } else { 330// OWLEntity newEntity = renaming.computeIfAbsent(desc, k -> df.getOWLClass(getIRI(classVarQueue.poll()))); 331 OWLEntity newEntity = renaming.computeIfAbsent(desc, classRenamingFn); 332 renamedOWLObject = newEntity; 333 334 } 335 } 336 337 @Override 338 public void visit(OWLObjectProperty op) { 339 if(op.isTopEntity()){ 340 renamedOWLObject = op; 341 } else { 342 OWLEntity newEntity = renaming.computeIfAbsent(op, k -> df.getOWLObjectProperty( 343 getIRI(propertyVarQueue.poll()))); 344 renamedOWLObject = newEntity; 345 } 346 } 347 348 @Override 349 public void visit(OWLDataProperty dp) { 350 if(dp.isTopEntity()){ 351 renamedOWLObject = dp; 352 } else { 353 OWLEntity newEntity = renaming.computeIfAbsent(dp, 354 k -> df.getOWLDataProperty(getIRI(propertyVarQueue.poll()))); 355 renamedOWLObject = newEntity; 356 } 357 } 358 359 @Override 360 public void visit(@Nonnull OWLAnnotationProperty property) { 361 362 } 363 364 @Override 365 public void visit(OWLNamedIndividual ind) { 366 OWLEntity newEntity = renaming.computeIfAbsent(ind, k -> df.getOWLNamedIndividual( 367 getIRI(individualVarQueue.poll()))); 368 renamedOWLObject = newEntity; 369 } 370 371 private IRI getIRI(String var){ 372 return IRI.create(NS + var); 373 } 374 375 @Override 376 public void visit(OWLAnonymousIndividual ind) { 377 OWLEntity newEntity = renaming.get(ind); 378 if(newEntity == null){ 379 newEntity = df.getOWLNamedIndividual(getIRI(individualVarQueue.poll())); 380// renaming.put(ind, newEntity); 381 } 382 renamedOWLObject = newEntity; 383 } 384 385 @Override 386 public void visit(OWLDatatype dt) { 387 if(dt.isBuiltIn()) { 388 renamedOWLObject = dt; 389 } else { 390 renamedOWLObject = PatternConstants.USER_DEFINED_DATATYPE; 391 } 392 } 393 394 @Override 395 public void visit(OWLDataOneOf desc) { 396 Set<OWLLiteral> literals = desc.getValues(); 397 Set<OWLLiteral> renamedLiterals = new TreeSet<>(); 398 for (OWLLiteral lit : literals) { 399 renamedLiterals.add(rename(lit)); 400 } 401 renamedOWLObject = df.getOWLDataOneOf(renamedLiterals); 402 } 403 404 @Override 405 public void visit(OWLDataComplementOf desc) { 406 OWLDataRange dataRange = desc.getDataRange(); 407 dataRange = rename(dataRange); 408 renamedOWLObject = df.getOWLDataComplementOf(dataRange); 409 } 410 411 @Override 412 public void visit(OWLDataIntersectionOf desc) { 413 List<OWLDataRange> operands = new ArrayList<>(desc.getOperands()); 414 Collections.sort(operands, comparator); 415 SortedSet<OWLDataRange> renamedOperands = new TreeSet<>(comparator); 416 for(OWLDataRange expr : operands){ 417 renamedOperands.add(rename(expr)); 418 } 419 renamedOWLObject = df.getOWLDataIntersectionOf(renamedOperands); 420 } 421 422 @Override 423 public void visit(OWLDataUnionOf desc) { 424 List<OWLDataRange> operands = new ArrayList<>(desc.getOperands()); 425 Collections.sort(operands, comparator); 426 SortedSet<OWLDataRange> renamedOperands = new TreeSet<>(comparator); 427 for(OWLDataRange expr : operands){ 428 renamedOperands.add(rename(expr)); 429 } 430 renamedOWLObject = df.getOWLDataUnionOf(renamedOperands); 431 } 432 433 @Override 434 public void visit(OWLDatatypeRestriction desc) { 435 OWLDatatype datatype = desc.getDatatype(); 436 Set<OWLFacetRestriction> facetRestrictions = desc.getFacetRestrictions(); 437 Set<OWLFacetRestriction> newFacets = facetRestrictions.stream() 438 .map(facetRestriction -> normalize(facetRestriction)) 439 .sorted() 440 .collect(Collectors.toSet()); 441 renamedOWLObject = df.getOWLDatatypeRestriction(datatype, newFacets);; 442 } 443 444 private OWLFacetRestriction normalize(OWLFacetRestriction fr) { 445 OWLFacet facet = fr.getFacet(); 446 447 OWLLiteral value = fr.getFacetValue(); 448 449 return df.getOWLFacetRestriction(facet, normalize(value, facet)); 450 } 451 452 private OWLLiteral normalize(OWLLiteral lit, OWLFacet facet) { 453 OWLDatatype datatype = lit.getDatatype(); 454 OWLLiteral newLit = lit; 455 if(datatype.isBuiltIn()) { 456 switch(facet) { 457 case MIN_INCLUSIVE: 458 case MIN_EXCLUSIVE: 459 if(datatype.isDouble()) { 460 newLit = df.getOWLLiteral(MIN_DOUBLE_VALUE); 461 } else if(datatype.isInteger()) { 462 newLit = df.getOWLLiteral(MIN_INTEGER_VALUE); 463 } else if(datatype.isFloat()) { 464 newLit = df.getOWLLiteral(MIN_FLOAT_VALUE); 465 } 466 break; 467 case MAX_INCLUSIVE: 468 case MAX_EXCLUSIVE: 469 if(datatype.isDouble()) { 470 newLit = df.getOWLLiteral(MAX_DOUBLE_VALUE); 471 } else if(datatype.isInteger()) { 472 newLit = df.getOWLLiteral(MAX_INTEGER_VALUE); 473 } else if(datatype.isFloat()) { 474 newLit = df.getOWLLiteral(MAX_FLOAT_VALUE); 475 } 476 break; 477 default: 478 } 479 480 } 481 return newLit; 482 } 483 484 @Override 485 public void visit(@Nonnull OWLLiteral node) { 486 487 } 488 489 @Override 490 public void visit(@Nonnull OWLFacetRestriction node) { 491 492 } 493}