/*
* 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.stanbol.ontologymanager.registry.impl;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.serializedform.Parser;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Property;
import org.apache.felix.scr.annotations.PropertyOption;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.stanbol.commons.owl.OWLOntologyManagerFactory;
import org.apache.stanbol.commons.stanboltools.datafileprovider.DataFileProvider;
import org.apache.stanbol.ontologymanager.multiplexer.clerezza.ontology.ClerezzaOntologyProvider;
import org.apache.stanbol.ontologymanager.registry.api.RegistryContentException;
import org.apache.stanbol.ontologymanager.registry.api.RegistryContentListener;
import org.apache.stanbol.ontologymanager.registry.api.RegistryItemFactory;
import org.apache.stanbol.ontologymanager.registry.api.RegistryManager;
import org.apache.stanbol.ontologymanager.registry.api.model.CachingPolicy;
import org.apache.stanbol.ontologymanager.registry.api.model.Library;
import org.apache.stanbol.ontologymanager.registry.api.model.Registry;
import org.apache.stanbol.ontologymanager.registry.api.model.RegistryItem;
import org.apache.stanbol.ontologymanager.registry.api.model.RegistryItem.Type;
import org.apache.stanbol.ontologymanager.registry.api.model.RegistryOntology;
import org.apache.stanbol.ontologymanager.registry.impl.util.RegistryUtils;
import org.apache.stanbol.ontologymanager.registry.xd.vocabulary.CODOVocabulary;
import org.apache.stanbol.ontologymanager.servicesapi.OfflineConfiguration;
import org.apache.stanbol.ontologymanager.servicesapi.ontology.OntologyProvider;
import org.osgi.service.component.ComponentContext;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.io.IRIDocumentSource;
import org.semanticweb.owlapi.io.OWLOntologyDocumentSource;
import org.semanticweb.owlapi.io.StreamDocumentSource;
import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAnnotationAssertionAxiom;
import org.semanticweb.owlapi.model.OWLAnnotationProperty;
import org.semanticweb.owlapi.model.OWLAnnotationValue;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLAxiomVisitor;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLClassExpression;
import org.semanticweb.owlapi.model.OWLDataFactory;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLNamedObject;
import org.semanticweb.owlapi.model.OWLObject;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyAlreadyExistsException;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.model.OWLOntologyLoaderConfiguration;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.util.OWLAxiomVisitorAdapter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Default implementation of the registry manager, that listens to requests on its referenced resources and
* issues loading requests accordingly.
*
* @author alexdma
*/
@Component(immediate = true, metatype = true)
@Service(RegistryManager.class)
public class RegistryManagerImpl implements RegistryManager, RegistryContentListener {
private static final CachingPolicy _CACHING_POLICY_DEFAULT = CachingPolicy.CENTRALISED;
private static final boolean _LAZY_LOADING_DEFAULT = true;
private static final boolean _RETAIN_INCOMPLETE_DEFAULT = true;
private static final OWLClass cRegistryLibrary, cOntology;
private static final OWLAnnotationProperty hasOntologyAnn, isOntologyOfAnn;
private static final OWLObjectProperty hasOntology, isOntologyOf;
static {
OWLDataFactory factory = OWLManager.getOWLDataFactory();
cOntology = factory.getOWLClass(IRI.create(CODOVocabulary.CODK_Ontology));
cRegistryLibrary = factory.getOWLClass(IRI.create(CODOVocabulary.CODD_OntologyLibrary));
isOntologyOf = factory.getOWLObjectProperty(IRI.create(CODOVocabulary.ODPM_IsOntologyOf));
hasOntology = factory.getOWLObjectProperty(IRI.create(CODOVocabulary.ODPM_HasOntology));
hasOntologyAnn = factory.getOWLAnnotationProperty(IRI.create(CODOVocabulary.ODPM_HasOntology));
isOntologyOfAnn = factory.getOWLAnnotationProperty(IRI.create(CODOVocabulary.ODPM_IsOntologyOf));
}
@Reference
private OntologyProvider<?> cache;
@Property(name = RegistryManager.CACHING_POLICY, options = {
@PropertyOption(value = '%'
+ RegistryManager.CACHING_POLICY
+ ".option.distributed", name = "DISTRIBUTED"),
@PropertyOption(value = '%'
+ RegistryManager.CACHING_POLICY
+ ".option.centralised", name = "CENTRALISED")}, value = "CENTRALISED")
private String cachingPolicyString;
@Reference
private DataFileProvider dataFileProvider;
@Property(name = RegistryManager.LAZY_LOADING, boolValue = _LAZY_LOADING_DEFAULT)
private boolean lazyLoading = _LAZY_LOADING_DEFAULT;
/* Maps registries to libraries */
private Map<IRI,Set<IRI>> libraryIndex = new HashMap<IRI,Set<IRI>>();
@Property(name = RegistryManager.REGISTRY_LOCATIONS, cardinality = 1000, value = {"stanbol_network.owl"})
private String[] locations;
private Logger log = LoggerFactory.getLogger(getClass());
@Reference
private OfflineConfiguration offline;
/*
* Maps libraries (values) to ontologies (keys). This does not keep track of the loading status of each
* library, as it is handled by the library itelf.
*/
private Map<IRI,Set<IRI>> ontologyIndex = new HashMap<IRI,Set<IRI>>();
private Map<IRI,RegistryItem> population = new TreeMap<IRI,RegistryItem>();
private Set<IRI> registries = new HashSet<IRI>();
@Property(name = RegistryManager.RETAIN_INCOMPLETE, boolValue = _RETAIN_INCOMPLETE_DEFAULT)
private boolean retainIncomplete = _RETAIN_INCOMPLETE_DEFAULT;
private RegistryItemFactory riFactory;
/**
* This default constructor is <b>only</b> intended to be used by the OSGI environment with Service
* Component Runtime support.
* <p>
* DO NOT USE to manually create instances - the RegistryManagerImpl instances do need to be configured!
* YOU NEED TO USE {@link #RegistryManagerImpl(OfflineConfiguration, OntologyProvider, Dictionary))} or
* its overloads, to parse the configuration and then initialise the rule store if running outside an OSGI
* environment.
*/
public RegistryManagerImpl() {}
/**
* To be invoked by non-OSGi environments.
*
* @param the
* configuration registry manager-specific configuration
*/
public RegistryManagerImpl(OfflineConfiguration offline,
OntologyProvider<?> cache,
Dictionary<String,Object> configuration) {
this();
this.offline = offline;
this.cache = cache;
activate(configuration);
}
@SuppressWarnings("unchecked")
@Activate
protected void activate(ComponentContext context) {
log.info("in {} activate with context {}", getClass(), context);
if (context == null) {
throw new IllegalStateException("No valid" + ComponentContext.class + " parsed in activate!");
}
activate((Dictionary<String,Object>) context.getProperties());
}
protected void activate(Dictionary<String,Object> configuration) {
// Parse configuration.
try {
lazyLoading = (Boolean) (configuration.get(RegistryManager.LAZY_LOADING));
} catch (Exception ex) {
lazyLoading = _LAZY_LOADING_DEFAULT;
}
try {
retainIncomplete = (Boolean) (configuration.get(RegistryManager.RETAIN_INCOMPLETE));
} catch (Exception ex) {
retainIncomplete = _RETAIN_INCOMPLETE_DEFAULT;
}
Object obj = configuration.get(RegistryManager.REGISTRY_LOCATIONS);
if (obj instanceof String[]) locations = (String[]) obj;
else if (obj instanceof String) locations = new String[] {(String) obj};
if (locations == null) locations = new String[] {"stanbol_network.owl"};
Object cachingPolicy = configuration.get(RegistryManager.CACHING_POLICY);
if (cachingPolicy == null) {
this.cachingPolicyString = _CACHING_POLICY_DEFAULT.name();
} else {
this.cachingPolicyString = cachingPolicy.toString();
}
final IRI[] offlineResources;
if (this.offline != null) {
List<IRI> paths = offline.getOntologySourceLocations();
if (paths != null) offlineResources = paths.toArray(new IRI[0]);
// There are no offline paths.
else offlineResources = new IRI[0];
}
// There's no offline configuration at all.
else offlineResources = new IRI[0];
// Used only for creating the registry model, do not use for caching.
OWLOntologyManager mgr = OWLOntologyManagerFactory.createOWLOntologyManager(offlineResources);
OWLOntologyLoaderConfiguration conf = new OWLOntologyLoaderConfiguration();
// If we are retaining incomplete registries, do not throw exceptions if imports fail.
conf.setSilentMissingImportsHandling(retainIncomplete);
// Load registries
Set<OWLOntology> regOnts = new HashSet<OWLOntology>();
for (String loc : locations) {
try {
IRI iri = IRI.create(loc);
OWLOntologyDocumentSource src = null;
OWLOntology o = null;
if (iri.isAbsolute()) src = new IRIDocumentSource(iri);
else {
// Relative IRI : use data file provider
log.debug("Found relative IRI {} . Will try to retrieve from data file providers.", iri);
Map<String,String> info = new HashMap<String,String>();
if (dataFileProvider != null && dataFileProvider.isAvailable(null, loc, info)) src = new StreamDocumentSource(
dataFileProvider.getInputStream(null, loc, info));
}
if (src != null) o = mgr.loadOntologyFromOntologyDocument(src, conf);
if (o != null) regOnts.add(o);
else log.warn("Failed to obtain OWL ontology from resource {}", loc);
} catch (OWLOntologyAlreadyExistsException e) {
log.info("Skipping cached ontology {}.", e.getOntologyID());
continue;
} catch (OWLOntologyCreationException e) {
log.warn("Failed to load ontology " + loc + " - Skipping...", e);
continue;
} catch (Exception e) {
log.warn("Invalid registry configuration " + loc + " - Skipping...", e);
continue;
}
}
// Create and set the cache.
if (cachingPolicyString.equals(CachingPolicy.CENTRALISED.name())) {
// this.cache = OWLOntologyManagerFactory.createOWLOntologyManager(offlineResources);
if (cache == null) {
log.warn("Caching policy is set as Centralised, but no ontology provider is supplied. Will use new in-memory tcProvider.");
cache = new ClerezzaOntologyProvider(TcManager.getInstance(), offline, Parser.getInstance());
}
// else sta bene cosi'
} else if (cachingPolicyString.equals(CachingPolicy.DISTRIBUTED.name())) {
this.cache = null;
}
riFactory = new RegistryItemFactoryImpl(cache);
// Build the model.
createModel(regOnts);
// Set the cache on libraries.
Set<RegistryItem> visited = new HashSet<RegistryItem>();
for (Registry reg : getRegistries())
for (RegistryItem child : reg.getChildren())
if (!visited.contains(child)) {
if (child instanceof Library) {
if (this.cache != null) ((Library) child).setCache(this.cache);
else ((Library) child).setCache(new ClerezzaOntologyProvider(TcManager.getInstance(),
offline, Parser.getInstance()));
}
visited.add(child);
}
if (isLazyLoading()) {
// Nothing to do about it at the moment.
} else {
loadEager();
}
}
@Override
public void addRegistry(Registry registry) {
// TODO: automatically set the cache if unset or non conform to the caching policy.
try {
population.put(registry.getIRI(), registry);
registries.add(registry.getIRI());
updateLocations();
} catch (Exception e) {
log.error("Failed to add ontology registry.", e);
}
}
@Override
public void clearRegistries() {
for (IRI id : registries)
if (registries.remove(id)) population.remove(id);
updateLocations();
}
/**
* @deprecated with each library having its own cache, load balancing is no longer necessary
* @return
*/
protected Registry computeBestCandidate(Library lib) {
Map<IRI,Float> loadFactors = computeLoadFactors();
IRI current = null;
float lowest = 1.0f;
for (RegistryItem item : lib.getParents()) {
IRI iri = item.getIRI();
if (loadFactors.containsKey(iri)) {
float f = loadFactors.get(iri);
if (f < lowest) {
lowest = f;
current = iri;
}
}
}
return (Registry) (population.get(current));
}
/**
* @deprecated with each library having its own cache, load balancing is no longer necessary
* @return
*/
protected Map<IRI,Float> computeLoadFactors() {
Map<IRI,Float> loadFactors = new HashMap<IRI,Float>();
for (Registry r : getRegistries()) {
int tot = 0, num = 0;
RegistryItem[] children = r.getChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] instanceof Library) {
if (((Library) children[i]).isLoaded()) num++;
tot++;
}
}
loadFactors.put(r.getIRI(), (float) num / (float) tot);
}
return loadFactors;
}
@Override
public Set<Registry> createModel(Set<OWLOntology> registryOntologies) {
Set<Registry> results = new HashSet<Registry>();
// Reset population
population.clear();
// Build the transitive imports closure of the union.
Set<OWLOntology> closure = new HashSet<OWLOntology>();
for (OWLOntology rego : registryOntologies)
closure.addAll(rego.getOWLOntologyManager().getImportsClosure(rego));
/*
* For each value in this map, index 0 is the score of the library class, while 1 is the score of the
* ontology class.
*/
final Map<IRI,int[]> candidateTypes = new HashMap<IRI,int[]>();
/*
* Scans class assertions and object property values and tries to determine the type of each
* individual it finds.
*/
OWLAxiomVisitor scanner = new OWLAxiomVisitorAdapter() {
/*
* For a given identifier, returns the array of integers whose value determine the likelihood if
* the corresponding entity being a library or an ontology. If no such array exists, it is
* created.
*/
private int[] checkScores(IRI key) {
int[] scores;
if (candidateTypes.containsKey(key)) scores = candidateTypes.get(key);
else {
scores = new int[] {0, 0};
candidateTypes.put(key, scores);
}
return scores;
}
@Override
public void visit(OWLAnnotationAssertionAxiom axiom) {
/*
* Works like object property assertions, in case hasOntology and isOntologyOf are not
* detected to be object properties (e.g. due to a failure to load codolight or the registry
* metamodel).
*/
OWLAnnotationProperty prop = axiom.getProperty();
if (hasOntologyAnn.equals(prop)) {
IRI iri;
// The axiom subject gets a +1 in its library score.
OWLObject ind = axiom.getSubject();
if (ind instanceof IRI) {
iri = (IRI) ind;
checkScores(iri)[0]++;
}
// The axiom object gets a +1 in its ontology score.
ind = axiom.getValue();
if (ind instanceof IRI) {
iri = (IRI) ind;
checkScores(iri)[1]++;
}
} else if (isOntologyOfAnn.equals(prop)) {
IRI iri;
// The axiom subject gets a +1 in its ontology score.
OWLObject ind = axiom.getSubject();
if (ind instanceof IRI) {
iri = (IRI) ind;
checkScores(iri)[1]++;
}
// The axiom object gets a +1 in its library score.
ind = axiom.getValue();
if (ind instanceof IRI) {
iri = (IRI) ind;
checkScores(iri)[0]++;
}
}
}
@Override
public void visit(OWLClassAssertionAxiom axiom) {
OWLIndividual ind = axiom.getIndividual();
// Do not accept anonymous registry items.
if (ind.isAnonymous()) return;
IRI iri = ind.asOWLNamedIndividual().getIRI();
int[] scores = checkScores(iri);
OWLClassExpression type = axiom.getClassExpression();
// If the type is stated to be a library, increase its library score.
if (cRegistryLibrary.equals(type)) {
scores[0]++;
} else
// If the type is stated to be an ontology, increase its ontology score.
if (cOntology.equals(type)) {
scores[1]++;
}
}
@Override
public void visit(OWLObjectPropertyAssertionAxiom axiom) {
OWLObjectPropertyExpression prop = axiom.getProperty();
if (hasOntology.equals(prop)) {
IRI iri;
// The axiom subject gets a +1 in its library score.
OWLIndividual ind = axiom.getSubject();
if (!ind.isAnonymous()) {
iri = ind.asOWLNamedIndividual().getIRI();
checkScores(iri)[0]++;
}
// The axiom object gets a +1 in its ontology score.
ind = axiom.getObject();
if (!ind.isAnonymous()) {
iri = ind.asOWLNamedIndividual().getIRI();
checkScores(iri)[1]++;
}
} else if (isOntologyOf.equals(prop)) {
IRI iri;
// The axiom subject gets a +1 in its ontology score.
OWLIndividual ind = axiom.getSubject();
if (!ind.isAnonymous()) {
iri = ind.asOWLNamedIndividual().getIRI();
checkScores(iri)[1]++;
}
// The axiom object gets a +1 in its library score.
ind = axiom.getObject();
if (!ind.isAnonymous()) {
iri = ind.asOWLNamedIndividual().getIRI();
checkScores(iri)[0]++;
}
}
}
};
// First pass to determine the types.
for (OWLOntology o : closure)
for (OWLAxiom ax : o.getAxioms())
ax.accept(scanner);
// Then populate on the registry
OWLDataFactory df = OWLManager.getOWLDataFactory();
for (IRI iri : candidateTypes.keySet()) {
int[] scores = candidateTypes.get(iri);
if (scores != null && (scores[0] > 0 || scores[1] > 0)) {
if (scores[0] > 0 && scores[1] == 0) population.put(iri,
riFactory.createLibrary(df.getOWLNamedIndividual(iri)));
else if (scores[0] == 0 && scores[1] > 0) population.put(iri,
riFactory.createRegistryOntology(df.getOWLNamedIndividual(iri)));
}
// else log.warn("Unable to determine type for registry item {}", iri);
}
for (OWLOntology oReg : registryOntologies) {
try {
results.add(populateRegistry(oReg));
} catch (RegistryContentException e) {
log.error("An error occurred while populating an ontology registry.", e);
}
}
return results;
}
@Deactivate
protected void deactivate(ComponentContext context) {
lazyLoading = _LAZY_LOADING_DEFAULT;
locations = null;
log.info("in {} deactivate with context {}", getClass(), context);
}
@Override
public CachingPolicy getCachingPolicy() {
try {
return CachingPolicy.valueOf(cachingPolicyString);
} catch (IllegalArgumentException e) {
log.warn("The value \"" + cachingPolicyString
+ "\" configured as default CachingPolicy does not match any value of the Enumeration! "
+ "Return the default policy as defined by the " + CachingPolicy.class + ".");
return _CACHING_POLICY_DEFAULT;
}
}
@Override
public Set<Library> getLibraries() {
Set<Library> results = new HashSet<Library>();
for (IRI key : population.keySet()) {
RegistryItem item = population.get(key);
if (item instanceof Library) results.add((Library) item);
}
return results;
}
@Override
public Set<Library> getLibraries(IRI ontologyID) {
Set<Library> results = new HashSet<Library>();
RegistryItem ri = population.get(ontologyID);
if (ri != null) for (RegistryItem item : ri.getParents())
if (item instanceof Library) results.add((Library) item);
return results;
}
@Override
public Library getLibrary(IRI id) {
RegistryItem item = population.get(id);
if (item != null && item instanceof Library) return (Library) item;
return null;
}
@Override
public OfflineConfiguration getOfflineConfiguration() {
return offline;
}
@Override
public Set<Registry> getRegistries() {
Set<Registry> results = new HashSet<Registry>();
for (IRI key : population.keySet()) {
RegistryItem item = population.get(key);
if (item instanceof Registry) results.add((Registry) item);
}
return results;
}
@Override
public Set<Registry> getRegistries(IRI libraryID) {
Set<Registry> results = new HashSet<Registry>();
try {
for (RegistryItem item : population.get(libraryID).getParents())
if (item instanceof Registry) results.add((Registry) item);
} catch (NullPointerException ex) {
return results;
}
return results;
}
@Override
public Registry getRegistry(IRI id) {
RegistryItem item = population.get(id);
return item != null && item instanceof Registry ? (Registry) item : null;
}
@Override
public boolean isLazyLoading() {
return lazyLoading;
}
private void loadEager() {
for (RegistryItem item : population.values()) {
if (item instanceof Library && !((Library) item).isLoaded()) {
// TODO: implement ontology request targets.
if (CachingPolicy.CENTRALISED.equals(getCachingPolicy()) && this.cache != null) {
((Library) item).loadOntologies(this.cache);
} else if (CachingPolicy.DISTRIBUTED.equals(getCachingPolicy())) {
Library lib = (Library) item;
lib.loadOntologies(lib.getCache());
} else {
log.error("Tried to load ontology resource {} using a null cache.", item);
}
}
}
}
protected Library populateLibrary(OWLNamedObject ind, Set<OWLOntology> registries) throws RegistryContentException {
IRI libId = ind.getIRI();
RegistryItem lib = null;
if (population.containsKey(libId)) {
// We are not allowing multityping either.
lib = population.get(libId);
if (!(lib instanceof Library)) throw new RegistryContentException(
"Inconsistent multityping: for item " + libId + " : {" + Library.class + ", "
+ lib.getClass() + "}");
} else {
lib = riFactory.createLibrary(ind);
try {
population.put(lib.getIRI(), lib);
} catch (Exception e) {
log.error("Invalid identifier for library item " + lib, e);
return null;
}
}
// EXIT nodes.
Set<OWLNamedObject> ironts = new HashSet<OWLNamedObject>();
OWLDataFactory df = OWLManager.getOWLDataFactory();
for (OWLOntology o : registries) {
if (ind instanceof OWLIndividual) {
// Get usages of hasOntology as an object property
for (OWLIndividual value : ((OWLIndividual) ind).getObjectPropertyValues(hasOntology, o))
if (value.isNamed()) ironts.add(value.asOWLNamedIndividual());
// Get usages of hasOntology as an annotation property
for (OWLAnnotationAssertionAxiom ann : o.getAnnotationAssertionAxioms(ind.getIRI()))
if (hasOntologyAnn.equals(ann.getProperty())) {
OWLAnnotationValue value = ann.getValue();
if (value instanceof OWLNamedObject) ironts.add((OWLNamedObject) value);
else if (value instanceof IRI) ironts.add(df.getOWLNamedIndividual((IRI) value));
}
}
}
for (OWLNamedObject iront : ironts) {
IRI childId = iront.getIRI();
// If some populate*() method has created it, it will be there.
RegistryItem ront = population.get(childId);
// Otherwise populating it will also put it in population.
if (ront == null) ront = populateOntology(iront, registries);
lib.addChild(ront);
if (ontologyIndex.get(childId) == null) ontologyIndex.put(childId, new HashSet<IRI>());
ontologyIndex.get(childId).add(libId);
}
return (Library) lib;
}
protected RegistryOntology populateOntology(OWLNamedObject ind, Set<OWLOntology> registries) throws RegistryContentException {
IRI ontId = ind.getIRI();
RegistryItem ront = null;
if (population.containsKey(ontId)) {
// We are not allowing multityping either.
ront = population.get(ontId);
if (!(ront instanceof RegistryOntology)) throw new RegistryContentException(
"Inconsistent multityping: for item " + ontId + " : {" + RegistryOntology.class + ", "
+ ront.getClass() + "}");
} else {
ront = riFactory.createRegistryOntology(ind);
try {
population.put(ront.getIRI(), ront);
} catch (Exception e) {
log.error("Invalid identifier for library item " + ront, e);
return null;
}
}
// EXIT nodes.
Set<OWLNamedObject> libs = new HashSet<OWLNamedObject>();
OWLDataFactory df = OWLManager.getOWLDataFactory();
for (OWLOntology o : registries) {
if (ind instanceof OWLIndividual) {
// Get usages of isOntologyOf as an object property
for (OWLIndividual value : ((OWLIndividual) ind).getObjectPropertyValues(isOntologyOf, o))
if (value.isNamed()) libs.add(value.asOWLNamedIndividual());
// Get usages of isOntologyOf as an annotation property
for (OWLAnnotationAssertionAxiom ann : o.getAnnotationAssertionAxioms(ind.getIRI()))
if (isOntologyOfAnn.equals(ann.getProperty())) {
OWLAnnotationValue value = ann.getValue();
if (value instanceof OWLNamedObject) libs.add((OWLNamedObject) value);
else if (value instanceof IRI) libs.add(df.getOWLNamedIndividual((IRI) value));
}
}
}
for (OWLNamedObject ilib : libs) {
IRI parentId = ilib.getIRI();
// If some populate*() method has created it, it will be there.
RegistryItem rlib = population.get(parentId);
// Otherwise populating it will also put it in population.
if (rlib == null) rlib = populateLibrary(ilib, registries);
ront.addParent(rlib);
if (ontologyIndex.get(ontId) == null) ontologyIndex.put(ontId, new HashSet<IRI>());
ontologyIndex.get(ontId).add(parentId);
}
return (RegistryOntology) ront;
}
protected Registry populateRegistry(OWLOntology registry) throws RegistryContentException {
log.debug("Populating registry content from ontology {}", registry);
Registry reg = riFactory.createRegistry(registry);
Set<OWLOntology> closure = registry.getOWLOntologyManager().getImportsClosure(registry);
// Just scan all individuals. Recurse in case the registry imports more registries.
for (OWLIndividual ind : registry.getIndividualsInSignature(true)) {
// We do not allow anonymous registry items.
if (ind.isAnonymous()) continue;
RegistryItem item = null;
// IRI id = ind.asOWLNamedIndividual().getIRI();
Type t = RegistryUtils.getType(ind, closure);
if (t == null) {
log.warn("Undetermined type for registry ontology individual {}", ind);
continue;
}
switch (t) {
case LIBRARY:
log.debug("Found library for individual {}", ind);
// Create the library and attach to parent and children
item = populateLibrary(ind.asOWLNamedIndividual(), closure);
reg.addChild(item);
item.addRegistryContentListener(this);
break;
case ONTOLOGY:
log.debug("Found ontology for individual {}", ind);
// Create the ontology and attach to parent
item = populateOntology(ind.asOWLNamedIndividual(), closure);
item.addRegistryContentListener(this);
// We don't know where to attach it within this method.
break;
default:
break;
}
}
try {
reg.addRegistryContentListener(this);
log.info("Registry {} added.", reg.getIRI());
population.put(reg.getIRI(), reg);
} catch (Exception e) {
log.error("Invalid identifier for library item " + reg, e);
return null;
}
return reg;
}
@Override
public void registryContentRequested(RegistryItem requestTarget) {
log.debug("In {} registry content was requested on {}.", getClass(), requestTarget);
// TODO: implement ontology request targets.
if (CachingPolicy.CENTRALISED.equals(getCachingPolicy()) && this.cache != null) {
if (requestTarget instanceof Library && !((Library) requestTarget).isLoaded()) ((Library) requestTarget)
.loadOntologies(this.cache);
} else if (CachingPolicy.DISTRIBUTED.equals(getCachingPolicy())) {
if (requestTarget instanceof Library && !((Library) requestTarget).isLoaded()) {
Library lib = (Library) requestTarget;
lib.loadOntologies(lib.getCache());
}
} else {
log.error("Tried to load ontology resource {} using a null cache.", requestTarget);
}
}
@Override
public void removeRegistry(IRI registryId) {
// TODO: automatically remove ontologies from the cache if centralised.
registries.remove(registryId);
updateLocations();
}
@Override
public void setLazyLoading(boolean lazy) {
// Warning: do not use in constructor!
this.lazyLoading = lazy;
if (!lazy) loadEager();
}
protected synchronized void updateLocations() {
Set<IRI> locations = Collections.unmodifiableSet(registries);
this.locations = locations.toArray(new String[0]);
}
}