From e524ca752c25480390d9e3f57ac2c4ec35b31b29 Mon Sep 17 00:00:00 2001 From: Eduard Marbach Date: Sun, 25 Feb 2018 15:55:19 +0100 Subject: [PATCH] Set Domain/Range of inverse properties to same as the inverse. Fixes #33 --- .../converter/InputStreamConverter.java | 2 +- .../parser/owlapi/EntityCreationVisitor.java | 17 ++++- .../vowl/classes/OwlClassAxiomVisitor.java | 2 +- .../vowl/property/DomainRangeFiller.java | 63 +++++++++++++------ .../vis/vowl/owl2vowl/CompleteTestSuite.java | 3 +- .../vis/vowl/owl2vowl/Constants.java | 12 ++++ .../vis/vowl/owl2vowl/PropertyTest.java | 27 ++++++++ .../vis/vowl/owl2vowl/TestConverter.java | 19 ++++++ src/test/resources/inverse-anonym-test.ttl | 28 +++++++++ src/test/resources/log4j2.xml | 37 +++++++++++ 10 files changed, 186 insertions(+), 24 deletions(-) create mode 100644 src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/Constants.java create mode 100644 src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/PropertyTest.java create mode 100644 src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/TestConverter.java create mode 100644 src/test/resources/inverse-anonym-test.ttl create mode 100644 src/test/resources/log4j2.xml diff --git a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/converter/InputStreamConverter.java b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/converter/InputStreamConverter.java index 4d3fa6e..f9f9306 100644 --- a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/converter/InputStreamConverter.java +++ b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/converter/InputStreamConverter.java @@ -18,7 +18,7 @@ public class InputStreamConverter extends AbstractConverter { private static final Logger logger = LogManager.getLogger(InputStreamConverter.class); public InputStreamConverter(InputStream ontology) { - this(ontology, Collections.emptyList()); + this(ontology, Collections.emptyList()); } public InputStreamConverter(InputStream ontology, Collection necessaryExternals) { diff --git a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/owlapi/EntityCreationVisitor.java b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/owlapi/EntityCreationVisitor.java index bb3462c..8a1d8af 100644 --- a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/owlapi/EntityCreationVisitor.java +++ b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/owlapi/EntityCreationVisitor.java @@ -7,11 +7,19 @@ import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.nodes.datatypes.VowlLiteral; import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.properties.VowlDatatypeProperty; import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.properties.VowlObjectProperty; -import org.semanticweb.owlapi.model.*; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.semanticweb.owlapi.model.OWLClass; +import org.semanticweb.owlapi.model.OWLDataProperty; +import org.semanticweb.owlapi.model.OWLDatatype; +import org.semanticweb.owlapi.model.OWLLiteral; +import org.semanticweb.owlapi.model.OWLObjectProperty; +import org.semanticweb.owlapi.model.OWLObjectVisitor; public class EntityCreationVisitor implements OWLObjectVisitor { private VowlData vowlData; + private Logger logger = LogManager.getLogger(EntityCreationVisitor.class); public EntityCreationVisitor(VowlData vowlData) { this.vowlData = vowlData; @@ -28,6 +36,7 @@ public void visit(OWLClass ce) { clazz = new VowlClass(ce.getIRI()); } else { // TODO Anonymous behaviour undefined + logger.info("Anonymous OWLClass " + ce); return; } @@ -52,10 +61,11 @@ public void visit(OWLDatatype node) { public void visit(OWLObjectProperty property) { VowlObjectProperty prop; - if(!property.isAnonymous()) { + if (!property.isAnonymous()) { prop = new VowlObjectProperty(property.getIRI()); } else { // TODO anonymous behaviour + logger.info("Anonymous OWLObjectProperty " + property); return; } @@ -66,10 +76,11 @@ public void visit(OWLObjectProperty property) { public void visit(OWLDataProperty property) { VowlDatatypeProperty prop; - if(!property.isAnonymous()) { + if (!property.isAnonymous()) { prop = new VowlDatatypeProperty(property.getIRI()); } else { // TODO anonymous behaviour + logger.info("Anonymous OWLDataProperty " + property); return; } diff --git a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/classes/OwlClassAxiomVisitor.java b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/classes/OwlClassAxiomVisitor.java index 9008468..8ceef47 100644 --- a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/classes/OwlClassAxiomVisitor.java +++ b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/classes/OwlClassAxiomVisitor.java @@ -285,7 +285,7 @@ public void visit(OWLObjectIntersectionOf ce) { node.addAttribute(VowlAttribute.INTERSECTION); } else { // TODO Anonymous undefined behaviour - logger.info("Anonymous exists in intersections."); + logger.info("Anonymous exists in intersections. " + operand); } } } diff --git a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/property/DomainRangeFiller.java b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/property/DomainRangeFiller.java index d6bda8d..2b3450c 100644 --- a/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/property/DomainRangeFiller.java +++ b/src/main/java/de/uni_stuttgart/vis/vowl/owl2vowl/parser/vowl/property/DomainRangeFiller.java @@ -10,16 +10,15 @@ import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.properties.VowlDatatypeProperty; import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.properties.VowlObjectProperty; import de.uni_stuttgart.vis.vowl.owl2vowl.model.visitor.VowlPropertyVisitor; - +import java.util.Collection; +import java.util.Set; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.semanticweb.owlapi.model.IRI; -import java.util.Collection; -import java.util.Set; - /** * Class which is responsible to fill the Domain/Range of properties regarding the VOWL specification. + * * @author Eduard */ public class DomainRangeFiller implements VowlPropertyVisitor { @@ -37,23 +36,28 @@ public DomainRangeFiller(VowlData vowlData, Collection { - if (element instanceof HasReference) { - //Ignore references cause they do not need generated Domain/Range - return; - } - try { - element.accept(this); - } catch (Exception e){ - logger.info(" DomainRange Filler faild to accept element"); - logger.info(" Element: "+element); - logger.info(" Reason: "+e); - logger.info(" SKIPPING THIS ELEMENT *****"); - } - }); + values.stream() + // Only process props which have empty domain/range + .filter(property -> property.getDomains().isEmpty() || property.getRanges().isEmpty()) + // skip inverse properties + .filter(property -> property.getInverse() == null) + .forEach(this::processProperty); + } + + private void processProperty(AbstractProperty property) { + if (property instanceof HasReference) { + //Ignore references cause they do not need generated Domain/Range + return; + } + try { + property.accept(this); + } catch (Exception e) { + logger.error("Exception during processing property: " + e + " with message: " + e.getMessage() + " | Skip"); + } } private VowlThing searchForConnectedThing(Set value) { @@ -79,6 +83,29 @@ private void mergeMulti() { } } + private void processInverseProperties() { + values.stream() + .filter(property -> property.getInverse() != null) + .filter(property -> property.getDomains().isEmpty() || property.getRanges().isEmpty()) + .peek(this::fillWithInverse) + .filter(property -> property.getDomains().isEmpty() || property.getRanges().isEmpty()) + .forEach(this::processProperty); + } + + private void fillWithInverse(AbstractProperty property) { + AbstractProperty inverse = vowlData.getPropertyForIri(property.getInverse()); + + if (property.getDomains().isEmpty() && inverse.getJsonRange() != null) { + property.getDomains().add(inverse.getJsonRange()); + logger.debug("Filled inverse property domain " + property + " with " + inverse.getJsonRange()); + } + + if (property.getRanges().isEmpty() && inverse.getJsonDomain() != null) { + property.getRanges().add(inverse.getJsonDomain()); + logger.debug("Filled inverse property range " + property + " with " + inverse.getJsonDomain()); + } + } + @Override public void visit(VowlObjectProperty vowlObjectProperty) { classBehaviour(vowlObjectProperty); diff --git a/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/CompleteTestSuite.java b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/CompleteTestSuite.java index b6e1104..50c46ba 100644 --- a/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/CompleteTestSuite.java +++ b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/CompleteTestSuite.java @@ -7,9 +7,10 @@ @RunWith(Suite.class) @Suite.SuiteClasses({ + ComparisonHelperTest.class, ConsoleMainTest.class, OntobenchTest.class, - ComparisonHelperTest.class + PropertyTest.class }) public class CompleteTestSuite extends TestSuite { diff --git a/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/Constants.java b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/Constants.java new file mode 100644 index 0000000..757dfb2 --- /dev/null +++ b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/Constants.java @@ -0,0 +1,12 @@ +package de.uni_stuttgart.vis.vowl.owl2vowl; + +import org.semanticweb.owlapi.model.IRI; + +public class Constants { + + public static final String OWL2VOWL_NAMESPACE = "https://owl2vowl.de/"; + + public static IRI getIRIWithTestNamespace(String entityIRI) { + return IRI.create(OWL2VOWL_NAMESPACE + entityIRI); + } +} diff --git a/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/PropertyTest.java b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/PropertyTest.java new file mode 100644 index 0000000..00b103a --- /dev/null +++ b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/PropertyTest.java @@ -0,0 +1,27 @@ +package de.uni_stuttgart.vis.vowl.owl2vowl; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import de.uni_stuttgart.vis.vowl.owl2vowl.model.data.VowlData; +import de.uni_stuttgart.vis.vowl.owl2vowl.model.entities.properties.AbstractProperty; +import org.junit.Test; + + +public class PropertyTest { + + @Test + public void shouldProcessAnonymousInverseRelationCorrectly() { + TestConverter converter = new TestConverter(getClass().getResourceAsStream("/inverse-anonym-test.ttl")); + VowlData data = converter.getConvertedData(); + + AbstractProperty propertyA = data.getPropertyForIri(Constants.getIRIWithTestNamespace("propertyA")); + AbstractProperty propertyB = data.getPropertyForIri(Constants.getIRIWithTestNamespace("propertyB")); + + assertThat(propertyA.getJsonDomain(), is(Constants.getIRIWithTestNamespace("classA"))); + assertThat(propertyA.getJsonRange(), is(Constants.getIRIWithTestNamespace("classB"))); + + assertThat(propertyB.getJsonDomain(), is(Constants.getIRIWithTestNamespace("classB"))); + assertThat(propertyB.getJsonRange(), is(Constants.getIRIWithTestNamespace("classA"))); + } +} diff --git a/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/TestConverter.java b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/TestConverter.java new file mode 100644 index 0000000..6ec7d80 --- /dev/null +++ b/src/test/java/de/uni_stuttgart/vis/vowl/owl2vowl/TestConverter.java @@ -0,0 +1,19 @@ +package de.uni_stuttgart.vis.vowl.owl2vowl; + +import de.uni_stuttgart.vis.vowl.owl2vowl.converter.InputStreamConverter; +import de.uni_stuttgart.vis.vowl.owl2vowl.model.data.VowlData; +import java.io.InputStream; + +public class TestConverter extends InputStreamConverter { + + public TestConverter(InputStream ontology) { + super(ontology); + } + + public VowlData getConvertedData() { + if (!this.initialized) { + this.convert(); + } + return this.vowlData; + } +} diff --git a/src/test/resources/inverse-anonym-test.ttl b/src/test/resources/inverse-anonym-test.ttl new file mode 100644 index 0000000..b9afc1a --- /dev/null +++ b/src/test/resources/inverse-anonym-test.ttl @@ -0,0 +1,28 @@ +#################################PREFIXES################################ + +@prefix : . +@prefix this: . +@prefix dcterms: . +@prefix owl: . +@prefix rdf: . +@prefix rdfs: . +@prefix schema: . +@prefix xsd: . + +#################################ONTOLOGY################################# + +this:schema + a owl:Ontology ; + dcterms:title "OWL2VOWL Testing" ; +. + +#################################ENTITIES################################## + +:propertyA + a owl:ObjectProperty ; + rdfs:domain :classA ; + rdfs:range :classB ; +. +:propertyB + owl:inverseOf :propertyA ; +. diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml new file mode 100644 index 0000000..51e2aaf --- /dev/null +++ b/src/test/resources/log4j2.xml @@ -0,0 +1,37 @@ + + + + ???? + %xwEx + %5p + %clr{%d{yyyy-MM-dd HH:mm:ss.SSS}}{faint} %clr{${LOG_LEVEL_PATTERN}} %clr{${sys:PID}}{magenta} %clr{---}{faint} + %clr{[%15.15t]}{faint} %clr{%-40.40c{1.}}{cyan} %clr{:}{faint} %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD} + + %d{yyyy-MM-dd HH:mm:ss.SSS} ${LOG_LEVEL_PATTERN} ${sys:PID} --- [%t] %-40.40c{1.} : + %m%n${sys:LOG_EXCEPTION_CONVERSION_WORD} + + + + + + + + + + + + + + + + + + + + + + + + + +