/*
* Copyright 2011 JBoss Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.drools.semantics.builder.model.inference;
//import com.clarkparsia.pellet.owlapiv3.PelletReasonerFactory;
import org.apache.commons.collections15.map.MultiKeyMap;
import org.apache.log4j.Logger;
import org.drools.io.Resource;
import org.drools.runtime.ClassObjectFilter;
import org.drools.runtime.StatefulKnowledgeSession;
import org.drools.semantics.builder.DLFactoryConfiguration;
import org.drools.semantics.builder.model.Concept;
import org.drools.semantics.builder.model.Individual;
import org.drools.semantics.builder.model.OntoModel;
import org.drools.semantics.builder.model.PropertyRelation;
import org.drools.semantics.builder.model.SubConceptOf;
import org.drools.semantics.utils.NameUtils;
import org.drools.semantics.utils.NamespaceUtils;
import org.drools.util.HierarchySorter;
import org.semanticweb.HermiT.Reasoner;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.AxiomType;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotation;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLCardinalityRestriction;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLClassExpressionVisitor;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
import org.semanticweb.owlapi.model.OWLDataExactCardinality;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLDataHasValue;
import org.semanticweb.owlapi.model.OWLDataMaxCardinality;
import org.semanticweb.owlapi.model.OWLDataMinCardinality;
import org.semanticweb.owlapi.model.OWLDataOneOf;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLDataPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyExpression;
import org.semanticweb.owlapi.model.OWLDataPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLDataSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLEntity;
import org.semanticweb.owlapi.model.OWLEquivalentClassesAxiom;
import org.semanticweb.owlapi.model.OWLHasKeyAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLInverseObjectPropertiesAxiom;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLNaryBooleanClassExpression;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectCardinalityRestriction;
import org.semanticweb.owlapi.model.OWLObjectComplementOf;
import org.semanticweb.owlapi.model.OWLObjectExactCardinality;
import org.semanticweb.owlapi.model.OWLObjectHasSelf;
import org.semanticweb.owlapi.model.OWLObjectHasValue;
import org.semanticweb.owlapi.model.OWLObjectIntersectionOf;
import org.semanticweb.owlapi.model.OWLObjectMaxCardinality;
import org.semanticweb.owlapi.model.OWLObjectMinCardinality;
import org.semanticweb.owlapi.model.OWLObjectOneOf;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyDomainAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLObjectPropertyRangeAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectUnionOf;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLProperty;
import org.semanticweb.owlapi.model.OWLQuantifiedDataRestriction;
import org.semanticweb.owlapi.model.OWLQuantifiedObjectRestriction;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLSubPropertyChainOfAxiom;
import org.semanticweb.owlapi.model.RemoveAxiom;
import org.semanticweb.owlapi.reasoner.ConsoleProgressMonitor;
import org.semanticweb.owlapi.reasoner.InferenceType;
import org.semanticweb.owlapi.reasoner.OWLReasoner;
import org.semanticweb.owlapi.reasoner.OWLReasonerConfiguration;
import org.semanticweb.owlapi.reasoner.OWLReasonerFactory;
import org.semanticweb.owlapi.reasoner.SimpleConfiguration;
import org.semanticweb.owlapi.util.InferredAxiomGenerator;
import org.semanticweb.owlapi.util.InferredOntologyGenerator;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class DelegateInferenceStrategy extends AbstractModelInferenceStrategy {
private static Logger logger = Logger.getLogger( DelegateInferenceStrategy.class );
private int counter = 0;
public int minCounter = 0;
public int maxCounter = 0;
private Map<OWLClassExpression,OWLClassExpression> aliases;
private Map<OWLClassExpression,Set<OWLClassExpression>> reverseAliases = new HashMap<OWLClassExpression, Set<OWLClassExpression>>();
private Map<OWLClassExpression,OWLClass> anonNameAliases = new HashMap<OWLClassExpression, OWLClass>();
private Map<String, Concept> conceptCache = new LinkedHashMap<String, Concept>();
private Map<String, String> individualTypesCache = new HashMap<String, String>();
private Map<OWLClassExpression, OWLClass> fillerCache = new HashMap<OWLClassExpression, OWLClass>();
private Map<String, String> props = new HashMap<String, String>();
private MultiKeyMap minCards = new MultiKeyMap();
private MultiKeyMap maxCards = new MultiKeyMap();
private static void register( String prim, String klass ) {
IRI i1 = IRI.create( prim );
Concept con = new Concept( i1, klass, true );
primitives.put( i1.toQuotedString(), con );
}
private static Map<String, Concept> primitives = new HashMap<String, Concept>();
{
register( "http://www.w3.org/2001/XMLSchema#string", "xsd:string" );
register( "http://www.w3.org/2001/XMLSchema#dateTime", "xsd:dateTime" );
register( "http://www.w3.org/2001/XMLSchema#date", "xsd:date" );
register( "http://www.w3.org/2001/XMLSchema#time", "xsd:time" );
register( "http://www.w3.org/2001/XMLSchema#int", "xsd:int" );
register( "http://www.w3.org/2001/XMLSchema#integer", "xsd:integer" );
register( "http://www.w3.org/2001/XMLSchema#long", "xsd:long" );
register( "http://www.w3.org/2001/XMLSchema#float", "xsd:float" );
register( "http://www.w3.org/2001/XMLSchema#double", "xsd:double" );
register( "http://www.w3.org/2001/XMLSchema#short", "xsd:short" );
register( "http://www.w3.org/2000/01/rdf-schema#Literal", "xsd:anySimpleType" );
register( "http://www.w3.org/2000/01/rdf-schema#XMLLiteral", "xsd:anySimpleType" );
register( "http://www.w3.org/1999/02/22-rdf-syntax-ns#PlainLiteral", "xsd:anySimpleType" );
register( "http://www.w3.org/2001/XMLSchema#boolean", "xsd:boolean" );
register( "http://www.w3.org/2001/XMLSchema#decimal", "xsd:decimal" );
register( "http://www.w3.org/2001/XMLSchema#byte", "xsd:byte" );
register( "http://www.w3.org/2001/XMLSchema#unsignedByte", "xsd:unsignedByte" );
register( "http://www.w3.org/2001/XMLSchema#unsignedShort", "xsd:unsignedShort" );
register( "http://www.w3.org/2001/XMLSchema#unsignedInt", "xsd:unsignedInt" );
register( "http://www.w3.org/2001/XMLSchema#anyURI", "xsd:anyURI" );
}
@Override
protected OntoModel buildProperties( OWLOntology ontoDescr, StatefulKnowledgeSession kSession, Map<InferenceTask, Resource> theory, OntoModel hierarchicalModel, DLFactoryConfiguration conf ) {
OWLDataFactory factory = ontoDescr.getOWLOntologyManager().getOWLDataFactory();
fillPropNamesInDataStructs( ontoDescr );
// Complete missing domains and ranges for properties. Might be overridden later, if anything can be inferred
createAndAddBasicProperties( ontoDescr, factory, hierarchicalModel );
// Apply any cardinality / range restriction
applyPropertyRestrictions( ontoDescr, hierarchicalModel, factory );
// Compose property chains
fixPropertyChains( ontoDescr, hierarchicalModel );
// Manage inverse relations
fixInverseRelations( ontoDescr, hierarchicalModel );
// assign Key properties
setKeys( ontoDescr, hierarchicalModel );
fixRootHierarchy( hierarchicalModel );
validate( hierarchicalModel );
return hierarchicalModel;
}
@Override
protected OntoModel buildIndividuals(OWLOntology ontoDescr, StatefulKnowledgeSession kSession, Map<InferenceTask, Resource> theory, OntoModel hierachicalModel, DLFactoryConfiguration conf ) {
for ( OWLNamedIndividual individual : ontoDescr.getIndividualsInSignature( true ) ) {
if ( logger.isInfoEnabled() ) { logger.info( "Found Individual " + individual.getIRI() ); };
IRI iri = individual.getIRI();
String typeIri = individualTypesCache.get( iri.toQuotedString() );
Concept klass = hierachicalModel.getConcept( typeIri );
if ( klass == null ) {
logger.error( "found individual with no class " + iri );
System.exit( -1 );
}
Individual ind = new Individual( iri.getFragment(), iri.toQuotedString(), klass.getFullyQualifiedName() );
for ( OWLOntology onto : ontoDescr.getImportsClosure() ) {
for ( OWLDataPropertyExpression prop : individual.getDataPropertyValues( onto ).keySet() ) {
if ( ! prop.isTopEntity() ) {
PropertyRelation rel = hierachicalModel.getProperty( prop.asOWLDataProperty().getIRI().toQuotedString() );
String propName = rel.getName();
Set<OWLLiteral> propValues = individual.getDataPropertyValues( onto ).get( prop );
Set<Individual.ValueTypePair> values = new HashSet<Individual.ValueTypePair>();
for ( OWLLiteral tgt : propValues ) {
String value = null;
String typeName = rel.getTarget().getFullyQualifiedName();
//TODO improve datatype checking
if ( typeName.equals( "xsd:string" )
|| typeName.equals( "xsd:dateTime" ) ) {
value = "\"" + tgt.getLiteral() + "\"";
} else {
value = tgt.getLiteral();
}
Individual.ValueTypePair vtp = new Individual.ValueTypePair( value, typeName );
values.add( vtp );
}
ind.setPropertyValues( propName, values );
}
}
for ( OWLObjectPropertyExpression prop : individual.getObjectPropertyValues( onto ).keySet() ) {
if ( ! prop.isTopEntity() ) {
String propName = hierachicalModel.getProperty( prop.asOWLObjectProperty().getIRI().toQuotedString()).getName();
Set<OWLIndividual> propValues = individual.getObjectPropertyValues( onto ).get( prop );
Set<Individual.ValueTypePair> values = new HashSet<Individual.ValueTypePair>();
for ( OWLIndividual tgt : propValues ) {
if ( tgt instanceof OWLNamedIndividual ) {
values.add( new Individual.ValueTypePair(
((OWLNamedIndividual) tgt).getIRI().getFragment(),
"object" ) );
}
}
ind.setPropertyValues( propName, values );
}
}
}
hierachicalModel.addIndividual( ind );
}
return hierachicalModel;
}
private void fixInverseRelations( OWLOntology ontoDescr, OntoModel hierarchicalModel ) {
for ( OWLInverseObjectPropertiesAxiom ax : ontoDescr.getAxioms( AxiomType.INVERSE_OBJECT_PROPERTIES ) ) {
String fst = ax.getFirstProperty().asOWLObjectProperty().getIRI().toQuotedString();
if ( ! ax.getSecondProperty().isAnonymous() ) {
String sec = ax.getSecondProperty().asOWLObjectProperty().getIRI().toQuotedString();
PropertyRelation first = hierarchicalModel.getProperty( fst );
PropertyRelation second = hierarchicalModel.getProperty( sec );
if ( first != null && second != null ) {
if ( logger.isInfoEnabled() ) { logger.info( "Marking " + first + " as Inverse" ); };
first.setInverse( true );
}
}
}
}
private void setKeys( OWLOntology ontoDescr, OntoModel hierarchicalModel ) {
for ( OWLHasKeyAxiom hasKey : ontoDescr.getAxioms( AxiomType.HAS_KEY ) ) {
Concept con = conceptCache.get( hasKey.getClassExpression().asOWLClass().getIRI().toQuotedString() );
for ( OWLDataPropertyExpression expr : hasKey.getDataPropertyExpressions() ) {
String propIri = expr.asOWLDataProperty().getIRI().toQuotedString();
PropertyRelation keyRel = con.getProperties().get( propIri );
//con.addKey( keyRel.getName() );
con.addKey( propIri );
}
for ( OWLObjectPropertyExpression expr : hasKey.getObjectPropertyExpressions() ) {
String propIri = expr.asOWLObjectProperty().getIRI().toQuotedString();
PropertyRelation keyRel = con.getProperties().get( propIri );
// con.addKey( keyRel.getName() );
con.addKey( propIri );
}
}
}
private void fixPropertyChains( OWLOntology ontoDescr, OntoModel hierarchicalModel ) {
ontoDescr.getClassesInSignature( true );
for ( OWLSubPropertyChainOfAxiom ax : ontoDescr.getAxioms( AxiomType.SUB_PROPERTY_CHAIN_OF ) ) {
String propIri = ax.getSuperProperty().asOWLObjectProperty().getIRI().toQuotedString();
PropertyRelation prop = hierarchicalModel.getProperty( propIri );
List<PropertyRelation> chain = new ArrayList<PropertyRelation>();
for ( OWLObjectPropertyExpression link : ax.getPropertyChain() ) {
chain.add( hierarchicalModel.getProperty( link.asOWLObjectProperty().getIRI().toQuotedString() ) );
}
prop.addPropertyChain( chain );
}
}
private void applyPropertyRestrictions( OWLOntology ontoDescr, OntoModel hierarchicalModel, OWLDataFactory factory ) {
for ( PropertyRelation prop : hierarchicalModel.getProperties() ) {
if ( prop.getTarget() == null ) {
logger.warn( "Property without target concept " + prop.getName() );
}
}
Map<String, Set<OWLClassExpression>> supers = new HashMap<String, Set<OWLClassExpression>>();
for ( OWLClass klass : ontoDescr.getClassesInSignature( true ) ) {
supers.put( klass.getIRI().toQuotedString(), new HashSet<OWLClassExpression>() );
}
for ( OWLClass klass : ontoDescr.getClassesInSignature( true ) ) {
if ( isDelegating( klass ) ) {
OWLClassExpression delegate = aliases.get( klass );
supers.get( delegate.asOWLClass().getIRI().toQuotedString() ).addAll( klass.getSuperClasses( ontoDescr ) );
} else {
Set<OWLClassExpression> sup = supers.get( klass.asOWLClass().getIRI().toQuotedString() );
Set<OWLClassExpression> ancestors = klass.getSuperClasses( ontoDescr );
sup.addAll(ancestors);
for ( OWLClassExpression anc : ancestors ) {
if ( reverseAliases.containsKey( anc ) ) {
sup.addAll(reverseAliases.get(anc));
}
}
}
}
for ( Concept con : hierarchicalModel.getConcepts() ) { //use concepts as they're sorted!
if ( isDelegating( con.getIri() ) ) {
continue;
}
if ( con == null ) {
logger.warn( "Looking for superclasses of an undefined concept" );
continue;
}
LinkedList<OWLClassExpression> orderedSupers = new LinkedList<OWLClassExpression>();
// cardinalities should be fixed last
for ( OWLClassExpression sup : supers.get( con.getIri() ) ) {
if ( sup instanceof OWLCardinalityRestriction ) {
orderedSupers.addLast( sup );
} else {
orderedSupers.addFirst( sup );
}
}
for ( OWLClassExpression sup : orderedSupers ) {
if ( sup.isClassExpressionLiteral() ) {
continue;
}
processSuperClass( sup, con, hierarchicalModel, factory );
}
// for ( PropertyRelation prop : con.getProperties().values() ) {
// if ( prop.isRestricted() && ( prop.getMaxCard() == null || prop.getMaxCard() > 1 ) ) {
// prop.setName( prop.getName() + "s" );
// }
// }
}
}
private void processSuperClass( OWLClassExpression sup, Concept con, OntoModel hierarchicalModel, OWLDataFactory factory ) {
String propIri;
PropertyRelation rel;
Concept tgt;
switch ( sup.getClassExpressionType() ) {
case DATA_SOME_VALUES_FROM:
//check that it's a subclass of the domain. Should have already been done, or it would be an inconsistency
break;
case DATA_ALL_VALUES_FROM:
OWLDataAllValuesFrom forall = (OWLDataAllValuesFrom) sup;
propIri = forall.getProperty().asOWLDataProperty().getIRI().toQuotedString();
tgt = primitives.get( dataRangeToDataType( forall.getFiller(), factory ).getIRI().toQuotedString() );
if ( tgt.equals( "xsd:anySimpleType" ) ) {
break;
}
rel = extractProperty( con, propIri, tgt, null, null, true );
if ( rel != null ) {
// hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case DATA_MIN_CARDINALITY:
OWLDataMinCardinality min = (OWLDataMinCardinality) sup;
propIri = min.getProperty().asOWLDataProperty().getIRI().toQuotedString();
tgt = primitives.get( dataRangeToDataType( min.getFiller(), factory ).getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, min.getCardinality(), null, false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case DATA_MAX_CARDINALITY:
OWLDataMaxCardinality max = (OWLDataMaxCardinality) sup;
propIri = max.getProperty().asOWLDataProperty().getIRI().toQuotedString();
tgt = primitives.get( dataRangeToDataType( max.getFiller(), factory ).getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, null, max.getCardinality(), false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case DATA_EXACT_CARDINALITY:
OWLDataExactCardinality ex = (OWLDataExactCardinality) sup;
propIri = ex.getProperty().asOWLDataProperty().getIRI().toQuotedString();
tgt = primitives.get( dataRangeToDataType( ex.getFiller(), factory ).getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, ex.getCardinality(), ex.getCardinality(), false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_SOME_VALUES_FROM:
OWLObjectSomeValuesFrom someO = (OWLObjectSomeValuesFrom) sup;
propIri = someO.getProperty().asOWLObjectProperty().getIRI().toQuotedString();
if ( filterAliases( someO.getFiller() ).isAnonymous() ) {
logger.warn( ": Complex unaliased restriction " + someO );
break;
}
tgt = conceptCache.get( filterAliases( someO.getFiller() ).asOWLClass().getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, 1, null, false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_ALL_VALUES_FROM:
OWLObjectAllValuesFrom forallO = (OWLObjectAllValuesFrom) sup;
propIri = forallO.getProperty().asOWLObjectProperty().getIRI().toQuotedString();
if ( filterAliases( forallO.getFiller() ).isAnonymous() ) {
logger.warn( ": Complex unaliased restriction " + forallO );
break;
}
tgt = conceptCache.get( filterAliases( forallO.getFiller() ).asOWLClass().getIRI().toQuotedString() );
if ( tgt.equals( "<http://www.w3.org/2002/07/owl#Thing>" ) ) {
break;
}
rel = extractProperty( con, propIri, tgt, null, null, true );
if ( rel != null ) {
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_MIN_CARDINALITY:
OWLObjectMinCardinality minO = (OWLObjectMinCardinality) sup;
propIri = minO.getProperty().asOWLObjectProperty().getIRI().toQuotedString();
tgt = conceptCache.get( filterAliases( minO.getFiller() ).asOWLClass().getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, minO.getCardinality(), null, false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_MAX_CARDINALITY:
OWLObjectMaxCardinality maxO = (OWLObjectMaxCardinality) sup;
propIri = maxO.getProperty().asOWLObjectProperty().getIRI().toQuotedString();
tgt = conceptCache.get( filterAliases( maxO.getFiller() ).asOWLClass().getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, null, maxO.getCardinality(), false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_EXACT_CARDINALITY:
OWLObjectExactCardinality exO = (OWLObjectExactCardinality) sup;
propIri = exO.getProperty().asOWLObjectProperty().getIRI().toQuotedString();
tgt = conceptCache.get( filterAliases( exO.getFiller() ).asOWLClass().getIRI().toQuotedString() );
rel = extractProperty( con, propIri, tgt, exO.getCardinality(), exO.getCardinality(), false );
if ( rel != null ) {
hierarchicalModel.addProperty( rel );
} else {
logger.warn( " Could not find property " + propIri + " restricted in class " + con.getIri() );
}
break;
case OBJECT_INTERSECTION_OF:
OWLObjectIntersectionOf and = (OWLObjectIntersectionOf) sup;
for ( OWLClassExpression arg : and.asConjunctSet() ) {
processSuperClass( arg, con, hierarchicalModel, factory );
}
break;
case OWL_CLASS:
break;
default:
logger.warn( " Cannot handle " + sup );
}
}
private String createSuffix(String role, String name, boolean plural) {
String type = NameUtils.map( name, true );
if ( type.indexOf(".") >= 0 ) {
type = type.substring( type.lastIndexOf(".") + 1 );
}
return type + ( plural ? ( type.endsWith( "s" ) ? "es" : "s") : "" ); // + "As" + role;
}
private PropertyRelation extractProperty( Concept con, String propIri, Concept target, Integer min, Integer max, boolean restrictTarget ) {
if ( target == null ) {
logger.warn( "Null target for property " + propIri );
}
String restrictedSuffix = createSuffix( con.getName(), target.getName(), true );
String restrictedPropIri = propIri.replace( ">", restrictedSuffix + ">" );
// PropertyRelation rel = con.getProperties().get( propIri );
// if ( rel == null ) {
// rel = con.getProperties().get( restrictedPropIri );
// }
//
// if ( rel == null ) {
// rel = inheritPropertyCopy( con, con, propIri );
// inherited = true;
// }
boolean alreadyRestricted = false;
PropertyRelation rel = con.getProperties().get( propIri );
PropertyRelation originalProperty;
if ( rel != null ) {
originalProperty = rel;
rel = cloneRel( originalProperty );
} else {
rel = con.getProperties().get( restrictedPropIri );
if ( rel != null ) {
originalProperty = rel;
alreadyRestricted = true;
rel = cloneRel( originalProperty );
} else {
PropertyRelation source = inheritPropertyCopy( con, con, restrictedPropIri );
if ( source != null ) {
originalProperty = source;
alreadyRestricted = true;
rel = cloneRel( originalProperty );
} else {
originalProperty = inheritPropertyCopy( con, con, propIri );
rel = cloneRel( originalProperty );
}
}
}
if ( rel != null ) {
boolean tgtRestrictionApplied = restrictTarget && ! rel.getTarget().equals( target );
if ( tgtRestrictionApplied ) {
rel.restrictTargetTo( target );
}
boolean dirty = false;
if ( target.getIri().equals( "<http://www.w3.org/2002/07/owl#Thing>" )
|| target.getIri().equals("<http://www.w3.org/2000/01/rdf-schema#Literal>" )
|| target.getEquivalentConcepts().contains( conceptCache.get( "<http://www.w3.org/2002/07/owl#Thing>" ) )
) {
target = rel.getTarget();
restrictedSuffix = createSuffix( con.getName(), target.getName(), true );
restrictedPropIri = propIri.replace ( ">", restrictedSuffix + ">" );
// dirty = true;
}
if ( ! rel.getTarget().equals( target ) && ! restrictTarget ) {
//TODO FIXME : check that target is really restrictive!
if ( ! target.getIri().equals( "<http://www.w3.org/2002/07/owl#Thing>" )
&& ! target.getIri().equals("<http://www.w3.org/2000/01/rdf-schema#Literal>")
) {
rel.setTarget( target );
rel.setObject( target.getIri() );
dirty = true;
}
}
if ( min != null && min > rel.getMinCard() ) {
rel.setMinCard( min );
// if ( min > 1 ) {
dirty = true;
// }
}
if ( max != null && ( rel.getMaxCard() == null || max < rel.getMaxCard() ) ) {
rel.setMaxCard( max );
if ( max == 1 ) {
if ( alreadyRestricted ) {
con.removeProperty( restrictedPropIri );
}
restrictedSuffix = createSuffix( con.getName(), target.getName(), false );
restrictedPropIri = propIri.replace ( ">", restrictedSuffix + ">" );
}
dirty = true;
}
// if ( dirty ) {
if ( dirty ) {
if ( ! target.isPrimitive() || ! rel.getDomain().equals( con ) ) {
rel.setRestricted( true );
rel.setName( originalProperty.getBaseProperty().getName() + restrictedSuffix );
rel.setProperty( restrictedPropIri );
} else {
if ( rel.getMaxCard() != null && rel.getMaxCard() <= 1 ) {
rel.setSimple( true );
}
}
}
rel.setSubject( con.getIri() );
rel.setDomain( con );
boolean inherited = false;
for ( Concept sup : con.getSuperConcepts() ) {
if ( sup.getEffectiveProperties().contains( rel ) ) {
inherited = true;
rel.setInherited( inherited );
break;
}
}
if ( ! rel.mirrors( rel.getBaseProperty() ) ) {
con.addProperty( rel.getProperty(), rel.getName(), rel );
}
if ( dirty ) {
rel.setBaseProperty( originalProperty );
} else {
if ( logger.isDebugEnabled() ) { logger.debug( "No real restriction detected II "+ rel.getName() ); }
rel = originalProperty;
}
rel.getDomain().addProperty( rel.getProperty(), rel.getName(), rel );
return rel;
} else {
if ( logger.isDebugEnabled() ) { logger.debug( "No real restriction detected" ); }
// rel is null and that is what will be returned
}
return rel;
}
private PropertyRelation inheritPropertyCopy( Concept original, Concept current, String propIri ) {
PropertyRelation rel;
for ( Concept sup : current.getSuperConcepts() ) {
// String key = propIri.replace( "As"+current.getName(), "As"+sup.getName() );
String key = propIri;
rel = sup.getProperties().get( key );
if ( rel != null ) {
return rel;
} else {
rel = inheritPropertyCopy( original, sup, propIri );
if ( rel != null ) {
return rel;
}
}
}
return null;
}
private PropertyRelation cloneRel( PropertyRelation rel ) {
PropertyRelation clonedRel = new PropertyRelation( rel.getSubject(), rel.getProperty(), rel.getObject(), rel.getName() );
clonedRel.setMinCard( rel.getMinCard() );
clonedRel.setMaxCard( rel.getMaxCard() );
clonedRel.setTarget( rel.getTarget() );
clonedRel.setDomain( rel.getDomain() );
clonedRel.setRestricted( rel.isRestricted() );
return clonedRel;
}
private void createAndAddBasicProperties( OWLOntology ontoDescr, OWLDataFactory factory, OntoModel hierarchicalModel ) {
int missDomain = 0;
int missDataRange = 0;
int missObjectRange = 0;
for ( OWLDataProperty dp : ontoDescr.getDataPropertiesInSignature( true ) ) {
if ( ! dp.isOWLTopDataProperty() && ! dp.isOWLBottomDataProperty() ) {
Set<OWLClassExpression> domains = dp.getDomains( ontoDescr.getImportsClosure() );
if ( domains.isEmpty() ) {
domains.add( factory.getOWLThing() );
logger.warn( "Added missing domain for" + dp);
missDomain++;
}
Set<OWLDataRange> ranges = dp.getRanges( ontoDescr.getImportsClosure() );
if ( ranges.isEmpty() ) {
ranges.add( factory.getRDFPlainLiteral() );
logger.warn( "Added missing range for" + dp);
missDataRange++;
}
for ( OWLClassExpression domain : domains ) {
for ( OWLDataRange range : ranges ) {
OWLClassExpression realDom = filterAliases( domain );
OWLDatatype dataRange = dataRangeToDataType( range, factory );
PropertyRelation rel = new PropertyRelation( realDom.asOWLClass().getIRI().toQuotedString(),
dp.getIRI().toQuotedString(),
dataRange.getIRI().toQuotedString(),
props.get( dp.getIRI().toQuotedString() ) );
Concept con = conceptCache.get( rel.getSubject() );
rel.setTarget( primitives.get( rel.getObject() ) );
rel.setDomain( con );
con.addProperty( rel.getProperty(), rel.getName(), rel );
hierarchicalModel.addProperty( rel );
}
}
}
}
for ( OWLObjectProperty op : ontoDescr.getObjectPropertiesInSignature( true ) ) {
if ( ! op.isOWLTopObjectProperty() && ! op.isOWLBottomObjectProperty() ) {
Set<OWLClassExpression> domains = op.getDomains( ontoDescr.getImportsClosure() );
if ( domains.isEmpty() ) {
domains.add( factory.getOWLThing() );
logger.warn("Added missing domain for " + op);
missDomain++;
}
Set<OWLClassExpression> ranges = op.getRanges( ontoDescr.getImportsClosure() );
if ( ranges.isEmpty() ) {
ranges.add( factory.getOWLThing() );
logger.warn("Added missing range for " + op);
missObjectRange++;
}
for ( OWLClassExpression domain : domains ) {
for ( OWLClassExpression range : ranges ) {
OWLClassExpression realDom = filterAliases( domain );
OWLClassExpression realRan = filterAliases( range );
if ( realDom.isAnonymous() || realRan.isAnonymous() ) {
logger.error("Domain and Range should no be anonymous at this point : DOM " + realDom + " RAN : " + range);
}
PropertyRelation rel = new PropertyRelation( realDom.asOWLClass().getIRI().toQuotedString(),
op.getIRI().toQuotedString(),
realRan.asOWLClass().getIRI().toQuotedString(),
props.get( op.getIRI().toQuotedString() ) );
Concept con = conceptCache.get( rel.getSubject() );
rel.setTarget( conceptCache.get( rel.getObject() ) );
rel.setDomain( con );
con.addProperty( rel.getProperty(), rel.getName(), rel );
hierarchicalModel.addProperty( rel );
}
}
}
}
if ( logger.isInfoEnabled() ) {
logger.info( "Misses : ");
logger.info( missDomain );
logger.info( missDataRange );
logger.info( missObjectRange );
}
}
private OWLDatatype dataRangeToDataType( OWLDataRange range, OWLDataFactory factory ) {
if ( range.isDatatype() ) {
return range.asOWLDatatype();
}
if ( range instanceof OWLDataOneOf ) {
OWLDataOneOf oneOf = (OWLDataOneOf) range;
Iterator<OWLLiteral> literals = oneOf.getValues().iterator();
OWLDatatype type = literals.next().getDatatype();
while ( literals.hasNext() ) {
OWLDatatype x = literals.next().getDatatype();
if ( ! type.equals( x ) ) {
return factory.getTopDatatype();
}
}
return type;
}
return range.asOWLDatatype();
}
private Map<OWLClassExpression,OWLClassExpression> buildAliasesForEquivalentClasses(OWLOntology ontoDescr) {
Map<OWLClassExpression,OWLClassExpression> aliases = new HashMap<OWLClassExpression,OWLClassExpression>();
Set<OWLEquivalentClassesAxiom> pool = new HashSet<OWLEquivalentClassesAxiom>();
Set<OWLEquivalentClassesAxiom> temp = new HashSet<OWLEquivalentClassesAxiom>();
for ( OWLClass klass : ontoDescr.getClassesInSignature( true ) ) {
for ( OWLEquivalentClassesAxiom klassEq : ontoDescr.getEquivalentClassesAxioms( klass ) ) {
for (OWLEquivalentClassesAxiom eq2 : klassEq.asPairwiseAxioms() ) {
pool.add( eq2 );
}
}
}
boolean stable = false;
while ( ! stable ) {
stable = true;
temp.addAll( pool );
for ( OWLEquivalentClassesAxiom eq2 : pool ) {
List<OWLClassExpression> pair = eq2.getClassExpressionsAsList();
OWLClassExpression first = pair.get( 0 );
OWLClassExpression secnd = pair.get( 1 );
OWLClassExpression removed = null;
if ( aliases.containsValue(first) ) {
// add to existing eqSet, put reversed
// A->X, add X->C ==> A->X, C->X
removed = aliases.put( secnd, first );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else if ( aliases.containsValue(secnd) ) {
// add to existing eqSet, put as is
// A->X, add C->X ==> A->X, C->X
removed = aliases.put( first, secnd );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else if ( aliases.containsKey(first) ) {
// apply transitivity, reversed
// A->X, add A->C ==> A->X, C->X
removed = aliases.put( secnd, aliases.get( first ) );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else if ( aliases.containsKey(secnd) ) {
// apply transitivity, as is
// A->X, add C->A ==> A->X, C->X
removed = aliases.put( first, aliases.get( secnd ) );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else if ( ! first.isAnonymous() ) {
removed = aliases.put( secnd, first );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else if ( ! secnd.isAnonymous() ) {
removed = aliases.put( first, secnd );
if ( removed != null ) {
logger.warn("DUPLICATE KEY WHILE RESOLVING EQUALITIES" + removed + " for value " + eq2);
}
stable = false;
temp.remove( eq2 );
} else {
// both anonymous
}
}
pool.clear();
pool.addAll(temp);
}
if ( ! pool.isEmpty() ) {
logger.error("COULD NOT RESOLVE ANON=ANON EQUALITIES " + pool);
for ( OWLEquivalentClassesAxiom eq2 : pool ) {
List<OWLClassExpression> l = eq2.getClassExpressionsAsList();
if ( ! (l.get(0).isAnonymous() && l.get(1).isAnonymous())) {
logger.error(" EQUALITY WAS NOT RESOLVED " + l);
}
}
}
if ( logger.isInfoEnabled() ) {
logger.info("----------------------------------------------------------------------- " + aliases.size());
for( Map.Entry<OWLClassExpression,OWLClassExpression> entry : aliases.entrySet() ) {
logger.trace(entry.getKey() + " == " + entry.getValue());
}
logger.info("-----------------------------------------------------------------------");
}
for ( Map.Entry<OWLClassExpression,OWLClassExpression> entry : aliases.entrySet() ) {
OWLClassExpression key = entry.getKey();
OWLClassExpression val = entry.getValue();
if ( ! reverseAliases.containsKey( val ) ) {
reverseAliases.put( val, new HashSet<OWLClassExpression>() );
}
reverseAliases.get( val ).add( key );
}
return aliases;
}
private boolean isAbstract(OWLClassExpression clax) {
return clax.asOWLClass().getIRI().toQuotedString().contains("Filler");
}
private boolean processComplexSuperClassesDomainAndRanges(OWLOntology ontoDescr, OWLDataFactory factory) {
boolean dirty = false;
dirty |= processComplexSuperclasses( ontoDescr, factory );
dirty |= processComplexDataPropertyDomains( ontoDescr, factory );
dirty |= processComplexObjectPropertyDomains( ontoDescr, factory );
dirty |= processComplexObjectPropertyRanges( ontoDescr, factory );
return dirty;
}
private boolean processComplexSuperclasses(OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
for ( OWLSubClassOfAxiom sub : ontoDescr.getAxioms(AxiomType.SUBCLASS_OF, true) ) {
if ( sub.getSuperClass().isAnonymous() ) {
if ( sub.getSuperClass() instanceof OWLObjectUnionOf ) {
Iterator<OWLClassExpression> disjuncts = sub.getSuperClass().asDisjunctSet().iterator();
String orNames = asNamedClass( disjuncts.next(), factory, ontoDescr ).getIRI().getFragment();
while ( disjuncts.hasNext() ) {
OWLClass disjunct = asNamedClass( disjuncts.next(), factory, ontoDescr );
orNames += "or" + disjunct.asOWLClass().getIRI().getFragment();
}
OWLClass unjon = factory.getOWLClass( IRI.create(
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toURI().toString() ) +
orNames ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( unjon) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom( sub.getSuperClass(), unjon ) ) );
dirty = true;
}
}
}
return dirty;
}
private OWLClass asNamedClass( OWLClassExpression owlClass, OWLDataFactory factory, OWLOntology ontoDescr ) {
if ( ! owlClass.isAnonymous() ) {
return owlClass.asOWLClass();
}
if ( anonNameAliases.containsKey( owlClass ) ) {
return anonNameAliases.get( owlClass );
}
OWLClass alias = factory.getOWLClass( IRI.create(
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toURI().toString() ) +
"Anon" + counter++ ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( alias ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom( owlClass, alias ) ) );
anonNameAliases.put( owlClass, alias );
return alias;
}
private boolean processComplexObjectPropertyDomains(OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
for ( OWLObjectProperty op : ontoDescr.getObjectPropertiesInSignature( true ) ) {
String typeName = NameUtils.buildNameFromIri( op.getIRI().getStart(), op.getIRI().getFragment() );
Set<OWLObjectPropertyDomainAxiom> domains = ontoDescr.getObjectPropertyDomainAxioms( op );
if ( domains.size() > 1 ) {
Set<OWLClassExpression> domainClasses = new HashSet<OWLClassExpression>();
for ( OWLObjectPropertyDomainAxiom dom : domains ) {
domainClasses.add( dom.getDomain() );
}
OWLObjectIntersectionOf and = factory.getOWLObjectIntersectionOf( domainClasses );
for ( OWLObjectPropertyDomainAxiom dom : domains ) {
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, dom ) );
}
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLObjectPropertyDomainAxiom( op, and ) ) );
dirty = true;
}
if ( op.getDomains( ontoDescr ).size() > 1 ) {
logger.warn( "Property " + op + " should have a single domain class, found " + op.getDomains( ontoDescr ) );
}
for ( OWLClassExpression dom : op.getDomains( ontoDescr.getImportsClosure() ) ) {
if ( dom.isAnonymous() ) {
OWLClass domain = factory.getOWLClass( IRI.create(
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toURI().toString() ) +
NameUtils.capitalize( typeName ) +
"Domain" ) );
OWLAnnotationAssertionAxiom ann = factory.getOWLAnnotationAssertionAxiom( factory.getOWLAnnotationProperty( IRI.create( "http://www.w3.org/2000/01/rdf-schema#comment" ) ),
domain.getIRI(),
factory.getOWLStringLiteral("abstract") );
if ( logger.isDebugEnabled() ) { logger.debug("REPLACED ANON DOMAIN " + op + " with " + domain + ", was " + dom); }
logger.warn( "REPLACED ANON DOMAIN " + op + " with " + domain + ", was " + dom );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( domain ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom( domain, dom ) ) );
OWLOntology defining = lookupDefiningOntology( ontoDescr, op );
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( defining, defining.getObjectPropertyDomainAxioms( op ).iterator().next() ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLObjectPropertyDomainAxiom( op, domain ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, ann ) );
dirty = true;
}
}
}
return dirty;
}
private OWLOntology lookupDefiningOntology( OWLOntology ontoDescr, OWLEntity axiom ) {
List<OWLOntology> imports = ontoDescr.getOWLOntologyManager().getSortedImportsClosure( ontoDescr );
OWLOntology defining = ontoDescr;
for ( OWLOntology onto : imports ) {
if ( onto.containsAxiom( ontoDescr.getOWLOntologyManager().getOWLDataFactory().getOWLDeclarationAxiom( axiom ) , false ) ) {
defining = onto;
break;
}
}
return defining;
}
private boolean processComplexDataPropertyDomains(OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
for ( OWLDataProperty dp : ontoDescr.getDataPropertiesInSignature( true ) ) {
String typeName = NameUtils.buildNameFromIri( dp.getIRI().getStart(), dp.getIRI().getFragment() );
OWLOntology defining = lookupDefiningOntology( ontoDescr, dp );
Set<OWLDataPropertyDomainAxiom> domains = defining.getDataPropertyDomainAxioms( dp );
if ( domains.size() > 1 ) {
Set<OWLClassExpression> domainClasses = new HashSet<OWLClassExpression>();
for ( OWLDataPropertyDomainAxiom dom : domains ) {
domainClasses.add( dom.getDomain() );
}
OWLObjectIntersectionOf and = factory.getOWLObjectIntersectionOf( domainClasses );
for ( OWLDataPropertyDomainAxiom dom : domains ) {
defining.getOWLOntologyManager().applyChange( new RemoveAxiom( defining, dom ) );
}
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLDataPropertyDomainAxiom(dp, and) ) );
dirty = true;
}
if ( dp.getDomains( ontoDescr ).size() > 1 ) {
logger.warn("Property " + dp + " should have a single domain class, found " + dp.getDomains(ontoDescr));
}
for ( OWLClassExpression dom : dp.getDomains( defining ) ) {
if ( dom.isAnonymous() ) {
OWLClass domain = factory.getOWLClass( IRI.create(
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toURI().toString() ) +
NameUtils.capitalize( typeName ) +
"Domain" ) );
OWLAnnotationAssertionAxiom ann = factory.getOWLAnnotationAssertionAxiom( factory.getOWLAnnotationProperty( IRI.create( "http://www.w3.org/2000/01/rdf-schema#comment" ) ),
domain.getIRI(),
factory.getOWLStringLiteral("abstract") );
if ( logger.isDebugEnabled() ) { logger.debug("INFO : REPLACED ANON DOMAIN " + dp + " with " + domain + ", was " + dom); }
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLDeclarationAxiom( domain ) ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLEquivalentClassesAxiom( domain, dom ) ) );
defining.getOWLOntologyManager().applyChange( new RemoveAxiom( defining, defining.getDataPropertyDomainAxioms( dp ).iterator().next() ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLDataPropertyDomainAxiom(dp, domain) ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, ann ) );
dirty = true;
}
}
}
return dirty;
}
private boolean processComplexObjectPropertyRanges( OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
for ( OWLObjectProperty op : ontoDescr.getObjectPropertiesInSignature( true ) ) {
String typeName = NameUtils.buildNameFromIri( op.getIRI().getStart(), op.getIRI().getFragment() );
Set<OWLObjectPropertyRangeAxiom> ranges = ontoDescr.getObjectPropertyRangeAxioms( op );
if ( ranges.size() > 1 ) {
Set<OWLClassExpression> rangeClasses = new HashSet<OWLClassExpression>();
for ( OWLObjectPropertyRangeAxiom dom : ranges ) {
rangeClasses.add( dom.getRange() );
}
OWLObjectIntersectionOf and = factory.getOWLObjectIntersectionOf( rangeClasses );
for ( OWLObjectPropertyRangeAxiom ran : ranges ) {
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, ran ) );
}
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLObjectPropertyRangeAxiom(op, and) ) );
dirty = true;
}
if ( op.getRanges(ontoDescr).size() > 1 ) {
logger.warn(" WARNING : Property " + op + " should have a single range class, found " + op.getRanges(ontoDescr));
}
for ( OWLClassExpression ran : op.getRanges( ontoDescr.getImportsClosure() ) ) {
if ( ran.isAnonymous() ) {
OWLClass range = factory.getOWLClass( IRI.create(
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toURI().toString() ) +
NameUtils.capitalize( typeName ) +
"Range" ) );
OWLAnnotationAssertionAxiom ann = factory.getOWLAnnotationAssertionAxiom( factory.getOWLAnnotationProperty( IRI.create( "http://www.w3.org/2000/01/rdf-schema#comment" ) ),
range.getIRI(),
factory.getOWLLiteral("abstract") );
if ( logger.isDebugEnabled() ) { logger.debug(" REPLACED ANON RANGE " + op + " with " + range + ", was " + ran); }
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( range ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom( range, ran ) ) );
OWLObjectPropertyRangeAxiom rangx = null;
Set<OWLOntology> ontologies = ontoDescr.getImportsClosure();
for ( OWLOntology onto : ontologies ) {
Set<OWLObjectPropertyRangeAxiom> assertedRanges = onto.getObjectPropertyRangeAxioms( op );
if ( ! assertedRanges.isEmpty() ) {
rangx = assertedRanges.iterator().next();
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, rangx ) );
}
}
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLObjectPropertyRangeAxiom(op, range) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, ann ) );
dirty = true;
}
}
}
return dirty;
}
private boolean preProcessIndividuals( OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
for ( OWLNamedIndividual ind : ontoDescr.getIndividualsInSignature( true ) ) {
OWLOntology defining = lookupDefiningOntology( ontoDescr, ind );
declareAnonymousIndividualSupertypes( defining, factory, ind );
logger.info( "Defining ontology : " + defining );
for ( OWLAxiom ax : defining.getAxioms( AxiomType.CLASS_ASSERTION ) ) {
logger.trace( ax );
}
logger.info( "Getting types for individual " + ind.getIRI() );
Set<OWLClassExpression> types = ind.getTypes( defining );
logger.info( "Found types in defining ontology" + types );
if ( types.isEmpty() ) {
ind.getTypes( ontoDescr.getImportsClosure() );
logger.info( "Found types in all ontologies " + ontoDescr.getImportsClosure() + " >> " + types );
}
types = simplify( types, defining );
if ( types.size() > 1 ) {
OWLObjectIntersectionOf and = factory.getOWLObjectIntersectionOf( types );
dirty = true;
logger.warn( " Individual " + ind + " got a new combined type " + and );
OWLClass type = factory.getOWLClass( IRI.create( ind.getIRI().getStart() + NameUtils.compactUpperCase( ind.getIRI().getFragment() ) + "Type" ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLDeclarationAxiom( type ) ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLSubClassOfAxiom( type, and ) ) );
defining.getOWLOntologyManager().applyChange( new AddAxiom( defining, factory.getOWLClassAssertionAxiom( type, ind ) ) );
individualTypesCache.put( ind.getIRI().toQuotedString(), type.getIRI().toQuotedString() );
} else {
if ( types.iterator().hasNext() ) {
individualTypesCache.put( ind.getIRI().toQuotedString(), types.iterator().next().asOWLClass().getIRI().toQuotedString() );
} else {
logger.warn( "WARNING no type detected for individual " + ind.getIRI().toQuotedString() );
}
}
}
return dirty;
}
private void declareAnonymousIndividualSupertypes(OWLOntology ontoDescr, OWLDataFactory factory, OWLNamedIndividual ind ) {
Set<OWLClassExpression> types = ind.getTypes( ontoDescr );
int j = 0;
for ( OWLClassExpression type : types ) {
j++;
if ( type.isAnonymous() ) {
OWLClass temp = factory.getOWLClass( IRI.create( ind.getIRI().getStart() + NameUtils.compactUpperCase( ind.getIRI().getFragment() ) + "RestrictedType" + j ) );
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, factory.getOWLClassAssertionAxiom( type, ind ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( temp ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom(temp, type) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLClassAssertionAxiom( temp, ind ) ) );
}
}
}
private Set<OWLClassExpression> simplify(Set<OWLClassExpression> types, OWLOntology ontoDescr) {
if ( types.size() == 1 ) {
return types;
}
Set<OWLClassExpression> ans = new HashSet<OWLClassExpression>( types );
for ( OWLClassExpression klass1 : types ) {
for ( OWLClassExpression klass2 : types ) {
if ( isSuperClass( ontoDescr, klass1, klass2 ) ) {
ans.remove( klass1 );
}
}
}
return ans;
}
private boolean isSuperClass( OWLOntology ontoDescr, Set<OWLClassExpression> supers, OWLClassExpression klass2 ) {
OWLClass k = klass2.asOWLClass();
OWLOntology defining = lookupDefiningOntology( ontoDescr, k );
Set<OWLSubClassOfAxiom> subKlassOfs = defining.getSubClassAxiomsForSubClass( k );
for ( OWLSubClassOfAxiom sub : subKlassOfs ) {
if ( supers.contains( sub.getSuperClass() ) ) {
return true;
} else {
if ( ! sub.getSuperClass().isAnonymous() && isSuperClass( ontoDescr, supers, sub.getSuperClass() ) ) {
return true;
}
}
}
return false;
}
private boolean isSuperClass( OWLOntology ontoDescr, OWLClassExpression klass1, OWLClassExpression klass2 ) {
Set<OWLSubClassOfAxiom> subKlassOfs = ontoDescr.getSubClassAxiomsForSuperClass( klass1.asOWLClass() );
for ( OWLSubClassOfAxiom sub : subKlassOfs ) {
if ( sub.getSubClass().equals( klass2 ) ) {
return true;
} else {
if ( isSuperClass( ontoDescr, sub.getSubClass(), klass2 ) ) {
return true;
}
}
}
return false;
}
private boolean processQuantifiedRestrictions( OWLOntology ontoDescr, OWLDataFactory factory ) {
boolean dirty = false;
// infer domain / range from quantified restrictions...
for ( OWLClass klassAx : ontoDescr.getClassesInSignature( true ) ) {
OWLClass klass = klassAx;
for ( OWLClassExpression clax : klass.getSuperClasses( ontoDescr ) ) {
clax = clax.getNNF();
dirty |= processQuantifiedRestrictionsInClass( klass, clax, ontoDescr, factory );
}
for ( OWLClassExpression clax : klass.getEquivalentClasses( ontoDescr ) ) {
clax = clax.getNNF();
dirty |= processQuantifiedRestrictionsInClass( klass, clax, ontoDescr, factory );
}
}
return dirty;
}
private boolean processQuantifiedRestrictionsInClass(OWLClass klass, OWLClassExpression clax, OWLOntology ontology, OWLDataFactory fac) {
final boolean[] dirty = { false };
final OWLClass inKlass = klass;
final OWLDataFactory factory = fac;
final OWLOntology ontoDescr = ontology;
clax.accept( new OWLClassExpressionVisitor() {
private void process( OWLClassExpression expr ) {
if ( expr instanceof OWLNaryBooleanClassExpression ) {
for (OWLClassExpression clax : ((OWLNaryBooleanClassExpression) expr).getOperandsAsList() ) {
process( clax );
}
} else if ( expr instanceof OWLQuantifiedObjectRestriction ) {
OWLQuantifiedObjectRestriction rest = (OWLQuantifiedObjectRestriction) expr;
//
OWLObjectProperty prop = rest.getProperty().asOWLObjectProperty();
OWLClassExpression fil = rest.getFiller();
boolean inDomain = checkIsPropertyInDomain( prop, inKlass, expr, ontoDescr );
if ( ! inDomain ) {
rewirePropertyDomain( prop, expr, ontoDescr );
}
reifyFiller( prop, fil );
process( fil );
} else if ( expr instanceof OWLObjectCardinalityRestriction ) {
OWLObjectCardinalityRestriction rest = (OWLObjectCardinalityRestriction) expr;
//
OWLObjectProperty prop = rest.getProperty().asOWLObjectProperty();
OWLClassExpression fil = rest.getFiller();
boolean inDomain = checkIsPropertyInDomain( prop, inKlass, expr, ontoDescr );
if ( ! inDomain ) {
rewirePropertyDomain( prop, expr, ontoDescr );
}
reifyFiller( prop, fil );
process( fil );
} else if ( expr instanceof OWLQuantifiedDataRestriction ) {
} else if ( expr instanceof OWLCardinalityRestriction ) {
if ( expr instanceof OWLDataMinCardinality ) {
minCards.put(inKlass.getIRI().toQuotedString(),
((OWLDataMinCardinality) expr).getProperty().asOWLDataProperty().getIRI().toQuotedString(),
((OWLDataMinCardinality) expr).getCardinality());
minCounter++;
} else if ( expr instanceof OWLDataMaxCardinality ) {
maxCards.put( inKlass.getIRI().toQuotedString(),
((OWLDataMaxCardinality) expr).getProperty().asOWLDataProperty().getIRI().toQuotedString(),
((OWLDataMaxCardinality) expr).getCardinality() );
maxCounter++;
} else if ( expr instanceof OWLObjectMaxCardinality ) {
maxCards.put( inKlass.getIRI().toQuotedString(),
((OWLObjectMaxCardinality) expr).getProperty().asOWLObjectProperty().getIRI().toQuotedString(),
((OWLObjectMaxCardinality) expr).getCardinality() );
process( ((OWLObjectMaxCardinality) expr).getFiller() );
maxCounter++;
} else if ( expr instanceof OWLObjectMinCardinality ) {
minCards.put( inKlass.getIRI().toQuotedString(),
((OWLObjectMinCardinality) expr).getProperty().asOWLObjectProperty().getIRI().toQuotedString(),
((OWLObjectMinCardinality) expr).getCardinality() );
process( ((OWLObjectMinCardinality) expr).getFiller() );
minCounter++;
}
}
else return;
}
private void rewirePropertyDomain( OWLObjectProperty prop, OWLClassExpression expr, OWLOntology ontoDescr ) {
OWLOntology defining = lookupDefiningOntology( ontoDescr, prop );
Set<OWLObjectPropertyDomainAxiom> domains = defining.getObjectPropertyDomainAxioms( prop );
OWLClassExpression propDomain = null;
for ( OWLObjectPropertyDomainAxiom dox : domains ) {
if ( ! dox.getDomain().isAnonymous() ) {
propDomain = dox.getDomain();
}
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, dox ) );
}
OWLClass extDomain = factory.getOWLClass( IRI.create(
prop.getIRI().getStart(), NameUtils.capitalize( prop.getIRI().getFragment() ) + "ExtraDomain" + counter++ ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( extDomain ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLSubClassOfAxiom( propDomain, extDomain ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLSubClassOfAxiom( extDomain, ontoDescr.getOWLOntologyManager().getOWLDataFactory().getOWLThing() ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLObjectPropertyDomainAxiom( prop, extDomain ) ) );
Set<OWLClassExpression> aliases = new HashSet<OWLClassExpression>();
for ( OWLEquivalentClassesAxiom eq : ontoDescr.getAxioms( AxiomType.EQUIVALENT_CLASSES ) ) {
if ( eq.contains( expr ) ) {
aliases.addAll( eq.getClassExpressions() );
}
}
for ( OWLSubClassOfAxiom sub : ontoDescr.getAxioms( AxiomType.SUBCLASS_OF ) ) {
if ( aliases.contains( sub.getSuperClass() ) && ! sub.getSubClass().equals( extDomain ) ) {
ontoDescr.getOWLOntologyManager().applyChange( new RemoveAxiom( ontoDescr, sub ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLSubClassOfAxiom( sub.getSubClass(), extDomain ) ) );
}
}
dirty[0] = true;
}
private boolean checkIsPropertyInDomain( OWLObjectProperty prop, OWLClass inKlass, OWLClassExpression expr, OWLOntology ontoDescr ) {
Set<OWLClassExpression> domains = new HashSet<OWLClassExpression>();
OWLOntology defining = lookupDefiningOntology( ontoDescr, prop );
for ( OWLObjectPropertyDomainAxiom dom : defining.getObjectPropertyDomainAxioms( prop ) ) {
domains.add( dom.getDomain() );
}
if ( domains.size() == 0 ) {
// this property will become part of (Root)Thing
return true;
}
if ( domains.contains( inKlass ) ) {
return true;
}
if ( isSuperClass( ontoDescr, domains, inKlass ) ) {
return true;
}
defining = lookupDefiningOntology( ontoDescr, inKlass );
for ( OWLEquivalentClassesAxiom eq : defining.getEquivalentClassesAxioms( inKlass ) ) {
for ( OWLClassExpression x : eq.getClassExpressions() ) {
if ( ! x.isAnonymous() ) {
if ( isSuperClass( ontoDescr, domains, x ) ) {
return true;
}
}
}
}
return false;
}
private void reifyFiller( OWLObjectProperty prop, OWLClassExpression fil ) {
if ( fil.isAnonymous() ) {
OWLClass filler = fillerCache.get( fil );
if ( filler == null ) {
String fillerName =
NameUtils.separatingName( ontoDescr.getOntologyID().getOntologyIRI().toString() ) +
NameUtils.capitalize( inKlass.getIRI().getFragment() ) +
NameUtils.capitalize( prop.getIRI().getFragment() ) +
"Filler" +
(counter++);
filler = factory.getOWLClass( IRI.create( fillerName ) );
// On a second thought, fillers could stay real...
// OWLAnnotationAssertionAxiom ann = factory.getOWLAnnotationAssertionAxiom( factory.getOWLAnnotationProperty( IRI.create( "http://www.w3.org/2000/01/rdf-schema#comment" ) ),
// filler.getIRI(),
// factory.getOWLStringLiteral("abstract") );
// ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, ann ) );
fillerCache.put( fil, filler );
} else {
if ( logger.isDebugEnabled() ) { logger.debug("REUSED FILLER FOR" + fil); }
}
dirty[0] = true;
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLDeclarationAxiom( filler ) ) );
ontoDescr.getOWLOntologyManager().applyChange( new AddAxiom( ontoDescr, factory.getOWLEquivalentClassesAxiom( filler, fil ) ) );
}
}
public void visit(OWLClass ce) {
process( ce );
}
public void visit(OWLObjectIntersectionOf ce) {
process( ce );
}
public void visit(OWLObjectUnionOf ce) {
process( ce );
}
public void visit(OWLObjectComplementOf ce) {
process( ce );
}
public void visit(OWLObjectSomeValuesFrom ce) {
process(ce);
}
public void visit(OWLObjectAllValuesFrom ce) {
process(ce);
}
public void visit(OWLObjectHasValue ce) {
process(ce);
}
public void visit(OWLObjectMinCardinality ce) {
// minCards.put(inKlass, ce.getProperty().asOWLObjectProperty().getIRI().toQuotedString(), ce.getCardinality());
// minCounter++;
process(ce);
}
public void visit(OWLObjectExactCardinality ce) {
// maxCards.put(inKlass, ce.getProperty().asOWLObjectProperty().getIRI().toQuotedString(), ce.getCardinality());
// minCards.put(inKlass, ce.getProperty().asOWLObjectProperty().getIRI().toQuotedString(), ce.getCardinality());
// minCounter++;
// maxCounter++;
process(ce);
}
public void visit(OWLObjectMaxCardinality ce) {
// maxCards.put(inKlass, ce.getProperty().asOWLObjectProperty().getIRI().toQuotedString(), ce.getCardinality());
// maxCounter++;
process(ce);
}
public void visit(OWLObjectHasSelf ce) {
throw new UnsupportedOperationException();
}
public void visit(OWLObjectOneOf ce) {
// throw new UnsupportedOperationException();
}
public void visit(OWLDataSomeValuesFrom ce) {
process(ce);
}
public void visit(OWLDataAllValuesFrom ce) {
process(ce);
}
public void visit(OWLDataHasValue ce) {
process(ce);
}
public void visit(OWLDataMinCardinality ce) {
// minCards.put(inKlass, ce.getProperty().asOWLDataProperty().getIRI().toQuotedString(), ce.getCardinality());
// minCounter++;
process(ce);
}
public void visit(OWLDataExactCardinality ce) {
// minCards.put(inKlass, ce.getProperty().asOWLDataProperty().getIRI().toQuotedString(), ce.getCardinality());
// maxCards.put(inKlass, ce.getProperty().asOWLDataProperty().getIRI().toQuotedString(), ce.getCardinality());
// maxCounter++;
// minCounter++;
process(ce);
}
public void visit(OWLDataMaxCardinality ce) {
// maxCards.put(inKlass, ce.getProperty().asOWLDataProperty().getIRI().toQuotedString(), ce.getCardinality());
// maxCounter++;
process(ce);
}
});
return dirty[0];
}
private void fillPropNamesInDataStructs( OWLOntology ontoDescr ) {
for ( OWLDataProperty dp : ontoDescr.getDataPropertiesInSignature( true ) ) {
if ( ! dp.isTopEntity() && ! dp.isBottomEntity() ) {
String propIri = dp.getIRI().toQuotedString();
String propName = NameUtils.buildLowCaseNameFromIri( dp.getIRI().getFragment() );
if ( propName == null ) {
propName = NameUtils.buildLowCaseNameFromIri( dp.getIRI().getStart() );
}
props.put( propIri, propName );
}
}
for ( OWLObjectProperty op : ontoDescr.getObjectPropertiesInSignature( true ) ) {
if ( ! op.isTopEntity() && ! op.isBottomEntity() ) {
String propIri = op.getIRI().toQuotedString();
String propName = NameUtils.buildLowCaseNameFromIri( op.getIRI().getFragment() );
if ( propName == null ) {
propName = NameUtils.buildLowCaseNameFromIri( op.getIRI().getStart() );
}
props.put( propIri, propName );
}
}
}
private String reportStats( OWLOntology ontoDescr ) {
StringBuilder sb = new StringBuilder();
sb.append( " *** Stats for ontology : " + ontoDescr.getOntologyID() );
sb.append( " Number of classes " + ontoDescr.getClassesInSignature( true ).size() );
sb.append( " \t Number of classes " + ontoDescr.getClassesInSignature( true ).size() );
sb.append( " Number of datatypes " + ontoDescr.getDatatypesInSignature().size() );
sb.append( " Number of dataProps " + ontoDescr.getDataPropertiesInSignature( true ).size() );
sb.append( "\t Number of dataProp domains " + ontoDescr.getAxiomCount( AxiomType.DATA_PROPERTY_DOMAIN ));
for ( OWLDataProperty p : ontoDescr.getDataPropertiesInSignature( true ) ) {
int num = ontoDescr.getDataPropertyDomainAxioms( p ).size();
if ( num != 1 ) {
sb.append( "\t\t Domain" + p + " --> " + num );
} else {
OWLDataPropertyDomainAxiom dom = ontoDescr.getDataPropertyDomainAxioms( p ).iterator().next();
if ( ! ( dom.getDomain() instanceof OWLClass ) ) {
sb.append( "\t\t Complex Domain" + p + " --> " + dom.getDomain() );
}
}
}
sb.append( "\t Number of dataProp ranges " + ontoDescr.getAxiomCount( AxiomType.DATA_PROPERTY_RANGE ));
for ( OWLDataProperty p : ontoDescr.getDataPropertiesInSignature( true ) ) {
int num = ontoDescr.getDataPropertyRangeAxioms( p ).size();
if ( num != 1 ) {
sb.append( "\t\t Range" + p + " --> " + num );
} else {
OWLDataPropertyRangeAxiom range = ontoDescr.getDataPropertyRangeAxioms( p ).iterator().next();
if ( ! ( range.getRange() instanceof OWLDatatype ) ) {
sb.append( "\t\t Complex Range" + p + " --> " + range.getRange() );
}
}
}
sb.append( " Number of objProps " + ontoDescr.getObjectPropertiesInSignature( true ).size() );
sb.append( "\t Number of objProp domains " + ontoDescr.getAxiomCount( AxiomType.OBJECT_PROPERTY_DOMAIN ));
for ( OWLObjectProperty p : ontoDescr.getObjectPropertiesInSignature( true ) ) {
int num = ontoDescr.getObjectPropertyDomainAxioms( p ).size();
if ( num != 1 ) {
sb.append( "\t\t Domain" + p + " --> " + num );
} else {
OWLObjectPropertyDomainAxiom dom = ontoDescr.getObjectPropertyDomainAxioms( p ).iterator().next();
if ( ! ( dom.getDomain() instanceof OWLClass ) ) {
sb.append( "\t\t Complex Domain" + p + " --> " + dom.getDomain() );
}
}
}
sb.append( "\t Number of objProp ranges " + ontoDescr.getAxiomCount( AxiomType.OBJECT_PROPERTY_RANGE ));
for ( OWLObjectProperty p : ontoDescr.getObjectPropertiesInSignature( true ) ) {
int num = ontoDescr.getObjectPropertyRangeAxioms( p ).size();
if ( num != 1 ) {
sb.append( "\t\t Range" + p + " --> " + num );
} else {
OWLObjectPropertyRangeAxiom range = ontoDescr.getObjectPropertyRangeAxioms( p ).iterator().next();
if ( ! ( range.getRange() instanceof OWLClass ) ) {
sb.append( "\t\t Complex Domain" + p + " --> " + range.getRange() );
}
}
}
return sb.toString();
}
private OWLProperty lookupDataProperty(String propId, Set<OWLDataProperty> set ) {
for (OWLDataProperty prop : set ) {
if ( prop.getIRI().toQuotedString().equals( propId ) ) {
return prop;
}
}
return null;
}
private OWLProperty lookupObjectProperty(String propId, Set<OWLObjectProperty> set ) {
for (OWLObjectProperty prop : set ) {
if ( prop.getIRI().toQuotedString().equals( propId ) ) {
return prop;
}
}
return null;
}
protected OntoModel buildClassLattice( OWLOntology ontoDescr,
StatefulKnowledgeSession kSession,
Map<InferenceTask,
Resource> theory,
OntoModel baseModel,
DLFactoryConfiguration conf ) {
boolean dirty = true;
OWLDataFactory factory = ontoDescr.getOWLOntologyManager().getOWLDataFactory();
launchReasoner( dirty, kSession, ontoDescr, conf.getAxiomGens() );
// reify complex superclasses, domains and ranges
dirty |= processComplexSuperClassesDomainAndRanges( ontoDescr, factory );
/************************************************************************************************************************************/
// check individuals for multiple inheritance
dirty |= preProcessIndividuals( ontoDescr, ontoDescr.getOWLOntologyManager().getOWLDataFactory() );
/************************************************************************************************************************************/
// new classes have been added, classify the
launchReasoner( dirty, kSession, ontoDescr, conf.getAxiomGens() );
/************************************************************************************************************************************/
// reify complex restriction fillers
dirty = processQuantifiedRestrictions( ontoDescr, factory );
/************************************************************************************************************************************/
// new classes have been added, classify the
if ( ! conf.isDisableFullReasoner() ) {
launchReasoner( dirty, kSession, ontoDescr, conf.getAxiomGens() );
}
/************************************************************************************************************************************/
// resolve aliases, choosing delegators
aliases = buildAliasesForEquivalentClasses( ontoDescr );
/************************************************************************************************************************************/
if ( logger.isInfoEnabled() ) {
logger.info( reportStats( ontoDescr ) );
}
// classes are stable now
addConceptsToModel( kSession, ontoDescr, baseModel );
// lattice is too. applies aliasing
addSubConceptsToModel( ontoDescr, baseModel );
kSession.fireAllRules();
return baseModel;
}
private void fixRootHierarchy(OntoModel model) {
Concept thing = model.getConcept( IRI.create( NamespaceUtils.getNamespaceByPrefix( "owl" ).getURI() + "#Thing" ).toQuotedString() );
if ( thing.getProperties().size() > 0 ) {
Concept localRoot = new Concept(
IRI.create( NameUtils.separatingName( model.getDefaultNamespace() ) + "RootThing" ),
"RootThing",
false );
model.addConcept( localRoot );
localRoot.addSuperConcept( thing );
thing.getSubConcepts().add( localRoot );
for ( String propIri : thing.getProperties().keySet() ) {
PropertyRelation rel = thing.getProperty( propIri );
rel.setDomain( localRoot );
localRoot.addProperty( propIri, rel.getName(), rel );
}
thing.getProperties().clear();
for ( Concept con : model.getConcepts() ) {
if ( con == localRoot ) {
continue;
}
if ( con.getSuperConcepts().contains( thing ) ) {
con.getSuperConcepts().remove( thing );
con.getSuperConcepts().add( localRoot );
}
if ( thing.getSubConcepts().contains( con ) ) {
thing.getSubConcepts().remove( con );
localRoot.getSubConcepts().add( con );
}
}
for ( PropertyRelation prop : model.getProperties() ) {
fixProperty( prop, thing, localRoot );
}
}
}
private void fixProperty( PropertyRelation prop, Concept thing, Concept localRoot ) {
if ( prop.getDomain() == thing ) {
prop.setDomain( localRoot );
}
if ( prop.getTarget() == thing ) {
prop.setTarget( localRoot );
}
for ( PropertyRelation sub : prop.getRestrictedProperties() ) {
fixProperty( sub, thing, localRoot );
}
}
private void processSubConceptAxiom( OWLClassExpression subClass, OWLClassExpression superClass, Map<String, Collection<String>> supers, String thing ) {
if ( ! superClass.isAnonymous() || superClass instanceof OWLObjectUnionOf ) {
String sub = filterAliases( subClass ).asOWLClass().getIRI().toQuotedString();
String sup = isDelegating( superClass ) ?
thing : filterAliases( superClass ).asOWLClass().getIRI().toQuotedString();
addSuper( sub, sup, supers );
} else if ( superClass instanceof OWLObjectIntersectionOf ) {
OWLObjectIntersectionOf and = (OWLObjectIntersectionOf) superClass;
for ( OWLClassExpression ex : and.asConjunctSet() ) {
processSubConceptAxiom( subClass, ex, supers, thing );
}
}
}
private void addSuper(String sub, String sup, Map<String, Collection<String>> supers) {
if ( sub.equals( sup ) ) {
return;
}
Collection<String> ancestors = supers.get( sub );
if ( ancestors == null ) {
ancestors = new HashSet<String>();
supers.put( sub, ancestors );
}
ancestors.add( sup );
}
private void addSubConceptsToModel( OWLOntology ontoDescr, OntoModel model) {
Map<String,Collection<String>> supers = new HashMap<String, Collection<String>>();
String thing = ontoDescr.getOWLOntologyManager().getOWLDataFactory().getOWLThing().getIRI().toQuotedString();
supers.put( thing, Collections.EMPTY_SET );
for ( OWLSubClassOfAxiom ax : ontoDescr.getAxioms( AxiomType.SUBCLASS_OF ) ) {
processSubConceptAxiom( ax.getSubClass(), ax.getSuperClass(), supers, thing );
}
for ( OWLEquivalentClassesAxiom ax : ontoDescr.getAxioms( AxiomType.EQUIVALENT_CLASSES ) ) {
processSubConceptAxiom( ax.getClassExpressionsAsList().get( 0 ), filterAliases( ax.getClassExpressionsAsList().get( 1 ) ), supers, thing );
}
for ( OWLClassExpression delegator : aliases.keySet() ) {
if ( ! delegator.isAnonymous() ) {
addSuper( delegator.asOWLClass().getIRI().toQuotedString(), thing, supers );
}
}
for ( OWLClassExpression delegator : aliases.keySet() ) {
if ( ! delegator.isAnonymous() ) {
OWLClassExpression delegate = aliases.get( delegator );
String sub = delegate.asOWLClass().getIRI().toQuotedString();
String sup = delegator.asOWLClass().getIRI().toQuotedString();
conceptCache.get( sub ).getEquivalentConcepts().add( conceptCache.get( sup ) );
addSuper(sub, sup, supers);
}
}
HierarchySorter<String> sorter = new HierarchySorter<String>();
List<String> sortedCons = sorter.sort( supers );
ArrayList missing = new ArrayList( conceptCache.keySet() );
missing.removeAll( supers.keySet() );
LinkedHashMap<String,Concept> sortedCache = new LinkedHashMap<String, Concept>();
for ( String con : sortedCons ) {
sortedCache.put( con, conceptCache.get( con ) );
}
conceptCache.clear();
conceptCache = sortedCache;
reduceTransitiveInheritance( sortedCache, supers );
for ( String con : supers.keySet() ) {
Collection<String> parents = supers.get( con );
for ( String sup : parents ) {
SubConceptOf subConceptOf = new SubConceptOf( con, sup );
model.addSubConceptOf( subConceptOf );
conceptCache.get( subConceptOf.getSubject() ).addSuperConcept( conceptCache.get( subConceptOf.getObject() ) );
}
}
}
private void reduceTransitiveInheritance(LinkedHashMap<String, Concept> sortedCache, Map<String, Collection<String>> supers) {
Map<String, Collection<String>> taboos = new HashMap<String, Collection<String>>();
for ( String con : sortedCache.keySet() ) {
Collection<String> ancestors = supers.get( con );
Set<String> taboo = new HashSet<String>();
for ( String anc : ancestors ) {
if ( taboos.containsKey( anc ) ) {
taboo.addAll( taboos.get( anc ) );
}
}
ancestors.removeAll( taboo );
taboo.addAll( ancestors );
taboos.put( con, taboo );
}
}
private boolean isDelegating( OWLClassExpression superClass ) {
return aliases.containsKey( superClass );
}
private boolean isDelegating( String classIri ) {
for ( OWLClassExpression klass : aliases.keySet() ) {
if ( ! klass.isAnonymous() && klass.asOWLClass().getIRI().toQuotedString().equals( classIri ) ) {
return true;
}
}
return false;
}
private OWLClassExpression filterAliases( OWLClassExpression klass ) {
if ( aliases.containsKey( klass ) ) {
return aliases.get( klass );
} else return klass;
}
private void addConceptsToModel(StatefulKnowledgeSession kSession, OWLOntology ontoDescr, OntoModel baseModel) {
Set<OWLClass> kis = ontoDescr.getClassesInSignature( true );
Set dek = ontoDescr.getAxioms( AxiomType.DECLARATION );
for ( OWLClass con : ontoDescr.getClassesInSignature( true ) ) {
if ( baseModel.getConcept( con.getIRI().toQuotedString()) == null ) {
Concept concept = new Concept(
con.getIRI(),
NameUtils.buildNameFromIri( con.getIRI().getStart(), con.getIRI().getFragment() ),
con.isOWLDatatype() );
for ( OWLAnnotation ann : con.getAnnotations( ontoDescr ) ) {
if ( ann.getProperty().isComment() && ann.getValue() instanceof OWLLiteral ) {
OWLLiteral lit = (OWLLiteral) ann.getValue();
if ( lit.getLiteral().trim().equals( "abstract" ) ) {
concept.setAbstrakt( true );
}
}
}
if ( concept.getName().endsWith( "Range" ) || concept.getName().endsWith( "Domain" ) || concept.getName().matches( "\\S*Filler\\d+" ) ) {
concept.setAnonymous( true );
}
baseModel.addConcept( concept );
kSession.insert(concept);
conceptCache.put(con.getIRI().toQuotedString(), concept);
}
}
}
private void addDataRange(Map<OWLProperty, Set<OWLDataRange>> dataRanges, OWLDataProperty dp, OWLDataRange owlData, OWLDataFactory factory ) {
Set<OWLDataRange> set = dataRanges.get( dp );
if ( set == null ) {
set = new HashSet<OWLDataRange>();
dataRanges.put( dp, set );
}
set.add( owlData );
if ( set.size() >= 2 && set.contains( factory.getTopDatatype() ) ) {
set.remove( factory.getTopDatatype() );
}
}
private void addRange(Map<OWLProperty, Set<OWLClassExpression>> ranges, OWLProperty rp, OWLClassExpression owlKlass, OWLDataFactory factory ) {
Set<OWLClassExpression> set = ranges.get( rp );
if ( set == null ) {
set = new HashSet<OWLClassExpression>();
ranges.put( rp, set );
}
set.add( owlKlass );
if ( set.size() >= 2 && set.contains( factory.getOWLThing() ) ) {
set.remove( factory.getOWLThing() );
}
}
private void addDomain(Map<OWLProperty, Set<OWLClassExpression>> domains, OWLProperty dp, OWLClassExpression owlKlass, OWLDataFactory factory) {
Set<OWLClassExpression> set = domains.get( dp );
if ( set == null ) {
set = new HashSet<OWLClassExpression>();
domains.put( dp, set );
}
set.add( owlKlass );
if ( set.size() >= 2 && set.contains( factory.getOWLThing() ) ) {
set.remove( factory.getOWLThing() );
}
}
private void setDomain(Map<OWLProperty, Set<OWLClassExpression>> domains, OWLProperty dp, OWLClassExpression owlKlass, OWLDataFactory factory ) {
Set<OWLClassExpression> set = domains.get( dp );
if ( set == null ) {
set = new HashSet<OWLClassExpression>();
domains.put( dp, set );
} else {
set.clear();
set.add( owlKlass );
}
}
private void setRange(Map<OWLProperty, Set<OWLClassExpression>> ranges, OWLProperty rp, OWLClassExpression owlKlass, OWLDataFactory factory ) {
Set<OWLClassExpression> set = ranges.get( rp );
if ( set == null ) {
set = new HashSet<OWLClassExpression>();
ranges.put( rp, set );
} else {
set.clear();
set.add( owlKlass );
}
}
private boolean validate( OntoModel model ) {
for ( PropertyRelation rel : model.getProperties() ) {
if ( ! rel.isRestricted() ) {
if ( rel != rel.getBaseProperty() ) {
throw new IllegalStateException( "Property is not restricted, but not a base property either " + rel + " >> base " + rel.getBaseProperty() );
}
}
for ( PropertyRelation rest : rel.getRestrictedProperties() ) {
checkForRestriction( rest, rel, rel.getBaseProperty() );
}
}
return true;
}
private void checkForRestriction( PropertyRelation restricted, PropertyRelation parent, PropertyRelation base ) {
if ( restricted.getBaseProperty() != base ) {
throw new IllegalStateException( "Inconsistent base property for" + restricted + " >> base " + restricted.getBaseProperty() + " , expected " + base );
}
if ( restricted.getImmediateBaseProperty() != parent ) {
throw new IllegalStateException( "Inconsistent parent property for" + restricted + " >> parent " + restricted.getImmediateBaseProperty() + " , expected " + parent );
}
int diff = diff( restricted, parent );
if ( 0 == diff ) {
throw new IllegalStateException( "Inconsistent restriction for " + restricted + " >> parent " + parent );
}
for ( PropertyRelation subRestr : restricted.getRestrictedProperties() ) {
checkForRestriction( subRestr, restricted, base );
}
}
private enum DIFF_BY {
DOMAIN( (byte) 1 ), RANGE( (byte) 2 ), MIN( (byte) 4 ), MAX( (byte) 8 );
DIFF_BY( byte x ) { bit = x; }
private byte bit;
public byte getBit() { return bit; }
}
private int diff( PropertyRelation restricted, PropertyRelation parent ) {
int diff = 0;
if ( ! restricted.getDomain().equals( parent.getDomain() ) ) {
diff |= DIFF_BY.DOMAIN.getBit();
}
if ( ! restricted.getTarget().equals( parent.getTarget() ) ) {
diff |= DIFF_BY.RANGE.getBit();
}
if ( restricted.getMinCard() == null && parent.getMinCard() != null
|| ! restricted.getMinCard().equals( parent.getMinCard() ) ) {
diff |= DIFF_BY.MIN.getBit();
}
if ( restricted.getMaxCard() == null && parent.getMaxCard() != null
|| restricted.getMaxCard() != null && parent.getMaxCard() == null
|| ( restricted.getMaxCard() != null && ! restricted.getMaxCard().equals( parent.getMaxCard() ) )
) {
diff |= DIFF_BY.MAX.getBit();
}
return diff;
}
private void launchReasoner( boolean dirty,
StatefulKnowledgeSession kSession,
OWLOntology ontoDescr,
List<InferredAxiomGenerator<? extends OWLAxiom>> axiomGenerators ) {
if ( dirty ) {
long now = new Date().getTime();
if ( logger.isInfoEnabled() ) {
logger.info( " START REASONER " );
}
InferredOntologyGenerator reasoner = initReasoner( kSession, ontoDescr, axiomGenerators );
reasoner.fillOntology( ontoDescr.getOWLOntologyManager(), ontoDescr );
if ( logger.isInfoEnabled() ) {
logger.info( " STOP REASONER : time elapsed >> " + ( new Date().getTime() - now ) );
}
} else {
if ( logger.isInfoEnabled() ) {
logger.info( " REASONER NOT NEEDED" );
}
}
}
protected InferredOntologyGenerator initReasoner( StatefulKnowledgeSession kSession,
OWLOntology ontoDescr,
List<InferredAxiomGenerator<? extends OWLAxiom>> axiomGenerators ) {
ConsoleProgressMonitor progressMonitor = new ConsoleProgressMonitor();
OWLReasonerConfiguration config = new SimpleConfiguration(progressMonitor);
OWLReasonerFactory reasonerFactory = new Reasoner.ReasonerFactory();
// if ( owler == null ) {
OWLReasoner owler = reasonerFactory.createReasoner( ontoDescr, config );
owler.precomputeInferences(
InferenceType.CLASS_HIERARCHY,
InferenceType.CLASS_ASSERTIONS,
InferenceType.OBJECT_PROPERTY_ASSERTIONS,
InferenceType.DATA_PROPERTY_ASSERTIONS,
InferenceType.DIFFERENT_INDIVIDUALS,
InferenceType.SAME_INDIVIDUAL,
InferenceType.DISJOINT_CLASSES,
// InferenceType.DATA_PROPERTY_HIERARCHY,
InferenceType.OBJECT_PROPERTY_HIERARCHY
);
if ( ! owler.isConsistent() ) {
throw new RuntimeException( "Inconsistent ontology " );
}
return new InferredOntologyGenerator( owler, axiomGenerators );
}
}