/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.apache.jena.reasoner;
import java.util.*;
import org.apache.jena.graph.* ;
import org.apache.jena.rdf.model.* ;
import org.apache.jena.reasoner.rulesys.* ;
import org.apache.jena.reasoner.transitiveReasoner.TransitiveReasonerFactory ;
import org.apache.jena.vocabulary.* ;
/**
* A global registry of known reasoner modules. Modules are identified
* by a URI and can have associated capability and descriptive
* information, in RDF. Currently the schema/ontology for such
* descriptions is mostly open. However, we do ensure that each reasoner
* URI at least has an associated rdf:type statement to indicate that it
* is a reasoner.
* <p>
* It is up to each reasoner or some associated configuration system
* to register it in this registry. </p>
*/
public class ReasonerRegistry {
/** Single global instance of the registry */
protected static ReasonerRegistry theRegistry;
/** Map from reasoner URI to the associated factory */
protected Map<String, ReasonerFactory> reasonerFactories = new HashMap<>();
/** Union of the all reasoner capability descriptions */
protected Model allDescriptions;
/**
* Constructor is hidden - go via theRegistry
*/
private ReasonerRegistry() {
allDescriptions = ModelFactory.createDefaultModel();
// Preload the known Jena reasoners
register(TransitiveReasonerFactory.theInstance());
register(RDFSRuleReasonerFactory.theInstance());
register(OWLFBRuleReasonerFactory.theInstance());
register(GenericRuleReasonerFactory.theInstance());
register(OWLMicroReasonerFactory.theInstance());
register(OWLMiniReasonerFactory.theInstance());
}
/**
* Return the single global instance of the registry
*/
public static ReasonerRegistry theRegistry() {
if (theRegistry == null) {
theRegistry = new ReasonerRegistry();
}
return theRegistry;
}
/**
* Register a Reasoner.
* @param factory an factory that can be used to create instances of the reasoner
*/
public void register(ReasonerFactory factory) {
reasonerFactories.put(factory.getURI(), factory);
Model description = factory.getCapabilities();
if (description != null) {
allDescriptions.add(description);
}
allDescriptions.createResource(factory.getURI())
.addProperty(RDF.type, ReasonerVocabulary.ReasonerClass);
}
/**
* Register a Reasoner - simple case with no RDF description.
* @param factory an factory that can be used to create instances of the reasoner
* @param reasonerUri the URI used to label the reasoner, expressed as a
* simple string
*/
public void register(String reasonerUri, ReasonerFactory factory) {
reasonerFactories.put(reasonerUri, factory);
allDescriptions.createResource(reasonerUri)
.addProperty(RDF.type, ReasonerVocabulary.ReasonerClass);
}
/**
* Return a composite set of RDF capability descriptions for all registered reasoners.
* Listing all Resources of type ReasonerClass in the returned model
* would enumerate all registered reasoners.
*/
public Model getAllDescriptions() {
return allDescriptions;
}
/**
* Return information on a given Reasoner.
* @param uri the URI of the reasoner
* @return a Resource representing the reasoner whose properties (as obtainable
* through listProperties etc) give a capability description of the reasoner;
* returns null if no such reasoner is registered.
*/
public Resource getDescription(String uri) {
Resource reasonerURI = allDescriptions.getResource(uri);
if (allDescriptions.contains(reasonerURI, RDF.type, ReasonerVocabulary.ReasonerClass)) {
return reasonerURI;
} else {
return null;
}
}
/**
* Return the factory for the given reasoner.
* @param uri the URI of the reasoner
* @return the ReasonerFactory instance for this reasoner
*/
public ReasonerFactory getFactory(String uri) {
return reasonerFactories.get(uri);
}
/**
* Create and return a new instance of the reasoner identified by
* the given uri.
* @param uri the uri of the reasoner to be created, expressed as a simple string
* @param configuration an optional set of configuration information encoded in RDF this
* parameter can be null if no configuration information is required.
* @return a reaoner instance
* @throws ReasonerException if there is not such reasoner or if there is
* some problem during instantiation
*/
public Reasoner create(String uri, Resource configuration) throws ReasonerException {
ReasonerFactory factory = getFactory(uri);
if (factory != null) {
return factory.create(configuration);
} else {
throw new ReasonerException("Attempted to instantiate an unknown reasoner: " + uri);
}
}
/**
* Return a property Node which represents the direct version of a
* transitively closed property. See <code>makeDirect(String)</code>;
* this method makes a new Node with the direct respelling of
* <code>node</code>s URI.
*/
public static Node makeDirect(Node node) {
return NodeFactory.createURI( makeDirect( node.getURI() ) );
}
/**
* Return a URI string which represents the direct version of a
* transitively closed property URI
*
* <p>Not clear what the right thing to do here is. Should not just invent
* a new local name in the same namespace because that might be a controlled
* namespace like RDF or RDFS. Can't even just extend the namespace slightly
* because that would be violating the web principles of namespace ownership.
* On the other hand, this solution results in staggeringly clumsy names.</p>
*
* @param uri the URI representing the transitive property
*/
public static String makeDirect( String uri )
{ return "urn:x-hp-direct-predicate:" + uri.replace( ':' ,'_' ); }
/** Prebuilt standard configuration for the default RDFS reasoner. */
protected static Reasoner theRDFSReasoner = null;
/**
* Return a prebuilt standard configuration for the default RDFS reasoner
*/
public static Reasoner getRDFSReasoner() {
if (theRDFSReasoner == null) theRDFSReasoner = RDFSRuleReasonerFactory.theInstance().create(null);
return theRDFSReasoner;
}
/** Prebuilt standard configuration for the default RDFS reasoner. */
protected static Reasoner theRDFSSimpleReasoner = null;
/**
* Return a prebuilt simplified configuration for the default RDFS reasoner
*/
public static Reasoner getRDFSSimpleReasoner() {
if (theRDFSSimpleReasoner == null) {
theRDFSSimpleReasoner = RDFSRuleReasonerFactory.theInstance().create(null);
theRDFSSimpleReasoner.setParameter(ReasonerVocabulary.PROPsetRDFSLevel, ReasonerVocabulary.RDFS_SIMPLE);
}
return theRDFSSimpleReasoner;
}
/** Prebuilt standard configuration for the default subclass/subproperty transitive closure reasoner. */
protected static Reasoner theTRANSITIVEReasoner;
/**
* Return a prebuilt standard configuration for the default subclass/subproperty transitive closure reasoner.
*/
public static Reasoner getTransitiveReasoner() {
if (theTRANSITIVEReasoner == null) theTRANSITIVEReasoner = TransitiveReasonerFactory.theInstance().create(null);
return theTRANSITIVEReasoner;
}
/** Prebuilt standard configuration OWL reasoner */
protected static Reasoner theOWLReasoner;
/**
* Prebuilt standard configuration for the default OWL reasoner. This configuration is
* hybrid forward/backward reasoner.
*/
public static Reasoner getOWLReasoner() {
if (theOWLReasoner == null) theOWLReasoner = OWLFBRuleReasonerFactory.theInstance().create(null);
return theOWLReasoner;
}
/** Prebuilt micro configuration OWL reasoner */
protected static Reasoner theOWLMicroReasoner;
/**
* Prebuilt standard configuration a micro-OWL reasoner. This just supports property axioms,
* and class inheritance sufficient to power the OntAPI.
*/
public static Reasoner getOWLMicroReasoner() {
if (theOWLMicroReasoner == null) theOWLMicroReasoner = OWLMicroReasonerFactory.theInstance().create(null);
return theOWLMicroReasoner;
}
/** Prebuilt mini configuration OWL reasoner */
protected static Reasoner theOWLMiniReasoner;
/**
* Prebuilt mini configuration for the default OWL reasoner. This omits bNode
* introduction rules which has significant performance gain in some cases and
* avoids breaking the find contract.
*/
public static Reasoner getOWLMiniReasoner() {
if (theOWLMiniReasoner == null) theOWLMiniReasoner = OWLMiniReasonerFactory.theInstance().create(null);
return theOWLMiniReasoner;
}
}