
org.protempa.backend.ksb.protege.ConnectionManager Maven / Gradle / Ivy
/*
* #%L
* Protempa Protege Knowledge Source Backend
* %%
* Copyright (C) 2012 - 2013 Emory University
* %%
* 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.
* #L%
*/
package org.protempa.backend.ksb.protege;
import java.util.*;
import java.util.logging.Level;
import edu.stanford.smi.protege.event.ProjectListener;
import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protege.model.Frame;
import edu.stanford.smi.protege.model.Instance;
import edu.stanford.smi.protege.model.KnowledgeBase;
import edu.stanford.smi.protege.model.Project;
import edu.stanford.smi.protege.model.Slot;
import org.protempa.backend.KnowledgeSourceBackendInitializationException;
import org.protempa.KnowledgeSourceReadException;
/**
* Implements a wrapper around a connection to a remote Protege project.
* Implements retry capability if something happens to the connection.
*
* @param
* @author Andrew Post
*/
abstract class ConnectionManager {
/**
* Number of times we try to execute a command.
*/
private static final int TRIES = 3;
private final String projectIdentifier;
private Project project;
private KnowledgeBase protegeKnowledgeBase;
private List projectListeners;
/**
* Constructor with an identifier for the Protege project.
*
* @param projectIdentifier a name {@link String} for a knowledge base, cannot be
* null
.
*/
protected ConnectionManager(String projectIdentifier) {
if (projectIdentifier == null) {
throw new IllegalArgumentException(
"projectIdentifier cannot be null");
}
this.projectIdentifier = projectIdentifier;
this.projectListeners = new ArrayList<>();
}
/**
* Returns the project identifier.
*
* @return a {@link String} guaranteed not to be null
.
*/
String getProjectIdentifier() {
return this.projectIdentifier;
}
/**
* Opens the project.
*
* @throws KnowledgeSourceBackendInitializationException if an error
* occurs.
*/
void init() throws KnowledgeSourceBackendInitializationException {
if (this.project == null) {
Util.logger().log(Level.FINE, "Opening Protege project {0}",
this.projectIdentifier);
this.project = initProject();
if (this.project == null) {
throw new KnowledgeSourceBackendInitializationException(
"Could not load project " + this.projectIdentifier);
} else {
this.protegeKnowledgeBase = this.project.getKnowledgeBase();
Util.logger().log(Level.FINE,
"Project {0} opened successfully",
this.projectIdentifier);
}
}
}
/**
* Opens and returns the project in a way that is specific to whether
* the project is local or remote.
*
* @return a Protege {@link Project}.
*/
protected abstract Project initProject();
/**
* Closes the project.
*/
void close() {
if (this.project != null) {
Util.logger().log(Level.FINE, "Closing Protege project {0}",
this.projectIdentifier);
for (Iterator itr =
this.projectListeners.iterator(); itr.hasNext(); ) {
this.project.removeProjectListener(itr.next());
itr.remove();
}
try {
this.project.dispose();
Util.logger().fine("Done closing connection.");
} catch (IllegalStateException e) {
/*
* Protege registers a shutdown hook that is removed when
* dispose() is called on a project. However, we might call this
* method during an already started shutdown process. See
* documentation for java.lang.Runtime.removeShutdownHook. This
* exception should be harmless, unless there are other reasons
* dispose() could throw this exception?
*/
Util.logger().fine("Done closing connection.");
} finally {
this.project = null;
}
}
}
/**
* Adds a listener for changes in the project.
*
* @param listener a ProjectListener
.
*/
void addProjectListener(ProjectListener listener) {
if (listener != null) {
this.projectListeners.add(listener);
}
}
/**
* Removes a listener for changes in the project.
*
* @param listener a ProjectListener
.
*/
void removeProjectListener(ProjectListener listener) {
this.project.removeProjectListener(listener);
this.projectListeners.remove(listener);
}
/*
* GETTERS FOR THE PROJECT'S KNOWLEDGE BASE, WITH RETRY SUPPORT.
*/
/**
* Template for executing various commands upon the project's knowledge base.
*
* @param The type of what is returned by the getter.
* @param The type of what is passed to Protege as a parameter.
* @author Andrew Post
*/
private abstract class ProtegeCommand {
private String what;
/**
* Constructor.
*
* @param what what the command is doing, used for debugging.
*/
ProtegeCommand(String what) {
this.what = what;
}
/**
* Implement this with the protege command. This may assume that
* protegeKnowledgeBase
is not null
.
*
* @param obj the parameter to send to Protege.
* @return the object returned from Protege.
*/
abstract S get(T obj);
/**
* Does null
checks on protegeKnowledgeBase
* and obj
before calling the {@link #get(Object)}
* method.
*
* @param obj the parameter to pass to the Protege command.
* @return the object returned from Protege, or null
if
* protegeKnowledgeBase
or obj
is
* null
, or if null
is returned
* from the Protege command.
*/
final S getHelper(T obj) {
if (protegeKnowledgeBase != null && obj != null) {
return get(obj);
} else {
return null;
}
}
/**
* Returns a string representing what this command is doing.
*
* @return a String
.
*/
final String getWhat() {
return what;
}
}
/**
* Executes a command upon the Protege knowledge base, retrying if needed.
*
* @param The type of what is returned by the getter.
* @param The type of what is passed to protege as a parameter.
* @param obj What is passed to Protege as a parameter.
* @param getter the ProtegeCommand
.
* @return what is returned from the Protege command.
*/
private S getFromProtege(T obj, ProtegeCommand getter)
throws KnowledgeSourceReadException {
if (protegeKnowledgeBase != null && getter != null) {
int tries = TRIES;
Exception lastException = null;
do {
try {
return getter.getHelper(obj);
} catch (Exception e) {
lastException = e;
Util.logger().log(
Level.WARNING,
"Exception attempting to "
+ getter.getWhat() + " " + obj, e);
tries--;
}
close();
try {
init();
} catch (KnowledgeSourceBackendInitializationException e) {
throw new KnowledgeSourceReadException(
"Exception attempting to "
+ getter.getWhat() + " " + obj, e);
}
} while (tries > 0);
throw new KnowledgeSourceReadException(
"Failed to " + getter.getWhat() + " "
+ obj + " after "
+ TRIES + " tries", lastException);
}
return null;
}
/**
* Command for retrieving instances from the knowledge base.
*
* @see #getInstance(String)
*/
private final ProtegeCommand INSTANCE_GETTER =
new ProtegeCommand("get instance") {
/**
* Gets a specified instance from the knowledge base.
*
* @param name
* the instance's name String
.
* @return the Instance
, or null
if no
* instance with that name was found.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Instance get(String name) {
return protegeKnowledgeBase.getInstance(name);
}
};
/**
* Retrieves a specified instance from the knowledge base.
*
* @param name the instance's name String
.
* @return the Instance
, or null
if not
* found.
* @see ConnectionManager#INSTANCE_GETTER
*/
Instance getInstance(String name) throws KnowledgeSourceReadException {
return getFromProtege(name, INSTANCE_GETTER);
}
/**
* Command for retrieving instances of a cls from the knowledge base.
*
* @see #getInstances(Cls)
*/
private final ProtegeCommand, Cls> INSTANCES_GETTER =
new ProtegeCommand, Cls>("get instances") {
/**
* Gets all instances of a specified cls from the knowledge base.
*
* @param cls
* the Cls
.
* @return a Collection
of Instance
s.
* Guaranteed not to be null
.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Collection get(Cls cls) {
Collection result = protegeKnowledgeBase.getInstances(cls);
// Protect against Protege returning null (its API doesn't guarantee
// a non-null return value).
if (result != null) {
return result;
} else {
return new ArrayList<>(0);
}
}
};
/**
* Gets all instances of the specified cls from the knowledge base.
*
* @param cls a Cls
* @return a Collection
of Instance
s.
* Guaranteed not to be null
.
* @see ConnectionManager#INSTANCES_GETTER
*/
Collection getInstances(Cls cls)
throws KnowledgeSourceReadException {
return getFromProtege(cls, INSTANCES_GETTER);
}
/**
* Command for getting clses from the knowledge base.
*
* @see #getCls(String)
*/
private final ProtegeCommand CLS_GETTER =
new ProtegeCommand("get cls") {
/**
* Gets a cls from the knowledge base.
*
* @param name
* the cls's name String
.
* @return the Cls
, or null
if no cls
* with that name was found.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Cls get(String name) {
return protegeKnowledgeBase.getCls(name);
}
};
/**
* Gets the specified cls from the knowledge base.
*
* @param name the name String
of the cls.
* @return the Cls
, or null
if no cls with
* that name was found.
* @see ConnectionManager#CLS_GETTER
*/
Cls getCls(String name) throws KnowledgeSourceReadException {
return getFromProtege(name, CLS_GETTER);
}
/**
* Command for getting slots from the knowledge base.
*
* @see #getSlot(String)
*/
private final ProtegeCommand SLOT_GETTER =
new ProtegeCommand("get slot") {
/**
* Gets a slot from the knowledge base.
*
* @param name
* the slot's name String
.
* @return the Slot
, or null
if no slot
* with that name was found.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Slot get(String name) {
return protegeKnowledgeBase.getSlot(name);
}
};
/**
* Gets the specified slot from the knowledge base.
*
* @param name the name String
of the slot.
* @return the Slot
, or null
if no slot with
* that name was found.
* @see ConnectionManager#SLOT_GETTER
*/
Slot getSlot(String name) throws KnowledgeSourceReadException {
return getFromProtege(name, SLOT_GETTER);
}
/**
* Container for passing parameters for creating Protege instances.
*
* @author Andrew Post
* @see ConnectionManager#INSTANCE_CREATOR
*/
private static final class InstanceSpec {
/**
* The name String
of the instance.
*/
String name;
/**
* The Cls
of the instance.
*/
Cls cls;
/**
* @param name the name String
of the instance.
* @param cls the Cls
of the instance.
*/
InstanceSpec(String name, Cls cls) {
this.name = name;
this.cls = cls;
}
}
/**
* Command for creating new instances.
*
* @see #createInstance(String, Cls)
*/
private final ProtegeCommand INSTANCE_CREATOR =
new ProtegeCommand("create instance") {
/**
* Creates a new instance in the knowledge base.
*
* @param instanceSpec
* a {@link ConnectionManager.InstanceSpec} specifying the
* instance to create.
* @return the created Instance
, or null
* if an invalid class specification was provided.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Instance get(InstanceSpec instanceSpec) {
return protegeKnowledgeBase.createInstance(instanceSpec.name,
instanceSpec.cls);
}
};
/**
* Creates a new instance in the knowledge base.
*
* @param name the name String
of the instance.
* @param cls the Cls
of the instance.
* @return a new Instance
, or null
if an
* invalid class specification was provided.
* @see ConnectionManager#INSTANCE_CREATOR
*/
Instance createInstance(String name, Cls cls)
throws KnowledgeSourceReadException {
return getFromProtege(new InstanceSpec(name, cls), INSTANCE_CREATOR);
}
/**
* Command for deleting an instance from the knowledge base.
*
* @see #deleteInstance(Instance)
*/
private final ProtegeCommand INSTANCE_DELETER =
new ProtegeCommand("delete instance") {
/**
* Deletes an instance from the knowledge base.
*
* @param instance
* the Instance
to delete.
* @return the deleted Instance
.
* @see ConnectionManager.ProtegeCommand#get(java.lang.Object)
*/
@Override
Instance get(Instance instance) {
protegeKnowledgeBase.deleteInstance(instance);
return instance;
}
};
/**
* Deletes an instance from the knowledge base.
*
* @param instance an Instance
.
* @see ConnectionManager#INSTANCE_DELETER
*/
void deleteInstance(Instance instance) throws KnowledgeSourceReadException {
getFromProtege(instance, INSTANCE_DELETER);
}
private static final class ClsSpec {
String name;
Collection clses;
/**
* @param name
* @param clses
*/
ClsSpec(String name, Collection clses) {
this.name = name;
this.clses = clses;
}
}
private final ProtegeCommand CLS_CREATOR =
new ProtegeCommand("create cls") {
@Override
Cls get(ClsSpec clsSpec) {
return protegeKnowledgeBase.createCls(clsSpec.name, clsSpec.clses);
}
};
> Cls createCls(String name, E clses)
throws KnowledgeSourceReadException {
return getFromProtege(new ClsSpec(name, clses), CLS_CREATOR);
}
/**
* Container for passing parameters for creating Protege instances.
*
* @author Andrew Post
* @see ConnectionManager#INSTANCE_CREATOR
*/
private static final class InstanceSpecMultipleInheritance {
/**
* The name String
of the instance.
*/
String name;
/**
* The Cls
of the instance.
*/
Collection clses;
/**
* @param name the name String
of the instance.
* @param clses the Cls
of the instance.
*/
InstanceSpecMultipleInheritance(String name, Collection clses) {
this.name = name;
this.clses = clses;
}
}
private final ProtegeCommand INSTANCE_CREATOR_MULTIPLE_INHERITANCE =
new ProtegeCommand(
"create instance multiple inheritance") {
@Override
Instance get(InstanceSpecMultipleInheritance clsSpec) {
return protegeKnowledgeBase.createCls(clsSpec.name, clsSpec.clses);
}
};
> Instance createInstance(String name, E clses)
throws KnowledgeSourceReadException {
return getFromProtege(new InstanceSpecMultipleInheritance(name, clses),
INSTANCE_CREATOR_MULTIPLE_INHERITANCE);
}
private static class SlotValueSpec {
Frame frame;
Slot slot;
/**
* @param frame
* @param slot
*/
SlotValueSpec(Frame frame, Slot slot) {
this.frame = frame;
this.slot = slot;
}
}
private final ProtegeCommand
© 2015 - 2025 Weber Informatics LLC | Privacy Policy