package tr.com.srdc.mdr.core.store;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import tr.com.srdc.mdr.core.model.MDRException;
import tr.com.srdc.mdr.core.model.MDRResourceFactory;
import tr.com.srdc.mdr.core.model.Util;
import tr.com.srdc.mdr.core.model.Vocabulary;
import tr.com.srdc.mdr.core.store.query.ResourceQueryFactory;
import tr.com.srdc.mdr.core.store.query.TDBQueryFactory;
import tr.com.srdc.mdr.core.store.query.VirtuosoQueryFactory;
import tr.com.srdc.triplestore.JenaStore;
import tr.com.srdc.triplestore.JenaStoreException;
import tr.com.srdc.triplestore.TripleStoreProvider;
import tr.com.srdc.triplestore.TripleStoreProvider.TripleStoreType;
import com.hp.hpl.jena.ontology.OntClass;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntProperty;
public class MDRDatabase {
private static final Logger logger = LoggerFactory
.getLogger(MDRDatabase.class);
private static final String ISO11179OntologyFilePath = "model/salus.mdr.owl";
public static final String BASE_URI = "http://www.salusproject.eu/iso11179-3/mdr#";
private JenaStore jenaStore;
private TripleStoreType storeType;
private String storeName;
private OntModel ontModel;
private MDRResourceFactory resourceFactory;
private ResourceQueryFactory queryFactory;
private Vocabulary vocabulary;
private Util util;
// used to indicate whether the store will be synced or not.
// for serial updates such as importing models
// one can change the sync mode for performance improvement
private boolean syncMode = true;
public MDRDatabase(TripleStoreType storeType, String storeName)
throws MDRException {
this.storeType = storeType;
this.storeName = storeName;
init();
}
private void init() throws MDRException {
try {
jenaStore = TripleStoreProvider.getInstance().createStore(
this.storeType, this.storeName);
logger.info("--Existing models in the JenaStore--");
for (String m : jenaStore.listModels()) {
logger.info(m);
}
logger.info("---------------");
this.ontModel = jenaStore.createOntModel(BASE_URI, null,
ISO11179OntologyFilePath);
if (!BASE_URI.equals(this.ontModel.getNsPrefixURI(""))) {
logger.info("BASE_URI and the Base URI of the loaded ontology do not match!!!");
logger.info("BASE_URI: {}", BASE_URI);
logger.info("Coming from the ontology: {}",
this.ontModel.getNsPrefixURI(""));
}
} catch (JenaStoreException e) {
String msg = "Cannot create the JenaStore for MDRDatabase, storeName: "
+ storeName;
logger.error(msg);
throw new MDRException(msg, e);
}
this.vocabulary = new Vocabulary(this);
this.util = new Util(this);
this.resourceFactory = new MDRResourceFactory(this);
switch (this.storeType) {
case JenaTDB:
this.queryFactory = new TDBQueryFactory(this);
break;
case Virtuoso:
this.queryFactory = new VirtuosoQueryFactory(this);
break;
}
}
public JenaStore getJenaStore() {
if (this.jenaStore == null) {
logger.error("JenaStore of the MDRDatabase is null.");
throw new IllegalStateException(
"JenaStore of the MDRDatabase cannot be null.");
}
return this.jenaStore;
}
/**
* MDRDatabase is based upon an ontology which keeps definitions and
* Elements of the MetaDataRepository. Apart form backend, this ontology is
* managed as on Jena {@link OntModel}
*
* @return {@link OntModel} representation of MDR Ontology.
*/
public OntModel getOntModel() {
if (this.ontModel == null) {
logger.error("OntModel of the MDRDatabase is null.");
throw new IllegalStateException(
"OntModel of the MDRDatabase cannot be null.");
}
return this.ontModel;
}
/**
* Elements in MetaDataRepository are based on ISO 11179-3 specification.
* Classes, attributes and properties at the speciication is kept in
* Vocabulary.
*
* @return {@link Vocabulary} based on ISO 11179-3 specification
*/
public Vocabulary getVocabulary() {
if (this.vocabulary == null) {
logger.error("Vocabulary of the MDRDatabase is null.");
throw new IllegalStateException(
"Vocabulary of the MDRDatabase cannot be null.");
}
return this.vocabulary;
}
/**
* Utility which have various methods to ease development like
* {@link Util#isNull(String)} or
* {@link Util#createList(com.hp.hpl.jena.rdf.model.NodeIterator, Class)}
*
* @return {@link Util} which have been initalized with this MDRDatabase
*/
public Util getUtil() {
if (this.util == null) {
logger.error("Util of the MDRDatabase is null.");
throw new IllegalStateException(
"Util of the MDRDatabase cannot be null.");
}
return this.util;
}
/**
* Given the name of the resource, retrieves the {@link OntClass} from the
* associated {@link OntModel}. Default and Test {@link OntModel}s must load
* the ISO11179 ontology upon the start of the application.
*
* @param name
* @return
*/
public OntClass getClass(String name) {
OntClass ontClass = ontModel.getOntClass(BASE_URI + name);
if (ontClass == null) {
logger.error("Class: {} does not exist in the OntModel", name);
throw new IllegalStateException(
"The classes of the ontology should already be loaded into the Model");
}
return ontClass;
}
/**
* Given the name of the resource, retrieves the {@link OntProperty} from
* the associated {@link OntModel}. Default and Test {@link OntModel}s must
* load the ISO11179 ontology upon the start of the application.
*
* @param name
* @return
*/
public OntProperty getProperty(String name) {
OntProperty ontProperty = ontModel.getOntProperty(BASE_URI + name);
if (ontProperty == null) {
throw new IllegalStateException(
"The properties of the ontology should already be loaded into the Model");
}
return ontProperty;
}
/**
* Static Factory has been adopted to prevent entering illegal states while
* creating elements in the Repository. So {@link MDRResourceFactory} which
* will create the Resources in this MDRDatabase is initialized while
* creating MDRDatabase.
*
* @return {@link MDRResourceFactory} which have been initialized with this
* MDRDatabase
*/
public MDRResourceFactory getResourceFactory() {
if (this.resourceFactory == null) {
logger.error("MDRResourceFactory of the MDRDatabase is null.");
throw new IllegalStateException(
"MDRResourceFactory of the MDRDatabase cannot be null.");
}
return this.resourceFactory;
}
// /**
// * Base URI of the Ontology holding definitions and elements of Metadata
// * Repository. It is known before loading the ontology file, however
// * obtained by using {@link OntModel#getNsPrefixURI("")} so that it can be
// * cross-checked in order to avoid inconsistencies.}
// *
// * @return the Base URI of the ontology holded by MDRDatabase
// */
// public String getBaseURI() {
// return BASE_URI;
// }
/**
* Type of the Instance the {@link JenaStore} which persists this
* MDRDatabase, is specified while creating database through the
* constructors.
*
* @return Type of {@link TripleStoreType}, {@link TripleStoreType#JenaTDB}
* or {@link TripleStoreType#Virtuoso}
*/
public TripleStoreType getStoreType() {
return this.storeType;
}
/**
* MDRQueryFactory is used to execute pre-defined SPARQL Queries over
* MDRDatabase's.
* <p>
* MDRQueryFactory is an abstract class including common query executions
* for both {@link JenaDatabase} and {@link VirtuosoDatabase}.
* {@link TDBQueryFactory} and {@link VirtuosoQueryFactory} are extensions
* to the {@link ResourceQueryFactory} and includes SPARQL with specific
* extensions such as pf:textMatch for Jena or bif:contains for Virtuoso.
*
* @return Appropriate {@link ResourceQueryFactory} implementation according
* to the type of {@link MDRDatabase#}
*/
public ResourceQueryFactory getQueryFactory() {
if (this.queryFactory == null) {
logger.error("ResourceQueryFactory of the MDRDatabase is null.");
throw new IllegalStateException(
"ResourceQueryFactory of the MDRDatabase cannot be null.");
}
return this.queryFactory;
}
/**
* Removes this {@link MDRDatabase} instance by removing the associated
* {@link JenaStore}.
*
* @throws MDRException
*/
public void remove() throws MDRException {
try {
this.jenaStore.remove();
} catch (JenaStoreException e) {
String msg = "Cannot remove the store: " + this.storeName;
logger.error(msg, e);
throw new MDRException(msg, e);
}
}
public void close() {
this.jenaStore.close();
}
/**
* Used to control whether mdrDatabase.sync should be called automatically
* or by user
*
* @param autoSync
* if given <code>true</code>, mdrDatabase.sync will be called
* automatically after each modification on underlying JenaStore.
* If given <code>false</code>, no sync will be done, it is the
* users responsibility to call sync to keep underlying JenaStore
* consistent.
*/
public void setSyncMode(boolean activated) {
this.syncMode = activated;
if (activated) {
this.jenaStore.setAutoSync(true);
} else {
this.jenaStore.setAutoSync(false);
}
}
public void sync() {
if (syncMode) {
this.jenaStore.sync();
}
}
}