From d43a2fe184bd0bfa44ed2f632c5daaacdca6082d Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Mon, 6 Mar 2023 14:06:53 -0600 Subject: [PATCH] VIVO 3828: Remove SDB in preparation to moving to new Jena. The Jena version being switched to (Jena 4) has removed support for SDB. The current forms of `DatasetWrapperFactory` and `StaticDatasetFactory` should no longer be needed. The SDB related code has been stripped out. Many of the classes with "SDB" in the name that actually provide more than just SDB have been re-created. These recreations are generally child classes of a similarly named Jena class. These recreates have "DB" in their name rather than "SDB". The `DatasetFactory.createMem()` is deprecated and may not be available in Jena 4. Attempts to replace this with `createTxnMem()` have revealed problems that are potentially transaction related. Replacing with `createGeneral()` might be possible but this is not done to avoid introducing more potential problems. Notable points in regards to replacing `DatasetFactory.createMem()`: 1) The method is deprecated. 2) The `DatasetFactory.createGeneral()` is the compatible equivalent. 3) The `DatasetFactory.createGeneral()` better supports TDB (which is the main reason for including in this commit set). 4) The `DatasetFactory.createTxnMem()` is the more recommended alternative and is transactional. 5) This better prepares the code for the upcoming Jena upgrade changes. There are some serious existing problems with closing dataset connections (and related). The (now removed) `DatasetWrapperFactory` probably should be rewritten to provide a new dataset each time rather than copying an existing one. The `close()` functionality appears to not be being called for TDB due to the SDB conditions. With this SDB condition the connections are now being closed. This has exposed several problems that both tests and runtime expose. This problem is considered out of scope for the changes and the close code is commented out with a FIXME statement. The documentation for `example.runtime.properties` refers to `VitroConnection.DataSource.*` only being used by SDB but this is incorrect. The OpenSocial code appears to talk directly to an SQL database using these properties. Update the documentation in this regard and replace the references to SDB with OpenSocial. Remove no longer necessary SDB helper code that is added to TDB as well because it "shouldn't hurt". Remove much of the documentation and installation functionality using or referencing SDB. The `IndividualDaoSDB.java` file is implemting `getAllIndividualUris()` and `getUpdatedSinceIterator()` via the now removed `IndivdiualSDB` class. This functionality is used by `RebuildIndexTask` and `UpdateUrisTask` classes. The new *DB classes now have java docs. These java docs have a bare-bones level of detail. --- .../dao/ObjectPropertyStatementDao.java | 1 + .../webapp/dao/jena/DataPropertyDaoJena.java | 4 +- .../dao/jena/DataPropertyStatementDaoDB.java | 113 ++ .../jena/DataPropertyStatementDaoJena.java | 33 +- .../dao/jena/DataPropertyStatementDaoSDB.java | 118 -- .../vitro/webapp/dao/jena/DatasetMode.java | 22 + .../vitro/webapp/dao/jena/DatasetWrapper.java | 50 +- .../dao/jena/DatasetWrapperFactory.java | 9 - .../vitro/webapp/dao/jena/IndividualDB.java | 777 ++++++++++++ .../webapp/dao/jena/IndividualDaoDB.java | 562 +++++++++ .../webapp/dao/jena/IndividualDaoJena.java | 57 +- .../webapp/dao/jena/IndividualDaoSDB.java | 550 --------- .../vitro/webapp/dao/jena/IndividualJena.java | 683 ++++++----- .../vitro/webapp/dao/jena/IndividualSDB.java | 1063 ----------------- .../vitro/webapp/dao/jena/JenaBaseDao.java | 29 +- .../dao/jena/ObjectPropertyDaoJena.java | 4 +- .../jena/ObjectPropertyStatementDaoDB.java | 262 ++++ .../jena/ObjectPropertyStatementDaoJena.java | 19 +- .../jena/ObjectPropertyStatementDaoSDB.java | 206 ---- .../webapp/dao/jena/PropertyDaoJena.java | 6 +- .../dao/jena/PropertyInstanceDaoJena.java | 4 +- .../dao/jena/SDBGraphConnectionGenerator.java | 47 - .../webapp/dao/jena/SDBGraphGenerator.java | 65 - .../webapp/dao/jena/StaticDatasetFactory.java | 19 - .../vitro/webapp/dao/jena/VClassDaoDB.java | 187 +++ .../vitro/webapp/dao/jena/VClassDaoJena.java | 38 +- .../vitro/webapp/dao/jena/VClassDaoSDB.java | 162 --- .../webapp/dao/jena/WebappDaoFactoryDB.java | 231 ++++ .../webapp/dao/jena/WebappDaoFactoryJena.java | 66 +- .../webapp/dao/jena/WebappDaoFactorySDB.java | 186 --- .../IndividualNotFoundException.java | 10 + .../impl/ContextModelAccessImpl.java | 24 +- .../impl/RequestModelAccessImpl.java | 39 +- .../rdfservice/impl/jena/RDFServiceJena.java | 45 +- .../impl/jena/model/RDFServiceModel.java | 6 +- .../impl/jena/sdb/RDFServiceFactorySDB.java | 80 -- .../impl/jena/sdb/RDFServiceSDB.java | 343 ------ .../vitro/webapp/reasoner/SimpleReasoner.java | 2 +- .../webapp/servlet/setup/FileGraphSetup.java | 8 +- .../impl/sdb/ContentTripleSourceSDB.java | 288 ----- .../impl/sdb/SDBConnectionSmokeTests.java | 187 --- .../triplesource/impl/sdb/SDBDataSource.java | 178 --- .../customlistview/ListConfigUtils.java | 2 - .../config/example.applicationSetup.n3 | 8 +- .../config/example.runtime.properties | 4 +- .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../firsttime/vitro_UiLabel.ttl | 8 - .../WEB-INF/classes/log4j.properties | 2 - .../templates/freemarker/body/sdbSetup.ftl | 12 - 55 files changed, 2765 insertions(+), 4110 deletions(-) create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetMode.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapperFactory.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDB.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoSDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphConnectionGenerator.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphGenerator.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/StaticDatasetFactory.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoSDB.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactorySDB.java create mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/exception/IndividualNotFoundException.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceFactorySDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceSDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/ContentTripleSourceSDB.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBConnectionSmokeTests.java delete mode 100644 api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java delete mode 100644 webapp/src/main/webapp/templates/freemarker/body/sdbSetup.ftl diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyStatementDao.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyStatementDao.java index 2a2ab45e62..9a60834079 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyStatementDao.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyStatementDao.java @@ -9,6 +9,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.dao.jena.exception.IndividualNotFoundException; /** * Created by IntelliJ IDEA. diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java index 5c836281db..410a3fa0f4 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java @@ -73,9 +73,9 @@ public int compare (DataProperty dp1, DataProperty dp2) { } public DataPropertyDaoJena(RDFService rdfService, - DatasetWrapperFactory dwf, + DatasetWrapper dw, WebappDaoFactoryJena wadf) { - super(rdfService, dwf, wadf); + super(rdfService, dw, wadf); } public void deleteDataProperty(DataProperty dtp) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoDB.java new file mode 100644 index 0000000000..b980e139de --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoDB.java @@ -0,0 +1,113 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.OntModelSpec; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.shared.Lock; +import org.apache.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; + +/** + * An extension of {@link DataPropertyStatementDaoJena} for databases, such as TDB. + */ +public class DataPropertyStatementDaoDB extends DataPropertyStatementDaoJena implements DataPropertyStatementDao { + + /** + * Initialize the data property statement DAO. + * + * @param dw The data wrapper. + * @param wadf The web application DAO factory. + */ + public DataPropertyStatementDaoDB(DatasetWrapper dw, WebappDaoFactoryDB wadf) { + super (dw, wadf); + } + + /** + * Fill existing data property statements for an individual. + * + * @param entity The individual. + * + * @return A filled out individual. + */ + public Individual fillExistingDataPropertyStatementsForIndividual(Individual entity) { + if (entity.getURI() == null) { + return entity; + } + + String query = + "CONSTRUCT { \n" + + " <" + entity.getURI() + "> ?p ?o . \n" + + "} WHERE { \n" + + " <" + entity.getURI() + "> ?p ?o . \n" + + " FILTER(isLiteral(?o)) \n" + + "}" ; + Model results = null; + Dataset dataset = getDataWrapper().getDataset(); + QueryExecution qexec = null; + + dataset.getLock().enterCriticalSection(Lock.READ); + try { + qexec = QueryExecutionFactory.create(QueryFactory.create(query), dataset); + results = qexec.execConstruct(); + } finally { + if (qexec != null) qexec.close(); + dataset.getLock().leaveCriticalSection(); + getDataWrapper().close(); + } + + OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, results); + ontModel.enterCriticalSection(Lock.READ); + try { + Resource ind = ontModel.getResource(entity.getURI()); + List edList = new ArrayList<>(); + StmtIterator stmtIt = ind.listProperties(); + + while (stmtIt.hasNext()) { + Statement st = stmtIt.next(); + boolean addToList = st.getObject().isLiteral() && + ( + ( + RDF.value.equals(st.getPredicate()) + || VitroVocabulary.value.equals(st.getPredicate().getURI())) + || MONIKER.equals(st.getPredicate()) + || !(NONUSER_NAMESPACES.contains(st.getPredicate().getNameSpace()) + ) + ); + + if (addToList) { + DataPropertyStatement ed = new DataPropertyStatementImpl(); + Literal lit = (Literal)st.getObject(); + fillDataPropertyStatementWithJenaLiteral(ed,lit); + ed.setDatapropURI(st.getPredicate().getURI()); + ed.setIndividualURI(ind.getURI()); + ed.setIndividual(entity); + edList.add(ed); + } + } + + entity.setDataPropertyStatements(edList); + return entity; + } finally { + ontModel.leaveCriticalSection(); + } + } +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java index fbebef2c2f..5f3394227b 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java @@ -50,15 +50,22 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro { private static final Log log = LogFactory.getLog(DataPropertyStatementDaoJena.class); + private DatasetWrapper dw; - private DatasetWrapperFactory dwf; - - public DataPropertyStatementDaoJena(DatasetWrapperFactory dwf, + public DataPropertyStatementDaoJena(DatasetWrapper dw, WebappDaoFactoryJena wadf) { super(wadf); - this.dwf = dwf; + this.dw = dw; } + /** + * Get the data wrapper. + * + * @return The data wrapper. + */ + public DatasetWrapper getDataWrapper() { + return dw; + } public void deleteDataPropertyStatement( DataPropertyStatement dataPropertyStatement ) { @@ -366,13 +373,11 @@ public List getDataPropertyValuesForIndividualByProperty(String subject // Run the SPARQL query to get the properties List values = new ArrayList(); - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); + Dataset dataset = dw.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); QueryExecution qexec = null; try { - qexec = QueryExecutionFactory.create( - queryString, dataset); + qexec = QueryExecutionFactory.create(queryString, dataset); ResultSet results = qexec.execSelect(); while (results.hasNext()) { @@ -388,7 +393,7 @@ public List getDataPropertyValuesForIndividualByProperty(String subject } finally { dataset.getLock().leaveCriticalSection(); - w.close(); + dw.close(); if (qexec != null) { qexec.close(); } @@ -430,8 +435,7 @@ public List getDataPropertyValuesForIndividualByProperty( // Run the SPARQL query to get the properties List values = new ArrayList(); - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); + Dataset dataset = dw.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); QueryExecution qexec = null; try { @@ -459,7 +463,7 @@ public List getDataPropertyValuesForIndividualByProperty( return Collections.emptyList(); } finally { dataset.getLock().leaveCriticalSection(); - w.close(); + dw.close(); if (qexec != null) { qexec.close(); } @@ -497,8 +501,7 @@ private Model constructModelForSelectQueries(String subjectUri, initialBindings.add( "property", ResourceFactory.createResource(propertyUri)); - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); + Dataset dataset = dw.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); QueryExecution qe = null; try { @@ -512,7 +515,7 @@ private Model constructModelForSelectQueries(String subjectUri, qe.close(); } dataset.getLock().leaveCriticalSection(); - w.close(); + dw.close(); } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java deleted file mode 100644 index 4921b5ea83..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoSDB.java +++ /dev/null @@ -1,118 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.util.ArrayList; -import java.util.List; - -import org.apache.jena.ontology.OntModel; -import org.apache.jena.ontology.OntModelSpec; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryExecutionFactory; -import org.apache.jena.query.QueryFactory; -import org.apache.jena.rdf.model.Literal; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.rdf.model.StmtIterator; -import org.apache.jena.shared.Lock; -import org.apache.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; - -public class DataPropertyStatementDaoSDB extends DataPropertyStatementDaoJena - implements DataPropertyStatementDao { - - private DatasetWrapperFactory dwf; - private SDBDatasetMode datasetMode; - - public DataPropertyStatementDaoSDB( - DatasetWrapperFactory datasetWrapperFactory, - SDBDatasetMode datasetMode, - WebappDaoFactoryJena wadf) { - super (datasetWrapperFactory, wadf); - this.dwf = datasetWrapperFactory; - this.datasetMode = datasetMode; - } - - @Override - public Individual fillExistingDataPropertyStatementsForIndividual( Individual entity/*, boolean allowAnyNameSpace*/) - { - if( entity.getURI() == null ) - { - return entity; - } - else - { - String query = - "CONSTRUCT { \n" + - " <" + entity.getURI() + "> ?p ?o . \n" + - "} WHERE { \n" + - " <" + entity.getURI() + "> ?p ?o . \n" + - " FILTER(isLiteral(?o)) \n" + - "}" ; - Model results = null; - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - QueryExecution qexec = null; - try { - qexec = QueryExecutionFactory.create(QueryFactory.create(query), dataset); - results = qexec.execConstruct(); - } finally { - if(qexec!=null) qexec.close(); - dataset.getLock().leaveCriticalSection(); - w.close(); - } - OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, results); - ontModel.enterCriticalSection(Lock.READ); - try { - Resource ind = ontModel.getResource(entity.getURI()); - List edList = new ArrayList(); - StmtIterator stmtIt = ind.listProperties(); - while( stmtIt.hasNext() ) - { - Statement st = stmtIt.next(); - boolean addToList = /*allowAnyNameSpace ? st.getObject().canAs(Literal.class) :*/ st.getObject().isLiteral() && - ( - (RDF.value.equals(st.getPredicate()) || VitroVocabulary.value.equals(st.getPredicate().getURI())) - || this.MONIKER.equals(st.getPredicate()) - || !(NONUSER_NAMESPACES.contains(st.getPredicate().getNameSpace())) - ); - if( addToList ) - { /* now want to expose Cornellemailnetid and potentially other properties so can at least control whether visible - boolean isExternalId = false; - ClosableIterator externalIdStmtIt = getOntModel().listStatements(st.getPredicate(), DATAPROPERTY_ISEXTERNALID, (Literal)null); - try { - if (externalIdStmtIt.hasNext()) { - isExternalId = true; - } - } finally { - externalIdStmtIt.close(); - } - if (!isExternalId) { */ - DataPropertyStatement ed = new DataPropertyStatementImpl(); - Literal lit = (Literal)st.getObject(); - fillDataPropertyStatementWithJenaLiteral(ed,lit); - ed.setDatapropURI(st.getPredicate().getURI()); - ed.setIndividualURI(ind.getURI()); - ed.setIndividual(entity); - edList.add(ed); - /* } */ - } - } - entity.setDataPropertyStatements(edList); - return entity; - } finally { - ontModel.leaveCriticalSection(); - } - } - } -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetMode.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetMode.java new file mode 100644 index 0000000000..634c45c7a3 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetMode.java @@ -0,0 +1,22 @@ +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +/** + * Modes for optimizing database queries. + */ +public enum DatasetMode { + + /** + * Only perform assertions. + */ + ASSERTIONS_ONLY, + + /** + * Only perform inferences. + */ + INFERENCES_ONLY, + + /** + * Perform both assertions and inferences. + */ + ASSERTIONS_AND_INFERENCES, +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapper.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapper.java index 42457cd566..264a1873d1 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapper.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapper.java @@ -3,37 +3,65 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; import org.apache.jena.query.Dataset; -import org.apache.jena.sdb.sql.SDBConnection; +import org.apache.jena.shared.ClosedException; public class DatasetWrapper { - private SDBConnection conn; private Dataset dataset; private boolean closed = false; + /** + * Initialize the data set. + * + * @param dataset The data set. + */ public DatasetWrapper(Dataset dataset) { this.dataset = dataset; } - public DatasetWrapper(Dataset dataset, SDBConnection conn) { - this.dataset = dataset; - this.conn = conn; - } - + /** + * Get the data set. + * + * @return The data set + */ public Dataset getDataset() { if (!closed) { return dataset; } else throw new RuntimeException("No operations on a closed dataset"); } + /** + * Set the data set closed boolean. + * + * This is normally handled internally. + * This should only be used for exceptional cases. + * + * Setting this to true or false neither opens nor closes the data set. + * + * @param closed The data set closed state. + */ + public void setClosed(boolean closed) { + this.closed = closed; + } + + /** + * Close the data. + * + * This does nothing if already closed according to the closed boolean. + * + * This sets the closed state to true. + */ public void close() { - if (!closed) { + // FIXME: This is causing NPEs and connection already closed errors in tests. + // Not closing the dataset can result in excessive memory or other resource usage. + /*if (!closed) { closed = true; - if (conn != null) { + try { dataset.close(); - conn.close(); + } catch (ClosedException e) { + // Do nothing. } - } + }*/ } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapperFactory.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapperFactory.java deleted file mode 100644 index a569b17581..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/DatasetWrapperFactory.java +++ /dev/null @@ -1,9 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -public interface DatasetWrapperFactory { - - public DatasetWrapper getDatasetWrapper(); - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDB.java new file mode 100644 index 0000000000..ef540e7cbd --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDB.java @@ -0,0 +1,777 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.exception.IndividualNotFoundException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.OntModelSpec; +import org.apache.jena.ontology.OntResource; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.shared.Lock; +import org.apache.jena.vocabulary.RDF; +import org.apache.jena.vocabulary.RDFS; + +/** + * An extension of {@link IndividualJena} for databases, such as TDB. + */ +public class IndividualDB extends IndividualJena { + + private static final Log LOG = LogFactory.getLog(IndividualJena.class.getName()); + private static final String VITRO = "http://vitro.mannlib.cornell.edu/ns/vitro/public"; + + private String indURI; + private DatasetWrapper dw; + private DatasetMode mode; + private Model model; + private Boolean hasThumb; + + /** + * Initialize the individual based on an initialization model. + * + * @param indURI The URI representing the individual. + * @param dw The data set wrapper. + * @param mode The database mode filter to utilize. + * @param wadf The DAO factory. + * @param initModel The model to use in order to initialize the individual. + */ + public IndividualDB(String indURI, DatasetWrapper dw, DatasetMode mode, + WebappDaoFactoryDB wadf, Model initModel) { + + super(null, wadf); + + this.indURI = indURI; + this.dw = dw; + this.mode = mode; + this.model = null; + this.hasThumb = null; + + try { + initModel.getLock().enterCriticalSection(Lock.READ); + + String getStatements = + "CONSTRUCT \n" + + "{ <" + indURI + "> <" + RDFS.label.getURI() + "> ?ooo. \n" + + "<" + indURI + "> a ?type . \n" + + "} \n" + + "WHERE { \n" + + "{ <" + indURI + "> <" + RDFS.label.getURI() + "> ?ooo } \n" + + " UNION { <" + indURI + "> a ?type } \n" + + "} "; + + model = QueryExecutionFactory.create( + QueryFactory.create(getStatements), initModel).execConstruct(); + } finally { + initModel.getLock().leaveCriticalSection(); + } + + setInd(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, model) + .createOntResource(indURI)); + + setupURIParts(getInd()); + } + + /** + * Initialize the individual. + * + * @param indURI The URI representing the individual. + * @param dw The data set wrapper. + * @param mode The database mode filter to utilize. + * @param wadf The DAO factory. + * + * @throws IndividualNotFoundException + */ + public IndividualDB(String indURI, DatasetWrapper dw, DatasetMode mode, + WebappDaoFactoryDB wadf) + throws IndividualNotFoundException { + + this(indURI, dw, mode, wadf, false); + } + + /** + * Initialize the individual, possibly skipping the model initialization. + * + * @param indURI The URI representing the individual. + * @param dw The data set wrapper. + * @param mode The database mode filter to utilize. + * @param wadf The DAO factory. + * @param skipInitialization True to skip model initialize, False to + * perform model initialization. + * + * @throws IndividualNotFoundException + */ + public IndividualDB(String indURI, DatasetWrapper dw, DatasetMode mode, + WebappDaoFactoryDB wadf, boolean skipInitialization) + throws IndividualNotFoundException { + + super(null, wadf); + + this.indURI = indURI; + this.dw = dw; + this.mode = mode; + this.model = null; + this.hasThumb = null; + + validateIndividualURI(indURI); + + if (skipInitialization) { + setInd(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM) + .createOntResource(indURI)); + } else { + try { + String getStatements = + "CONSTRUCT " + + "{ <" + indURI + "> <" + RDFS.label.getURI() + "> ?ooo \n" + + "} WHERE {" + + "{ <" + indURI + "> <" + RDFS.label.getURI() + "> ?ooo } \n" + + "}"; + + model = ModelFactory.createDefaultModel(); + getWebappDaoFactory().getRDFService().sparqlConstructQuery(getStatements, model); + } catch (RDFServiceException e) { + LOG.debug(e); + } + + setInd(ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, model) + .createOntResource(indURI)); + + if (model == null || model.isEmpty() && noTriplesForUri()) { + throw new IndividualNotFoundException(); + } + } + + setupURIParts(getInd()); + } + + /** + * Get the most specific type URI, using the RDF service. + * + * @return The list of URIs. + */ + public List getMostSpecificTypeURIs() { + final List typeURIs = new ArrayList(); + + if (this.getURI() == null) { + return typeURIs; + } + + String queryStr = "SELECT ?type WHERE { <" + this.getURI() + "> <" + + VitroVocabulary.MOST_SPECIFIC_TYPE + "> ?type }"; + + try { + getWebappDaoFactory().getRDFService().sparqlSelectQuery(queryStr, + new ResultSetConsumer() { + protected void processQuerySolution(QuerySolution qs) { + RDFNode node = qs.get("type"); + if (node.isURIResource()) { + typeURIs.add(node.asResource().getURI()); + } + } + } + ); + + return typeURIs; + } catch (RDFServiceException e) { + throw new RuntimeException(e); + } + } + + /** + * Determine if individual has a thumbnail URI. + * + * @return True if has thumbnail, false otherwise. + */ + public boolean hasThumb() { + if (hasThumb != null) { + return hasThumb; + } + + String ask = + "ASK { " + + " <" + indURI + "> <" + VITRO + "#mainImage> ?mainImage . \n" + + " ?mainImage <" + VITRO + "#thumbnailImage> ?thumbImage . }\n" ; + try { + hasThumb = getWebappDaoFactory().getRDFService().sparqlAskQuery(ask); + } catch (Exception e) { + LOG.error(e, e); + hasThumb = false; + } + + return hasThumb; + } + + /** + * Get data property statements for the given property URI. + * + * @param propertyUri The URI. + * + * @return The found list of statements. + */ + public List getDataPropertyStatements(String propertyUri) { + List stmts = this.dataPropertyStatements; + if (stmts == null) { + return sparqlForDataPropertyStatements(propertyUri); + } + + List stmtsForProp = new ArrayList<>(); + for (DataPropertyStatement stmt : stmts) { + if (stmt.getDatapropURI().equals(propertyUri)) { + stmtsForProp.add(stmt); + } + } + + return stmtsForProp; + } + + /** + * Get the search boost. + * + * @return The search boost. + */ + public Float getSearchBoost() { + String getPropertyValue = + "SELECT ?value \n" + + "WHERE { \n" + + "<" + indURI + "> <" + getWebappDaoFactory().getJenaBaseDao().SEARCH_BOOST_ANNOT + + "> ?value \n" + + "}"; + + Dataset dataset = dw.getDataset(); + dataset.getLock().enterCriticalSection(Lock.READ); + QueryExecution qe = QueryExecutionFactory.create( + QueryFactory.create(getPropertyValue), dataset); + + try { + ResultSet rs = qe.execSelect(); + if (rs.hasNext()) { + QuerySolution qs = rs.nextSolution(); + if (qs.get("value") != null) { + Literal value = qs.get("value").asLiteral(); + searchBoost = Float.parseFloat(value.getLexicalForm()); + return searchBoost; + } + } + } catch (Exception e) { + LOG.error(e); + } finally { + qe.close(); + dataset.getLock().leaveCriticalSection(); + } + + return null; + } + + /** + * Get VClasses. + * + * @param direct Only get direct VClasses rather than all. + * + * @return List of VClasses. + */ + public List getVClasses(boolean direct) { + if (direct) { + if (directVClasses == null) { + directVClasses = getMyVClasses(true); + } + + return directVClasses; + } + + if (allVClasses == null) { + allVClasses = getMyVClasses(false); + } + + return allVClasses; + } + + /** + * Get the data values for the property URI. + * + * This is overridden to use Sparql queries from the RDF service. + * + * @param propertyUri The URI. + * + * @return The found list of values. + * Null is returned if propertyUri or getURI() is null. + */ + public List getDataValues(String propertyUri) { + if (propertyUri == null) { + LOG.error("Cannot retrieve value for null property"); + return null; + } + + if (this.getURI() == null) { + LOG.error("Cannot retrieve value of property " + propertyUri + + " for anonymous individual"); + return null; + } + + List values = new ArrayList<>(); + List stmts = sparqlForDataPropertyStatements(propertyUri); + + if (stmts != null) { + for (DataPropertyStatement stmt : stmts) { + values.add(stmt.getData()); + } + } + + return values; + } + + /** + * Check if the URI is a VClass. + * + * The base method in {@link IndividualImpl} is adequate if the reasoner is up to date. + * + * If the base method returns false, check directly to see if any of the super classes of the + * direct classes will satisfy this request. + * + * @param uri The URI to check. + * + * @return True if URI is a VClass, false otherwise. + */ + public boolean isVClass(String uri) { + if (uri == null || this.getURI() == null) { + return false; + } + + String queryString = "ASK { <" + this.getURI() + "> a <" + uri + "> }"; + try { + return getWebappDaoFactory().getRDFService().sparqlAskQuery(queryString); + } catch (RDFServiceException e) { + throw new RuntimeException(e); + } + } + + /** + * Get web application DAO factory for databases, such as TDB. + * + * @return The web application DAO factory. + */ + protected WebappDaoFactoryDB getWebappDaoFactory() { + return (WebappDaoFactoryDB) super.getWebappDaoFactory(); + } + + /** + * Check that indURI is valid. + * + * This is used to help prevent SPARQL injection attacks. + * + * @param indURI + * @throws IndividualNotFoundException + * + * @see "https://www.w3.org/TR/rdf-sparql-query/#rIRI_REF" + */ + private void validateIndividualURI(String indURI) + throws IndividualNotFoundException { + + // Check that indURI is valid. (Prevent SPARQL injection attack.) + // Valid syntax is defined here: https://www.w3.org/TR/rdf-sparql-query/#rIRI_REF + if (!indURI.matches("[^<>\"{}|^`\\\\\u0000-\u0020]*")) { + throw new IndividualNotFoundException(); + } + } + + /** + * Determine if there are any triples for the given URI. + * + * @return True if there are no triples, false otherwise. + */ + private boolean noTriplesForUri() { + try { + return !getWebappDaoFactory().getRDFService() + .sparqlAskQuery("ASK { <" + indURI + "> ?p ?o }"); + } catch (RDFServiceException e) { + LOG.debug(e); + } + + return true; + } + + /** + * Execute sparql to select statements for the given property URI. + * + * @param propertyUri The URI. + * + * @return The found list of statements. + */ + private List sparqlForDataPropertyStatements(final String propertyUri) { + final List stmts = new ArrayList<>(); + final IndividualDB individualDB = this; + + String queryStr = "SELECT (str(?value) as ?valueString) WHERE { <" + this.getURI() + + "> <" + propertyUri + "> ?value }"; + + try { + getWebappDaoFactory().getRDFService().sparqlSelectQuery( + queryStr, new ResultSetConsumer() { + + protected void processQuerySolution(QuerySolution qs) { + RDFNode node = qs.get("valueString"); + if (!node.isLiteral()) { + LOG.debug("Ignoring non-literal value for " + node + " for property " + + propertyUri); + } else { + Literal lit = node.asLiteral(); + DataPropertyStatement stmt = new DataPropertyStatementImpl(); + + stmt.setData(lit.getLexicalForm()); + stmt.setDatatypeURI(lit.getDatatypeURI()); + stmt.setLanguage(lit.getLanguage()); + stmt.setDatapropURI(propertyUri); + stmt.setIndividualURI(individualDB.getURI()); + stmt.setIndividual(individualDB); + stmts.add(stmt); + } + } + }); + } catch (RDFServiceException e) { + LOG.error(e,e); + throw new RuntimeException(e); + } + + return stmts; + } + + /** + * Get object property statements for some property URI. + * + * @param propertyUri The URI. + * + * @return list of statements. + */ + public List getObjectPropertyStatements(String propertyUri) { + if (propertyUri == null) { + return null; + } + + List objectPropertyStatements = new ArrayList<>(); + Model tempModel = ModelFactory.createDefaultModel(); + OntModel ontModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); + Dataset dataset = dw.getDataset(); + QueryExecution qexec = null; + + dataset.getLock().enterCriticalSection(Lock.READ); + try { + String valuesOfProperty = + "CONSTRUCT{ <" + this.indURI + "> <" + propertyUri + "> ?object }" + + "WHERE{ <" + this.indURI + "> <" + propertyUri + "> ?object } \n"; + + qexec = QueryExecutionFactory.create(QueryFactory.create(valuesOfProperty), dataset); + tempModel = qexec.execConstruct(); + ontModel.add(tempModel.listStatements()); + + Resource ontRes = ontModel.getResource(this.indURI); + StmtIterator sit = ontRes.listProperties(ontRes.getModel().getProperty(propertyUri)); + + while (sit.hasNext()) { + Statement s = sit.nextStatement(); + if (!s.getSubject().canAs(OntResource.class) || !s.getObject().canAs(OntResource.class)) { + continue; + } + + Individual subj = null; + Individual obj = null; + + try { + subj = new IndividualDB(s.getSubject() + .as(OntResource.class).getURI(), dw, mode, getWebappDaoFactory()); + } catch (IndividualNotFoundException e) { + // leave null subject + } + + try { + obj = new IndividualDB(s.getObject() + .as(OntResource.class).getURI(), dw, mode, getWebappDaoFactory()); + } catch (IndividualNotFoundException e) { + // leave null object + } + + ObjectProperty op = getWebappDaoFactory().getObjectPropertyDao() + .getObjectPropertyByURI(s.getPredicate().getURI()); + // We don't want to filter out statements simply because we + // can't find a type for the property, so we'll just make a + // new ObjectProperty bean if we can't get one from the DAO. + if (op == null) { + op = new ObjectProperty(); + op.setURI(propertyUri); + } + + if (subj != null && obj != null) { + ObjectPropertyStatement ops = new ObjectPropertyStatementImpl(); + ops.setSubject(subj); + ops.setSubjectURI(subj.getURI()); + ops.setObject(obj); + ops.setObjectURI(obj.getURI()); + ops.setProperty(op); + ops.setPropertyURI(op.getURI()); + objectPropertyStatements.add(ops); + } + } + } finally { + if (qexec != null) { + qexec.close(); + } + + tempModel.close(); + ontModel.close(); + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + + return objectPropertyStatements; + } + + /** + * Get related individuals for some property URI. + * + * @param propertyUri The URI. + * + * @return list of related individuals. + */ + public List getRelatedIndividuals(String propertyUri) { + if (propertyUri == null) { + return null; + } + + List relatedIndividuals = new ArrayList<>(); + Dataset dataset = dw.getDataset(); + dataset.getLock().enterCriticalSection(Lock.READ); + try { + String valuesOfProperty = + "SELECT ?object " + + "WHERE{ <" + this.indURI + "> <" + propertyUri + "> ?object } \n"; + ResultSet values = QueryExecutionFactory.create( + QueryFactory.create(valuesOfProperty), dataset).execSelect(); + QuerySolution result = null; + + while (values.hasNext()) { + result = values.next(); + RDFNode value = result.get("object"); + + try { + if (value.canAs(OntResource.class)) { + relatedIndividuals.add(new IndividualDB(value.as(OntResource.class) + .getURI(), dw, mode, getWebappDaoFactory())); + } + } catch (IndividualNotFoundException e) { + // don't add to the list + } + } + } finally { + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + + return relatedIndividuals; + } + + /** + * Get a single related individual for some property URI. + * + * @param propertyUri The URI. + * + * @return list of related individuals. + */ + public Individual getRelatedIndividual(String propertyUri) { + if (propertyUri == null) { + return null; + } + + Dataset dataset = dw.getDataset(); + dataset.getLock().enterCriticalSection(Lock.READ); + try { + String valueOfProperty = + "SELECT ?object " + + "WHERE{ <" + this.indURI + "> <" + propertyUri + "> ?object } \n"; + QueryExecution qe = QueryExecutionFactory.create( + QueryFactory.create(valueOfProperty), dataset); + + try { + ResultSet results = qe.execSelect(); + if (results.hasNext()) { + QuerySolution result = results.next(); + RDFNode value = result.get("object"); + + if (value != null && value.canAs(OntResource.class)) { + try { + return new IndividualDB(value.as(OntResource.class) + .getURI(), dw, mode, getWebappDaoFactory()); + } catch (IndividualNotFoundException e) { + } + } + } + + return null; + } finally { + qe.close(); + } + } finally { + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + } + + /** + * Get VClass for the individual. + * + * @param assertedOnly Set to TRUE to only get asserted, FALSE to get all. + * + * @return The list of VClass. + */ + private List getMyVClasses(boolean assertedOnly) { + List vClassList = new ArrayList<>(); + Model tempModel = null; + + if (getInd().getModel().contains((Resource) null, RDF.type, (RDFNode) null)){ + tempModel = getInd().getModel(); + } else { + tempModel = ModelFactory.createDefaultModel(); + String getTypesQuery = buildMyVClassesQuery(assertedOnly); + + RDFService service = getWebappDaoFactory().getRDFService(); + try { + service.sparqlConstructQuery(getTypesQuery, tempModel); + } catch (RDFServiceException e) { + throw new RuntimeException(e); + } + } + + StmtIterator stmtItr = tempModel.listStatements((Resource) null, RDF.type, (RDFNode) null); + LinkedList list = new LinkedList<>(); + + while (stmtItr.hasNext()) { + Statement stmt = stmtItr.nextStatement(); + if (stmt.getObject().isResource() && !stmt.getObject().isAnon()) { + list.add(((Resource) stmt.getObject()).getURI()); + } + } + + if (assertedOnly) { + Iterator itr = null; + VClassDao checkSubClass = getWebappDaoFactory().getVClassDao(); + boolean directTypes = false; + String currentType = null; + ArrayList done = new ArrayList<>(); + + while (!directTypes) { + itr = list.listIterator(); + + do { + if (itr.hasNext()) { + currentType = itr.next(); + } else { + directTypes = true; + break; + } + } while (done.contains(currentType)); + + if (directTypes) { + break; + } else { + itr = list.listIterator(); + } + + while (itr.hasNext()) { + String nextType = itr.next(); + if (checkSubClass.isSubClassOf(currentType, nextType) + && !currentType.equalsIgnoreCase(nextType)) { + itr.remove(); + } + } + + done.add(currentType); + } + } + + for (Iterator it = list.iterator(); it.hasNext();) { + Resource type = ResourceFactory.createResource(it.next().toString()); + if (type.getNameSpace() == null || + (!getWebappDaoFactory().getNonuserNamespaces().contains(type.getNameSpace())) ) { + + VClass vc = getWebappDaoFactory().getVClassDao().getVClassByURI(type.getURI()); + if (vc != null) { + vClassList.add(vc); + } + } + } + + try { + Collections.sort(vClassList); + } catch (Exception e) { + LOG.error("Unable to sort VClass list", e); + } + + return vClassList; + } + + /** + * Build the VClass Sparql query. + * + * If we are restricting to asserted types, either by request or by dataset + * mode, then filter by graph and include a UNION clause to support + * retrieving inferred types from the unnamed base graph, as in Sesame and + * OWLIM. + * + * @param assertedOnly Set to TRUE to only get asserted, FALSE to get all. + * + * @return The query for getting all of the individuals VClass. + */ + private String buildMyVClassesQuery(boolean assertedOnly) { + DatasetMode queryMode = assertedOnly ? DatasetMode.ASSERTIONS_ONLY : mode; + + String filterBlock = WebappDaoFactoryDB.getFilterBlock(new String[] { "?g" }, queryMode); + + if (filterBlock.isEmpty()) { + return + "CONSTRUCT { <" + indURI + "> " + "<" + RDF.type + "> ?types }\n" + + "WHERE { <" + indURI + "> <" + RDF.type + "> ?types } \n"; + } + + String unionBlock = queryMode.equals(DatasetMode.ASSERTIONS_ONLY) + ? "" + : "UNION { <" + indURI +"> <" +RDF.type+ "> ?types }"; + + return + "CONSTRUCT{ <" + indURI + "> " + "<" + RDF.type + "> ?types }\n" + + "WHERE{ { GRAPH ?g" + + " { <" + indURI +"> <" + RDF.type + "> ?types } \n" + + filterBlock + + "} \n" + + unionBlock + + "} \n"; + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoDB.java new file mode 100644 index 0000000000..05a74482c2 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoDB.java @@ -0,0 +1,562 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.jena.exception.IndividualNotFoundException; +import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.jena.ontology.OntClass; +import org.apache.jena.ontology.OntModel; +import org.apache.jena.ontology.UnionClass; +import org.apache.jena.query.Dataset; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.QuerySolution; +import org.apache.jena.query.ResultSet; +import org.apache.jena.rdf.model.AnonId; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.shared.Lock; +import org.apache.jena.vocabulary.RDFS; +import org.joda.time.DateTime; + +/** + * An extension of {@link IndividualDaoJena} for databases, such as TDB. + */ +public class IndividualDaoDB extends IndividualDaoJena { + + private static final Log LOG = LogFactory.getLog(IndividualDaoDB.class.getName()); + + private DatasetWrapper dw; + private DatasetMode mode; + + /** + * Initialize the individual DAO. + * + * @param dw The dataset wrapper. + * @param mode The dataset mode. + * @param wadf The web application DAO factory. + */ + public IndividualDaoDB(DatasetWrapper dw, DatasetMode mode, WebappDaoFactoryDB wadf) { + super(wadf); + this.dw = dw; + this.mode = mode; + } + + /** + * Get an individual by the URI, creating one if necessary. + * + * @param entityURI The URI of the entity representing an individual. + * + * @return The individual. + */ + public Individual getIndividualByURI(String entityURI) { + if (entityURI == null || entityURI.length() == 0) { + return null; + } + + return makeIndividual(entityURI); + } + + /** + * Get all individuals based on VClass URI. + * + *@param vclassURI The VClass URI. + *@param offset An offset to start from. + *@param quantity A total amount of individuals to get. + * + * @return A list of individuals. + */ + public List getIndividualsByVClassURI(String vclassURI, int offset, int quantity) { + if (vclassURI == null) { + return null; + } + + List ents = new ArrayList<>(); + + Resource theClass = (vclassURI.indexOf(PSEUDO_BNODE_NS) == 0) + ? getOntModel().createResource(new AnonId(vclassURI.split("#")[1])) + : ResourceFactory.createResource(vclassURI); + + if (theClass.isAnon() && theClass.canAs(UnionClass.class)) { + UnionClass u = theClass.as(UnionClass.class); + for (OntClass operand : u.listOperands().toList()) { + VClass vc = new VClassJena(operand, getWebappDaoFactory()); + ents.addAll(getIndividualsByVClass(vc)); + } + } else { + // Check if there is a graph filter. + // If so, we will use it in a slightly strange way. Unfortunately, + // performance is quite bad if we add several graph variables in + // order to account for the fact that an individual's type + // declaration may be in a different graph from its label. + // Thus, we will run two queries: one with a single + // graph variable to get the list of URIs, and a second against + // the union graph to get individuals with their labels. + // We will then toss out any individual in the second + // list that is not also in the first list. + // Annoying, yes, but better than the alternative. + // Note that both queries need to sort identically or + // the results may be very strange. + String[] graphVars = {"?g"}; + String filterStr = WebappDaoFactoryDB.getFilterBlock(graphVars, mode); + + if (!StringUtils.isEmpty(filterStr)) { + List graphFilteredIndividualList = + getGraphFilteredIndividualList(theClass, filterStr); + List unfilteredIndividualList = getIndividualList(theClass); + Iterator unfilteredIt = unfilteredIndividualList.iterator(); + + for (Individual filt : graphFilteredIndividualList) { + Individual unfilt = unfilteredIt.next(); + while (!unfilt.getURI().equals(filt.getURI())) { + unfilt = unfilteredIt.next(); + } + + ents.add(unfilt); + } + } else { + ents = getIndividualList(theClass); + } + } + + Collections.sort(ents); + + if (quantity > 0 && offset > 0) { + List sublist = new ArrayList<>(); + for (int i = offset - 1; i < ((offset - 1) + quantity); i++) { + sublist.add(ents.get(i)); + } + + return sublist; + } + + return ents; + } + + /** + * Get individuals by data property using the full model. + * + * In Jena it can be difficult to get an object with a given dataproperty if + * you do not care about the datatype or lang of the literal. Use this + * method if you would like to ignore the lang and datatype. + * + * Note: this method doesn't require that a property be declared in the + * ontology as a data property -- only that it behaves as one. + * + * @param dataPropertyUri The data property URI. + * @param value The data property value. + * + * @return The list of matching individuals. + */ + @Override + public List getIndividualsByDataProperty(String dataPropertyUri, String value) { + OntModel fullModel = getOntModelSelector().getFullModel(); + + Property prop = null; + if (RDFS.label.getURI().equals(dataPropertyUri)) { + prop = RDFS.label; + } else { + prop = fullModel.getProperty(dataPropertyUri); + } + + if (prop == null) { + LOG.debug("Could not getIndividualsByDataProperty() because " + dataPropertyUri + + "was not found in model."); + return Collections.emptyList(); + } + + if( value == null ){ + LOG.debug("Could not getIndividualsByDataProperty() because value was null"); + return Collections.emptyList(); + } + + Literal litv1 = fullModel.createLiteral(value); + Literal litv2 = fullModel.createTypedLiteral(value); + + //warning: this assumes that any language tags will be EN + Literal litv3 = fullModel.createLiteral(value,"EN"); + + HashMap individualsMap = new HashMap<>(); + + fullModel.enterCriticalSection(Lock.READ); + try { + StmtIterator stmts = fullModel.listStatements((Resource) null, prop, litv1); + while (stmts.hasNext()) { + Statement stmt = stmts.nextStatement(); + + RDFNode sub = stmt.getSubject(); + if (sub == null || sub.isAnon() || sub.isLiteral()) { + continue; + } + + RDFNode obj = stmt.getObject(); + if (obj == null || !obj.isLiteral()) { + continue; + } + + Literal literal = (Literal) obj; + Object v = literal.getValue(); + if (v == null) { + continue; + } + + String subUri = ((Resource) sub).getURI(); + if (!individualsMap.containsKey(subUri)) { + individualsMap.put(subUri,makeIndividual(subUri)); + } + } + + stmts = fullModel.listStatements((Resource) null, prop, litv2); + while (stmts.hasNext()) { + Statement stmt = stmts.nextStatement(); + + RDFNode sub = stmt.getSubject(); + if (sub == null || sub.isAnon() || sub.isLiteral()) { + continue; + } + + RDFNode obj = stmt.getObject(); + if (obj == null || !obj.isLiteral()) { + continue; + } + + Literal literal = (Literal)obj; + Object v = literal.getValue(); + if (v == null) { + continue; + } + + String subUri = ((Resource)sub).getURI(); + if (!individualsMap.containsKey(subUri)) { + individualsMap.put(subUri, makeIndividual(subUri)); + } + } + + stmts = fullModel.listStatements((Resource) null, prop, litv3); + while (stmts.hasNext()) { + Statement stmt = stmts.nextStatement(); + + RDFNode sub = stmt.getSubject(); + if (sub == null || sub.isAnon() || sub.isLiteral()) { + continue; + } + + RDFNode obj = stmt.getObject(); + if (obj == null || !obj.isLiteral()) { + continue; + } + + Literal literal = (Literal) obj; + Object v = literal.getValue(); + if (v == null) { + continue; + } + + String subUri = ((Resource)sub).getURI(); + if (!individualsMap.containsKey(subUri)) { + individualsMap.put(subUri, makeIndividual(subUri)); + } + } + } finally { + fullModel.leaveCriticalSection(); + } + + List rv = new ArrayList<>(individualsMap.size()); + rv.addAll(individualsMap.values()); + return rv; + } + + /** + * Get each URI for all individuals. + * + * @return The list of URIs. + */ + public Collection getAllIndividualUris() { + final List list = new LinkedList<>(); + + // get all labeled resources from any non-tbox and non-metadata graphs, + // as well as the unnamed graph (first pattern below) + String query = "SELECT DISTINCT ?ind WHERE { \n" + + " { ?ind <" + RDFS.label.getURI() + "> ?label } " + + " UNION { " + + " GRAPH ?g { ?ind <" + RDFS.label.getURI() + "> ?label } \n" + + " FILTER (?g != <" + ModelNames.APPLICATION_METADATA + "> " + + " && !regex(str(?g),\"tbox\")) \n " + + " } " + + "}"; + + Query q = QueryFactory.create(query); + Dataset dataset = dw.getDataset(); + dataset.getLock().enterCriticalSection(Lock.READ); + QueryExecution qe = QueryExecutionFactory.create(q, dataset); + try { + ResultSet rs = qe.execSelect(); + while (rs.hasNext()) { + Resource res = rs.next().getResource("ind"); + if (!res.isAnon()) { + list.add(res.getURI()); + } + } + } finally { + qe.close(); + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + + return list; + } + + /** + * Get individual URIs updated since a given unit of time. + * + * @param updatedSince The instant in time, in milliseconds. + * + * @return A list of all individual URIs. + */ + public Iterator getUpdatedSinceIterator(long updatedSince) { + List individualURIs = new ArrayList(); + Date since = new DateTime(updatedSince).toDate(); + String sinceStr = xsdDateTimeFormat.format(since); + + getOntModel().enterCriticalSection(Lock.READ); + try { + String queryStr = "PREFIX vitro: <"+ VitroVocabulary.vitroURI+"> " + + "PREFIX xsd: "+ + "SELECT ?ent " + + "WHERE { " + + " ?ent vitro:modTime ?modTime ." + + " FILTER (xsd:dateTime(?modTime) >= \"" + + sinceStr + "\"^^xsd:dateTime) " + + "}"; + Query query = QueryFactory.create(queryStr); + QueryExecution qe = QueryExecutionFactory.create(query,getOntModel()); + try { + ResultSet results = qe.execSelect(); + while (results.hasNext()) { + QuerySolution qs = results.next(); + Resource res = (Resource) qs.get("?ent"); + if (res.getURI() != null) { + individualURIs.add(res.getURI()); + } + } + } finally { + qe.close(); + } + } finally { + getOntModel().leaveCriticalSection(); + } + + return individualURIs.iterator(); + } + + /** + * Get the web application DAO factory for databases such as TDB. + * + * @return The web application DAO factory. + */ + protected WebappDaoFactoryDB getWebappDaoFactory() { + return (WebappDaoFactoryDB) super.getWebappDaoFactory(); + } + + /** + * Get the ontology model. + * + * @return the Ontology model. + */ + protected OntModel getOntModel() { + return getOntModelSelector().getABoxModel(); + } + + /** + * Make an individual. + * + * @param indURI The URI of the individual. + * + * @return The made individual. + */ + protected Individual makeIndividual(String indURI) { + try { + return new IndividualDB(indURI, dw, mode, getWebappDaoFactory()); + } catch (IndividualNotFoundException e) { + LOG.debug("The individual represented by " + indURI + " does not exist"); + } catch (Exception ex) { + LOG.error("An error occurred trying to make an individual ", ex); + + if (StringUtils.isNotEmpty(indURI)) { + LOG.error("IndividualURI equals " + indURI); + } else { + LOG.error("IndividualURI is null or empty"); + } + } + + return null; + } + + /** + * Get a list of individuals associated with the class resource. + * + * @param theClass The class resource. + * + * @return The list of individuals. + */ + private List getIndividualList(Resource theClass) { + final List ents = new ArrayList<>(); + Dataset dataset = dw.getDataset(); + + dataset.getLock().enterCriticalSection(Lock.READ); + try { + String query = + "SELECT DISTINCT ?ind ?label " + + "WHERE " + + "{ \n" + + "{ ?ind a <" + theClass.getURI() + "> } \n" + + "UNION { \n" + + " ?ind a <" + theClass.getURI() + "> . \n" + + " ?ind <" + RDFS.label.getURI() + "> ?label \n" + + "} \n" + + "} ORDER BY ?ind ?label"; + + RDFService rdfService = getWebappDaoFactory().getRDFService(); + try { + rdfService.sparqlSelectQuery(query, new ResultSetConsumer() { + String uri = null; + String label = null; + + protected void processQuerySolution(QuerySolution qs) { + Resource currRes = qs.getResource("ind"); + if (currRes.isAnon()) { + return; + } + + if (uri != null && !uri.equals(currRes.getURI())) { + try { + ents.add(makeIndividual(uri, label)); + } catch (IndividualNotFoundException e) { + // don't add + } + + uri = currRes.getURI(); + label = null; + } else if (uri == null) { + uri = currRes.getURI(); + } + + Literal labelLit = qs.getLiteral("label"); + if (labelLit != null) { + label = labelLit.getLexicalForm(); + } + } + + @Override + protected void endProcessing() { + if (uri != null) { + try { + ents.add(makeIndividual(uri, label)); + } catch (IndividualNotFoundException e) { + // don't add + } + } + } + }); + } catch (RDFServiceException e) { + LOG.debug(e); + throw new RuntimeException(e); + } + } finally { + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + + return ents; + } + + /** + * Get a filtered list of individuals associated with the class resource. + * + * @param theClass The class resource. + * @param filter The filter. + * + * @return The list of individuals. + */ + private List getGraphFilteredIndividualList(Resource theClass, String filter) { + final List filteredIndividualList = new ArrayList<>(); + Dataset dataset = dw.getDataset(); + + dataset.getLock().enterCriticalSection(Lock.READ); + try { + String query = + "SELECT DISTINCT ?ind " + + "WHERE " + + "{ GRAPH ?g { \n" + + "{ ?ind a <" + theClass.getURI() + "> } \n" + + " } \n" + filter + + "} ORDER BY ?ind"; + RDFService rdfService = getWebappDaoFactory().getRDFService(); + try { + rdfService.sparqlSelectQuery(query, new ResultSetConsumer() { + protected void processQuerySolution(QuerySolution qs) { + Resource currRes = qs.getResource("ind"); + if (!currRes.isAnon()) { + try { + filteredIndividualList.add(makeIndividual(currRes.getURI(), null)); + } catch (IndividualNotFoundException e) { + // don't add + } + } + } + }); + } catch (RDFServiceException e) { + LOG.debug(e); + throw new RuntimeException(e); + } + } finally { + dataset.getLock().leaveCriticalSection(); + //w.close(); + } + + return filteredIndividualList; + } + + /** + * Make an individual. + * + * @param indURI The URI of the individual. + * @param label The label of the individual. + * + * @return The made individual. + */ + private Individual makeIndividual(String indURI, String label) + throws IndividualNotFoundException { + + Individual ent = new IndividualDB( + indURI, dw, mode, (WebappDaoFactoryDB) getWebappDaoFactory(), true); + + ent.setName(label); + ent.setRdfsLabel(label); + return ent; + } +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java index a2bdf8e905..2c1fde8970 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoJena.java @@ -52,7 +52,7 @@ public class IndividualDaoJena extends JenaBaseDao implements IndividualDao { //For random number generation, creating it everytime the method is called lead to nextInt being about the same //if calls were made close together in time - private Random random = new Random(System.currentTimeMillis()); + protected Random random = new Random(System.currentTimeMillis()); public IndividualDaoJena(WebappDaoFactoryJena wadf) { super(wadf); } @@ -131,49 +131,44 @@ public List getIndividualsByVClassURI(String vclassURI) { } public List getIndividualsByVClassURI(String vclassURI, int offset, int quantity ) { - - if (vclassURI==null) { + if (vclassURI == null) { return null; } - List ents = new ArrayList(); + List ents = new ArrayList<>(); Resource theClass = (vclassURI.indexOf(PSEUDO_BNODE_NS) == 0) ? getOntModel().createResource(new AnonId(vclassURI.split("#")[1])) : ResourceFactory.createResource(vclassURI); - - if (theClass.isAnon() && theClass.canAs(UnionClass.class)) { - UnionClass u = theClass.as(UnionClass.class); - for (OntClass operand : u.listOperands().toList()) { - VClass vc = new VClassJena(operand, getWebappDaoFactory()); - ents.addAll(getIndividualsByVClass(vc)); - } + UnionClass u = theClass.as(UnionClass.class); + for (OntClass operand : u.listOperands().toList()) { + VClass vc = new VClassJena(operand, getWebappDaoFactory()); + ents.addAll(getIndividualsByVClass(vc)); + } } else { - OntModel ontModel = getOntModelSelector().getABoxModel(); - try { - ontModel.enterCriticalSection(Lock.READ); - StmtIterator stmtIt = ontModel.listStatements((Resource) null, RDF.type, theClass); - try { - while (stmtIt.hasNext()) { - Statement stmt = stmtIt.nextStatement(); - OntResource ind = stmt.getSubject().as(OntResource.class); - ents.add(new IndividualJena(ind, getWebappDaoFactory())); - } - } finally { - stmtIt.close(); - } - } finally { - ontModel.leaveCriticalSection(); - } + OntModel ontModel = getOntModelSelector().getABoxModel(); + try { + ontModel.enterCriticalSection(Lock.READ); + StmtIterator stmtIt = ontModel.listStatements((Resource) null, RDF.type, theClass); + try { + while (stmtIt.hasNext()) { + Statement stmt = stmtIt.nextStatement(); + OntResource ind = stmt.getSubject().as(OntResource.class); + ents.add(new IndividualJena(ind, getWebappDaoFactory())); + } + } finally { + stmtIt.close(); + } + } finally { + ontModel.leaveCriticalSection(); + } } - java.util.Collections.sort(ents); return ents; - } public int getCountOfIndividualsInVClass(String vclassURI ) { @@ -711,8 +706,8 @@ public String getUnusedURI(Individual individual) throws InsertException { // This method returns an EditLiteral rather than a Jena Literal, since IndividualDao // should not reference Jena objects. (However, the problem isn't really solved // because EditLiteral currently references the Jena API.) - public EditLiteral getLabelEditLiteral(String individualUri) { - Literal literal = getLabelLiteral(individualUri); + public EditLiteral getLabelEditLiteral(String individualURI) { + Literal literal = getLabelLiteral(individualURI); if (literal == null) { return null; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java deleted file mode 100644 index bfc57e80ea..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualDaoSDB.java +++ /dev/null @@ -1,550 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; - -import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; - -import org.apache.jena.ontology.OntClass; -import org.apache.jena.ontology.OntModel; -import org.apache.jena.ontology.UnionClass; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.Query; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryExecutionFactory; -import org.apache.jena.query.QueryFactory; -import org.apache.jena.query.QuerySolution; -import org.apache.jena.query.ResultSet; -import org.apache.jena.rdf.model.AnonId; -import org.apache.jena.rdf.model.Literal; -import org.apache.jena.rdf.model.Property; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.rdf.model.StmtIterator; -import org.apache.jena.shared.Lock; -import org.apache.jena.vocabulary.RDFS; - -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.IndividualSDB.IndividualNotFoundException; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; - -public class IndividualDaoSDB extends IndividualDaoJena { - - private DatasetWrapperFactory dwf; - private SDBDatasetMode datasetMode; - private WebappDaoFactorySDB wadf; - - public IndividualDaoSDB(DatasetWrapperFactory dwf, - SDBDatasetMode datasetMode, - WebappDaoFactorySDB wadf) { - super(wadf); - this.dwf = dwf; - this.datasetMode = datasetMode; - this.wadf = wadf; - } - - protected DatasetWrapper getDatasetWrapper() { - return dwf.getDatasetWrapper(); - } - - protected Individual makeIndividual(String individualURI) { - try { - return new IndividualSDB(individualURI, - this.dwf, - datasetMode, - wadf); - } catch (IndividualNotFoundException e) { - // If the individual does not exist, return null. - return null; - } catch(Exception ex) { - //Should some other error occur, please log it here - log.error("An error occurred trying to make an individual ", ex); - if(StringUtils.isNotEmpty(individualURI)) { - log.error("IndividualURI equals " + individualURI); - } else { - log.error("IndividualURI is null or empty"); - } - return null; - } - } - - private static final Log log = LogFactory.getLog( - IndividualDaoSDB.class.getName()); - - @Override - protected OntModel getOntModel() { - return getOntModelSelector().getABoxModel(); - } - - private static final boolean SKIP_INITIALIZATION = true; - - @Override - public List getIndividualsByVClassURI(String vclassURI, - int offset, - int quantity ) { - - if (vclassURI==null) { - return null; - } - - List ents = new ArrayList(); - - Resource theClass = (vclassURI.indexOf(PSEUDO_BNODE_NS) == 0) - ? getOntModel().createResource(new AnonId(vclassURI.split("#")[1])) - : ResourceFactory.createResource(vclassURI); - - if (theClass.isAnon() && theClass.canAs(UnionClass.class)) { - UnionClass u = theClass.as(UnionClass.class); - for (OntClass operand : u.listOperands().toList()) { - VClass vc = new VClassJena(operand, getWebappDaoFactory()); - ents.addAll(getIndividualsByVClass(vc)); - } - } else { - - List individualList; - - // Check if there is a graph filter. - // If so, we will use it in a slightly strange way. Unfortunately, - // performance is quite bad if we add several graph variables in - // order to account for the fact that an individual's type - // declaration may be in a different graph from its label. - // Thus, we will run two queries: one with a single - // graph variable to get the list of URIs, and a second against - // the union graph to get individuals with their labels. - // We will then toss out any individual in the second - // list that is not also in the first list. - // Annoying, yes, but better than the alternative. - // Note that both queries need to sort identically or - // the results may be very strange. - String[] graphVars = {"?g"}; - String filterStr = WebappDaoFactorySDB.getFilterBlock( - graphVars, datasetMode); - if (!StringUtils.isEmpty(filterStr)) { - List graphFilteredIndividualList = - getGraphFilteredIndividualList(theClass, filterStr); - List unfilteredIndividualList = getIndividualList( - theClass); - Iterator unfilteredIt = unfilteredIndividualList - .iterator(); - for (Individual filt : graphFilteredIndividualList) { - Individual unfilt = unfilteredIt.next(); - while (!unfilt.getURI().equals(filt.getURI())) { - unfilt = unfilteredIt.next(); - } - ents.add(unfilt); - } - } else { - ents = getIndividualList(theClass); - } - } - - java.util.Collections.sort(ents); - - if (quantity > 0 && offset > 0) { - List sublist = new ArrayList(); - for (int i = offset - 1; i < ((offset - 1) + quantity); i++) { - sublist.add(ents.get(i)); - } - return sublist; - } - - return ents; - - } - - private List getIndividualList(Resource theClass) { - final List ents = new ArrayList(); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - String query = - "SELECT DISTINCT ?ind ?label " + - "WHERE " + - "{ \n" + - "{ ?ind a <" + theClass.getURI() + "> } \n" + - "UNION { \n" + - " ?ind a <" + theClass.getURI() + "> . \n" + - " ?ind <" + RDFS.label.getURI() + "> ?label \n" + - "} \n" + - "} ORDER BY ?ind ?label"; - - RDFService rdfService = wadf.getRDFService(); - try { - rdfService.sparqlSelectQuery( - query, new ResultSetConsumer() { - String uri = null; - String label = null; - - @Override - protected void processQuerySolution(QuerySolution qs) { - Resource currRes = qs.getResource("ind"); - if (currRes.isAnon()) { - return; - } - - if (uri != null && !uri.equals(currRes.getURI())) { - try { - ents.add(makeIndividual(uri, label)); - } catch (IndividualNotFoundException e) { - // don't add - } - uri = currRes.getURI(); - label = null; - } else if (uri == null) { - uri = currRes.getURI(); - } - Literal labelLit = qs.getLiteral("label"); - if (labelLit != null) { - label = labelLit.getLexicalForm(); - } - } - - @Override - protected void endProcessing() { - if (uri != null) { - try { - ents.add(makeIndividual(uri, label)); - } catch (IndividualNotFoundException e) { - // don't add - } - } - } - }); - } catch (RDFServiceException e) { - log.debug(e,e); - throw new RuntimeException(e); - } - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - return ents; - } - - private List getGraphFilteredIndividualList(Resource theClass, - String filterStr) { - final List filteredIndividualList = new ArrayList(); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - String query = - "SELECT DISTINCT ?ind " + - "WHERE " + - "{ GRAPH ?g { \n" + - "{ ?ind a <" + theClass.getURI() + "> } \n" + - " } \n" + filterStr + - "} ORDER BY ?ind"; - RDFService rdfService = wadf.getRDFService(); - try { - rdfService.sparqlSelectQuery( - query, new ResultSetConsumer() { - @Override - protected void processQuerySolution(QuerySolution qs) { - Resource currRes = qs.getResource("ind"); - if (!currRes.isAnon()) { - try { - filteredIndividualList.add( - makeIndividual(currRes.getURI(), null)); - } catch (IndividualNotFoundException e) { - // don't add - } - } - } - }); - } catch (RDFServiceException e) { - log.debug(e,e); - throw new RuntimeException(e); - } - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - return filteredIndividualList; - } - - private Individual makeIndividual(String uri, String label) throws IndividualNotFoundException { - Individual ent = new IndividualSDB(uri, - this.dwf, datasetMode, wadf, - SKIP_INITIALIZATION); - ent.setName(label); - ent.setRdfsLabel(label); - return ent; - } - - @Override - public Individual getIndividualByURI(String entityURI) { - if( entityURI == null || entityURI.length() == 0 ) { - return null; - } else { - return makeIndividual(entityURI); - } - } - - /** - * fills in the Individual objects needed for any ObjectPropertyStatements - * attached to the specified individual. - * @param entity An individual - */ - private void fillIndividualsForObjectPropertyStatements(Individual entity){ - getOntModel().enterCriticalSection(Lock.READ); - try { - for (ObjectPropertyStatement e2e : entity.getObjectPropertyStatements()) { - e2e.setSubject(makeIndividual(e2e.getSubjectURI())); - e2e.setObject(makeIndividual(e2e.getObjectURI())); - } - } finally { - getOntModel().leaveCriticalSection(); - } - } - - /** - * In Jena it can be difficult to get an object with a given dataproperty if - * you do not care about the datatype or lang of the literal. Use this - * method if you would like to ignore the lang and datatype. - * - * Note: this method doesn't require that a property be declared in the - * ontology as a data property -- only that it behaves as one. - */ - @Override - public List getIndividualsByDataProperty(String dataPropertyUri, - String value){ - OntModel fullModel = getOntModelSelector().getFullModel(); - - Property prop = null; - if( RDFS.label.getURI().equals( dataPropertyUri )){ - prop = RDFS.label; - }else{ - prop = fullModel.getProperty(dataPropertyUri); - } - - if( prop == null ) { - log.debug("Could not getIndividualsByDataProperty() " + - "because " + dataPropertyUri + "was not found in model."); - return Collections.emptyList(); - } - - if( value == null ){ - log.debug("Could not getIndividualsByDataProperty() " + - "because value was null"); - return Collections.emptyList(); - } - - Literal litv1 = fullModel.createLiteral(value); - Literal litv2 = fullModel.createTypedLiteral(value); - - //warning: this assumes that any language tags will be EN - Literal litv3 = fullModel.createLiteral(value,"EN"); - - HashMap individualsMap = - new HashMap(); - - fullModel.enterCriticalSection(Lock.READ); - int count = 0; - try{ - StmtIterator stmts - = fullModel.listStatements((Resource)null, prop, litv1); - while(stmts.hasNext()){ - count++; - Statement stmt = stmts.nextStatement(); - - RDFNode sub = stmt.getSubject(); - if( sub == null || sub.isAnon() || sub.isLiteral() ) - continue; - - RDFNode obj = stmt.getObject(); - if( obj == null || !obj.isLiteral() ) - continue; - - Literal literal = (Literal)obj; - Object v = literal.getValue(); - if( v == null ) - continue; - - String subUri = ((Resource)sub).getURI(); - if( ! individualsMap.containsKey(subUri)){ - individualsMap.put(subUri,makeIndividual(subUri)); - } - } - - stmts = fullModel.listStatements((Resource)null, prop, litv2); - while(stmts.hasNext()){ - count++; - Statement stmt = stmts.nextStatement(); - - RDFNode sub = stmt.getSubject(); - if( sub == null || sub.isAnon() || sub.isLiteral() ) - continue; - - RDFNode obj = stmt.getObject(); - if( obj == null || !obj.isLiteral() ) - continue; - - Literal literal = (Literal)obj; - Object v = literal.getValue(); - if( v == null ) - continue; - - String subUri = ((Resource)sub).getURI(); - if( ! individualsMap.containsKey(subUri)){ - individualsMap.put(subUri, makeIndividual(subUri)); - } - } - - stmts = fullModel.listStatements((Resource)null, prop, litv3); - while(stmts.hasNext()){ - count++; - Statement stmt = stmts.nextStatement(); - - RDFNode sub = stmt.getSubject(); - if( sub == null || sub.isAnon() || sub.isLiteral() ) - continue; - - RDFNode obj = stmt.getObject(); - if( obj == null || !obj.isLiteral() ) - continue; - - Literal literal = (Literal)obj; - Object v = literal.getValue(); - if( v == null ) - continue; - - String subUri = ((Resource)sub).getURI(); - if( ! individualsMap.containsKey(subUri)){ - individualsMap.put(subUri, makeIndividual(subUri)); - } - } - } finally { - fullModel.leaveCriticalSection(); - } - - List rv = new ArrayList(individualsMap.size()); - rv.addAll(individualsMap.values()); - return rv; - } - - @Override - public Collection getAllIndividualUris() { - final List list = new LinkedList(); - - // get all labeled resources from any non-tbox and non-metadata graphs, - // as well as the unnamed graph (first pattern below) - String query = "SELECT DISTINCT ?ind WHERE { \n" + - " { ?ind <" + RDFS.label.getURI() + "> ?label } " + - " UNION { " + - " GRAPH ?g { ?ind <" + RDFS.label.getURI() + - "> ?label } \n" + - " FILTER (?g != <" + ModelNames.APPLICATION_METADATA + "> " + - " && !regex(str(?g),\"tbox\")) \n " + - " } " + - "}"; - - Query q = QueryFactory.create(query); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - QueryExecution qe = QueryExecutionFactory.create(q, dataset); - try { - ResultSet rs = qe.execSelect(); - while (rs.hasNext()) { - Resource res = rs.next().getResource("ind"); - if (!res.isAnon()) { - list.add(res.getURI()); - } - } - } finally { - qe.close(); - dataset.getLock().leaveCriticalSection(); - w.close(); - } - - return list; - } - - private Iterator getIndividualIterator( - final List individualURIs) { - if (individualURIs.size() >0){ - log.info("Number of individuals from source: " - + individualURIs.size()); - return new Iterator(){ - Iterator innerIt = individualURIs.iterator(); - public boolean hasNext() { - return innerIt.hasNext(); - } - public Individual next() { - String indURI = innerIt.next(); - Individual ind = makeIndividual(indURI); - if (ind != null) { - return ind; - } else { - return new IndividualImpl(indURI); - } - } - public void remove() { - //not used - } - }; - } - else - return null; - } - - @Override - public Iterator getUpdatedSinceIterator(long updatedSince){ - List individualURIs = new ArrayList(); - Date since = new DateTime(updatedSince).toDate(); - String sinceStr = xsdDateTimeFormat.format(since); - getOntModel().enterCriticalSection(Lock.READ); - try { - String queryStr = "PREFIX vitro: <"+ VitroVocabulary.vitroURI+"> " + - "PREFIX xsd: "+ - "SELECT ?ent " + - "WHERE { " + - " ?ent vitro:modTime ?modTime ." + - " FILTER (xsd:dateTime(?modTime) >= \"" - + sinceStr + "\"^^xsd:dateTime) " + - "}"; - Query query = QueryFactory.create(queryStr); - QueryExecution qe = QueryExecutionFactory.create( - query,getOntModel()); - try { - ResultSet results = qe.execSelect(); - while (results.hasNext()) { - QuerySolution qs = results.next(); - Resource res = (Resource) qs.get("?ent"); - if (res.getURI() != null) { - individualURIs.add(res.getURI()); - } - } - } finally { - qe.close(); - } - } finally { - getOntModel().leaveCriticalSection(); - } - return individualURIs.iterator(); - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java index c3ec8bb750..0645b81316 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java @@ -2,6 +2,9 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; +import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.IND_MAIN_IMAGE; +import static edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary.PSEUDO_BNODE_NS; + import java.sql.Timestamp; import java.text.Collator; import java.util.ArrayList; @@ -38,44 +41,37 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo; public class IndividualJena extends IndividualImpl implements Individual { - private static final Log log = LogFactory.getLog(IndividualJena.class.getName()); - private OntResource ind = null; - private WebappDaoFactoryJena webappDaoFactory = null; - private Float _searchBoostJena = null; + private static final Log LOG = LogFactory.getLog(IndividualJena.class.getName()); + private boolean retrievedNullRdfsLabel = false; + private OntResource ind = null; + private WebappDaoFactoryJena wadf = null; + public IndividualJena(OntResource ind, WebappDaoFactoryJena wadf) { this.ind = ind; - if (ind.isAnon()) { - this.setNamespace(VitroVocabulary.PSEUDO_BNODE_NS); - this.setLocalName(ind.getId().toString()); - } else { - this.URI = ind.getURI(); - this.namespace = ind.getNameSpace(); - this.localName = ind.getLocalName(); - } - this.webappDaoFactory = wadf; + this.wadf = wadf; + + setupURIParts(this.ind); } public String getName() { if (this.name != null) { return name; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - this.name = webappDaoFactory.getJenaBaseDao().getLabelOrId(ind); - if (this.name == null) { - this.name = "[null]"; - } - return this.name; - } finally { - ind.getOntModel().leaveCriticalSection(); + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + this.name = wadf.getJenaBaseDao().getLabelOrId(ind); + if (this.name == null) { + this.name = "[null]"; } + return this.name; + } finally { + ind.getOntModel().leaveCriticalSection(); } } @@ -86,345 +82,334 @@ public String getLabel() { public String getRdfsLabel() { if (this.rdfsLabel != null) { return rdfsLabel; - } else if( this.rdfsLabel == null && retrievedNullRdfsLabel ){ - return null; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - this.rdfsLabel = webappDaoFactory.getJenaBaseDao().getLabel(ind); - retrievedNullRdfsLabel = this.rdfsLabel == null; - return this.rdfsLabel; - } finally { - ind.getOntModel().leaveCriticalSection(); - } + } + if (this.rdfsLabel == null && retrievedNullRdfsLabel) { + return null; + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + this.rdfsLabel = wadf.getJenaBaseDao().getLabel(ind); + retrievedNullRdfsLabel = this.rdfsLabel == null; + return this.rdfsLabel; + } finally { + ind.getOntModel().leaveCriticalSection(); } } public String getVClassURI() { if (this.vClassURI != null) { return vClassURI; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - ClosableIterator typeIt = ind.listRDFTypes(true); - try { - while (typeIt.hasNext()) { - Resource type = (Resource) typeIt.next(); - if (type.getNameSpace()!=null && (!webappDaoFactory.getJenaBaseDao().NONUSER_NAMESPACES.contains(type.getNameSpace()) || type.getURI().equals(OWL.Thing.getURI())) ) { - this.vClassURI=type.getURI(); - break; - } - } - } finally { - typeIt.close(); + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + ClosableIterator typeIt = ind.listRDFTypes(true); + try { + while (typeIt.hasNext()) { + Resource type = typeIt.next(); + if (type.getNameSpace()!=null && (!wadf.getJenaBaseDao().NONUSER_NAMESPACES + .contains(type.getNameSpace()) || type.getURI() + .equals(OWL.Thing.getURI())) ) { + + this.vClassURI=type.getURI(); + break; + } } - } finally { - ind.getOntModel().leaveCriticalSection(); - } - return this.vClassURI; + } finally { + typeIt.close(); + } + } finally { + ind.getOntModel().leaveCriticalSection(); } + return this.vClassURI; } public VClass getVClass() { if (this.vClass != null) { return this.vClass; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - ClosableIterator typeIt = ind.listRDFTypes(true); - try { - while (typeIt.hasNext()) { - Resource type = (Resource) typeIt.next(); - if (type.getNameSpace()!=null && (!webappDaoFactory.getJenaBaseDao().NONUSER_NAMESPACES.contains(type.getNameSpace()) || type.getURI().equals(OWL.Thing.getURI())) ) { - this.vClassURI=type.getURI(); - this.vClass = webappDaoFactory.getVClassDao().getVClassByURI(this.vClassURI); - break; - } - } - } finally { - typeIt.close(); - } - return this.vClass; - } finally { - ind.getOntModel().leaveCriticalSection(); - } + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + ClosableIterator typeIt = ind.listRDFTypes(true); + try { + while (typeIt.hasNext()) { + Resource type = (Resource) typeIt.next(); + if (type.getNameSpace()!=null && (!wadf.getJenaBaseDao().NONUSER_NAMESPACES + .contains(type.getNameSpace()) || type.getURI() + .equals(OWL.Thing.getURI()))) { + + this.vClassURI=type.getURI(); + this.vClass = wadf.getVClassDao().getVClassByURI(this.vClassURI); + break; + } + } + } finally { + typeIt.close(); + } + return this.vClass; + } finally { + ind.getOntModel().leaveCriticalSection(); } } public Timestamp getModTime() { if (modTime != null) { return modTime; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - Date modDate = webappDaoFactory.getJenaBaseDao().getPropertyDateTimeValue(ind,webappDaoFactory.getJenaBaseDao().MODTIME); - if (modDate != null) { - modTime = new Timestamp(modDate.getTime()); - } - return modTime; - } finally { - ind.getOntModel().leaveCriticalSection(); + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + Date modDate = wadf.getJenaBaseDao().getPropertyDateTimeValue(ind, + wadf.getJenaBaseDao().MODTIME); + if (modDate != null) { + modTime = new Timestamp(modDate.getTime()); } + return modTime; + } finally { + ind.getOntModel().leaveCriticalSection(); } } - public Float getSearchBoost(){ - if( this._searchBoostJena != null ){ - return this._searchBoostJena; - }else{ - ind.getOntModel().enterCriticalSection(Lock.READ); - try{ - try { - searchBoost = - ((Literal)ind.getPropertyValue(webappDaoFactory.getJenaBaseDao().SEARCH_BOOST_ANNOT)).getFloat(); - } catch (Exception e) { - searchBoost = null; - } - return searchBoost; - }finally{ - ind.getOntModel().leaveCriticalSection(); - } + public Float getSearchBoost() { + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + searchBoost = ((Literal) ind + .getPropertyValue(wadf.getJenaBaseDao().SEARCH_BOOST_ANNOT)).getFloat(); + } catch (Exception e) { + LOG.debug(e); + searchBoost = null; + } finally { + ind.getOntModel().leaveCriticalSection(); } + return searchBoost; } - @Override - public String getMainImageUri() { - if (this.mainImageUri != NOT_INITIALIZED) { - return mainImageUri; - } else { - for (ObjectPropertyStatement stmt : getObjectPropertyStatements()) { - if (stmt.getPropertyURI() - .equals(VitroVocabulary.IND_MAIN_IMAGE)) { - mainImageUri = stmt.getObjectURI(); - return mainImageUri; - } - } - return null; - } - } + public String getMainImageUri() { + if (this.mainImageUri != NOT_INITIALIZED) { + return mainImageUri; + } + for (ObjectPropertyStatement stmt : getObjectPropertyStatements()) { + if (stmt.getPropertyURI().equals(IND_MAIN_IMAGE)) { + // arbitrarily return the first value in the list. + mainImageUri = stmt.getObjectURI(); + return mainImageUri; + } + } + return null; + } - @Override - public String getImageUrl() { - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.instanceFromEntityUri(webappDaoFactory, this); - log.trace("figured imageInfo for " + getURI() + ": '" - + this.imageInfo + "'"); - } - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; - log.trace("imageInfo for " + getURI() + " is empty."); - } - return this.imageInfo.getMainImage().getBytestreamAliasUrl(); - } + public String getImageUrl() { + if (this.imageInfo == null) { + this.imageInfo = ImageInfo.instanceFromEntityUri(wadf, this); + LOG.trace("figured imageInfo for " + getURI() + ": '" + this.imageInfo + "'"); + } + if (this.imageInfo == null) { + this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; + LOG.trace("imageInfo for " + getURI() + " is empty."); + } + return this.imageInfo.getMainImage().getBytestreamAliasUrl(); + } - @Override - public String getThumbUrl() { - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.instanceFromEntityUri(webappDaoFactory, this); - log.trace("figured imageInfo for " + getURI() + ": '" - + this.imageInfo + "'"); - } - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; - log.trace("imageInfo for " + getURI() + " is empty."); - } - return this.imageInfo.getThumbnail().getBytestreamAliasUrl(); - } + public String getThumbUrl() { + if (this.imageInfo == null) { + this.imageInfo = ImageInfo.instanceFromEntityUri(wadf, this); + LOG.trace("figured imageInfo for " + getURI() + ": '" + this.imageInfo + "'"); + } + if (this.imageInfo == null) { + this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; + LOG.trace("imageInfo for " + getURI() + " is empty."); + } + return this.imageInfo.getThumbnail().getBytestreamAliasUrl(); + } public List getObjectPropertyStatements() { if (this.objectPropertyStatements != null) { return this.objectPropertyStatements; - } else { - try { - webappDaoFactory.getObjectPropertyStatementDao().fillExistingObjectPropertyStatements(this); - } catch (Exception e) { - log.error(this.getClass().getName()+" could not fill existing ObjectPropertyStatements for "+this.getURI(), e); - } - return this.objectPropertyStatements; } + try { + wadf.getObjectPropertyStatementDao().fillExistingObjectPropertyStatements(this); + } catch (Exception e) { + LOG.error(this.getClass().getName() + + " could not fill existing ObjectPropertyStatements for " + this.getURI(), e); + } + return this.objectPropertyStatements; } @Override public List getObjectPropertyStatements(String propertyURI) { - if (propertyURI == null) { - return null; - } - List objectPropertyStatements = new ArrayList(); - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - StmtIterator sit = ind.listProperties(ind.getModel().getProperty(propertyURI)); - while (sit.hasNext()) { - Statement s = sit.nextStatement(); - if (!s.getSubject().canAs(OntResource.class) || !s.getObject().canAs(OntResource.class)) { - continue; - } - Individual subj = new IndividualJena(s.getSubject().as(OntResource.class), webappDaoFactory); - Individual obj = new IndividualJena(s.getObject().as(OntResource.class), webappDaoFactory); - ObjectProperty op = webappDaoFactory.getObjectPropertyDao().getObjectPropertyByURI(s.getPredicate().getURI()); - if (subj != null && obj != null && op != null) { - ObjectPropertyStatement ops = new ObjectPropertyStatementImpl(); - ops.setSubject(subj); - ops.setSubjectURI(subj.getURI()); - ops.setObject(obj); - ops.setObjectURI(obj.getURI()); - ops.setProperty(op); - ops.setPropertyURI(op.getURI()); - objectPropertyStatements.add(ops); - } - } - } finally { - ind.getOntModel().leaveCriticalSection(); - } - return objectPropertyStatements; + if (propertyURI == null) { + return null; + } + List objectPropertyStatements = new ArrayList<>(); + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + StmtIterator sit = ind.listProperties(ind.getModel().getProperty(propertyURI)); + while (sit.hasNext()) { + Statement s = sit.nextStatement(); + if (!s.getSubject().canAs(OntResource.class) || !s.getObject().canAs(OntResource.class)) { + continue; + } + Individual subj = new IndividualJena(s.getSubject().as(OntResource.class), wadf); + Individual obj = new IndividualJena(s.getObject().as(OntResource.class), wadf); + ObjectProperty op = wadf.getObjectPropertyDao().getObjectPropertyByURI(s.getPredicate().getURI()); + if (subj != null && obj != null && op != null) { + ObjectPropertyStatement ops = new ObjectPropertyStatementImpl(); + ops.setSubject(subj); + ops.setSubjectURI(subj.getURI()); + ops.setObject(obj); + ops.setObjectURI(obj.getURI()); + ops.setProperty(op); + ops.setPropertyURI(op.getURI()); + objectPropertyStatements.add(ops); + } + } + } finally { + ind.getOntModel().leaveCriticalSection(); + } + return objectPropertyStatements; } @Override public List getRelatedIndividuals(String propertyURI) { - if (propertyURI == null) { - return null; - } - List relatedIndividuals = new ArrayList(); - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - NodeIterator values = ind.listPropertyValues(ind.getModel().getProperty(propertyURI)); - while (values.hasNext()) { - RDFNode value = values.nextNode(); - if (value.canAs(OntResource.class)) { - relatedIndividuals.add( - new IndividualJena(value.as(OntResource.class), webappDaoFactory) ); - } - } - } finally { - ind.getOntModel().leaveCriticalSection(); - } - return relatedIndividuals; + if (propertyURI == null) { + return null; + } + List relatedIndividuals = new ArrayList(); + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + NodeIterator values = ind.listPropertyValues(ind.getModel().getProperty(propertyURI)); + while (values.hasNext()) { + RDFNode value = values.nextNode(); + if (value.canAs(OntResource.class)) { + relatedIndividuals.add(new IndividualJena(value.as(OntResource.class), wadf)); + } + } + } finally { + ind.getOntModel().leaveCriticalSection(); + } + return relatedIndividuals; } @Override public Individual getRelatedIndividual(String propertyURI) { - if (propertyURI == null) { - return null; - } - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - RDFNode value = ind.getPropertyValue(ind.getModel().getProperty(propertyURI)); - if (value != null && value.canAs(OntResource.class)) { - return new IndividualJena(value.as(OntResource.class), webappDaoFactory); - } else { - return null; - } - } finally { - ind.getOntModel().leaveCriticalSection(); - } + if (propertyURI == null) { + return null; + } + ind.getOntModel().enterCriticalSection(Lock.READ); + try { + RDFNode value = ind.getPropertyValue(ind.getModel().getProperty(propertyURI)); + if (value != null && value.canAs(OntResource.class)) { + return new IndividualJena(value.as(OntResource.class), wadf); + } + return null; + } finally { + ind.getOntModel().leaveCriticalSection(); + } } public List getObjectPropertyList() { if (this.propertyList != null) { return this.propertyList; - } else { - try { - webappDaoFactory.getObjectPropertyDao().fillObjectPropertiesForIndividual( this ); - } catch (Exception e) { - log.error(this.getClass().getName()+" could not fillEntityProperties for "+this.getURI()); - } - return this.propertyList; } + try { + wadf.getObjectPropertyDao().fillObjectPropertiesForIndividual(this); + } catch (Exception e) { + LOG.error(this.getClass().getName() + " could not fillEntityProperties for " + + this.getURI()); + } + return this.propertyList; } @Override public List getPopulatedObjectPropertyList() { if (populatedObjectPropertyList == null) { - populatedObjectPropertyList = webappDaoFactory.getObjectPropertyDao().getObjectPropertyList(this); + populatedObjectPropertyList = wadf.getObjectPropertyDao().getObjectPropertyList(this); } return populatedObjectPropertyList; } @Override - public Map getObjectPropertyMap() { - if (this.objectPropertyMap != null) { - return objectPropertyMap; - } else { - Map map = new HashMap(); - if (this.propertyList == null) { - getObjectPropertyList(); - } - for (ObjectProperty op : this.propertyList) { - if (op.getURI() != null) { - map.put(op.getURI(), op); - } - } - this.objectPropertyMap = map; - return map; - } + public Map getObjectPropertyMap() { + if (this.objectPropertyMap != null) { + return objectPropertyMap; + } + Map map = new HashMap<>(); + if (this.propertyList == null) { + getObjectPropertyList(); + } + for (ObjectProperty op : this.propertyList) { + if (op.getURI() != null) { + map.put(op.getURI(), op); + } + } + this.objectPropertyMap = map; + return map; } public List getDataPropertyStatements() { if (this.dataPropertyStatements != null) { return this.dataPropertyStatements; - } else { - try { - webappDaoFactory.getDataPropertyStatementDao().fillExistingDataPropertyStatementsForIndividual(this/*,false*/); - } catch (Exception e) { - log.error(this.getClass().getName()+" could not fill existing DataPropertyStatements for "+this.getURI()); - } - return this.dataPropertyStatements; } + try { + wadf.getDataPropertyStatementDao().fillExistingDataPropertyStatementsForIndividual(this/*,false*/); + } catch (Exception e) { + LOG.error(this.getClass().getName() + + " could not fill existing DataPropertyStatements for " + this.getURI()); + } + return this.dataPropertyStatements; } public List getDataPropertyList() { if (this.datatypePropertyList != null) { return this.datatypePropertyList; - } else { - try { - webappDaoFactory.getDataPropertyDao().fillDataPropertiesForIndividual( this ); - } catch (Exception e) { - log.error(this.getClass().getName()+" could not fill data properties for "+this.getURI()); - } - return this.datatypePropertyList; } + try { + wadf.getDataPropertyDao().fillDataPropertiesForIndividual(this); + } catch (Exception e) { + LOG.error(this.getClass().getName() + " could not fill data properties for " + + this.getURI()); + } + return this.datatypePropertyList; } @Override public List getPopulatedDataPropertyList() { if (populatedDataPropertyList == null) { - populatedDataPropertyList = webappDaoFactory.getDataPropertyDao().getDataPropertyList(this); + populatedDataPropertyList = wadf.getDataPropertyDao().getDataPropertyList(this); } return populatedDataPropertyList; } @Override - public Map getDataPropertyMap() { - if (this.dataPropertyMap != null) { - return dataPropertyMap; - } else { - Map map = new HashMap(); - if (this.datatypePropertyList == null) { - getDataPropertyList(); - } - for (DataProperty dp : this.datatypePropertyList) { - if (dp.getURI() != null) { - map.put(dp.getURI(), dp); - } - } - this.dataPropertyMap = map; - return map; - } + public Map getDataPropertyMap() { + if (this.dataPropertyMap != null) { + return dataPropertyMap; + } + Map map = new HashMap<>(); + if (this.datatypePropertyList == null) { + getDataPropertyList(); + } + for (DataProperty dp : this.datatypePropertyList) { + if (dp.getURI() != null) { + map.put(dp.getURI(), dp); + } + } + this.dataPropertyMap = map; + return map; } public List getExternalIds() { // BJL 2007-11-11: need to decide whether we want to use Collections or Lists in our interfaces - we seem to be leaning toward Lists if (this.externalIds != null) { return this.externalIds; - } else { - try { - List dpsList = new ArrayList(); - dpsList.addAll(webappDaoFactory.getIndividualDao().getExternalIds(this.getURI(), null)); - this.externalIds = dpsList; - } catch (Exception e) { - log.error(this.getClass().getName()+" could not fill external IDs for "+this.getURI()); - } - return this.externalIds; } + try { + List dpsList = new ArrayList<>(); + dpsList.addAll(wadf.getIndividualDao().getExternalIds(this.getURI(), null)); + this.externalIds = dpsList; + } catch (Exception e) { + LOG.error(this.getClass().getName() + " could not fill external IDs for " + + this.getURI()); + } + return this.externalIds; } @Override @@ -434,52 +419,51 @@ public List getVClasses() { @Override public List getVClasses(boolean direct) { - if (direct) { - if (directVClasses != null) { - return directVClasses; - } else { - directVClasses = getMyVClasses(true); - return directVClasses; - } - } else { - if (allVClasses != null) { - return allVClasses; - } else { - allVClasses = getMyVClasses(false); - return allVClasses; - } - } + if (direct) { + if (directVClasses != null) { + return directVClasses; + } + directVClasses = getMyVClasses(true); + return directVClasses; + } + if (allVClasses != null) { + return allVClasses; + } + allVClasses = getMyVClasses(false); + return allVClasses; } private List getMyVClasses(boolean direct) { - List vClassList = new ArrayList(); - OntModel ontModel = ind.getOntModel(); - ontModel.enterCriticalSection(Lock.READ); - try { - ClosableIterator typeIt = ind.listRDFTypes(direct); - try { - for (Iterator it = typeIt; it.hasNext();) { - Resource type = (Resource) typeIt.next(); - String typeURI = (!type.isAnon()) ? type.getURI() : VitroVocabulary.PSEUDO_BNODE_NS + type.getId().toString(); - if (type.getNameSpace() == null || (!webappDaoFactory.getNonuserNamespaces().contains(type.getNameSpace())) ) { - VClass vc = webappDaoFactory.getVClassDao().getVClassByURI(typeURI); - if (vc != null) { - vClassList.add(vc); - } - } - - } - } finally { - typeIt.close(); - } - } finally { - ontModel.leaveCriticalSection(); - } - try { - Collections.sort(vClassList); - } catch (Exception e) {} - return vClassList; - } + List vClassList = new ArrayList<>(); + OntModel ontModel = ind.getOntModel(); + ontModel.enterCriticalSection(Lock.READ); + try { + ClosableIterator typeIt = ind.listRDFTypes(direct); + try { + for (Iterator it = typeIt; it.hasNext();) { + Resource type = typeIt.next(); + String typeURI = (!type.isAnon()) + ? type.getURI() + : PSEUDO_BNODE_NS + type.getId().toString(); + if (type.getNameSpace() == null || + (!wadf.getNonuserNamespaces().contains(type.getNameSpace()))) { + VClass vc = wadf.getVClassDao().getVClassByURI(typeURI); + if (vc != null) { + vClassList.add(vc); + } + } + } + } finally { + typeIt.close(); + } + } finally { + ontModel.leaveCriticalSection(); + } + try { + Collections.sort(vClassList); + } catch (Exception e) {} + return vClassList; + } /** * The base method in {@link IndividualImpl} is adequate if the reasoner is @@ -498,7 +482,7 @@ public boolean isVClass(String uri) { return true; } - VClassDao vclassDao = webappDaoFactory.getVClassDao(); + VClassDao vclassDao = wadf.getVClassDao(); for (VClass vClass : getVClasses(true)) { for (String superClassUri: vclassDao.getAllSuperClassURIs(vClass.getURI())) { if (uri.equals(superClassUri)) { @@ -529,9 +513,9 @@ protected void sortEnts2EntsForDisplay(){ private Collator collator = Collator.getInstance(); private void sortObjectPropertyStatementsForDisplay(ObjectProperty prop) { - try { - log.info("Doing special sort for "+prop.getDomainPublic()); - final String sortPropertyURI = prop.getObjectIndividualSortPropertyURI(); + try { + LOG.info("Doing special sort for "+prop.getDomainPublic()); + final String sortPropertyURI = prop.getObjectIndividualSortPropertyURI(); String tmpDir; boolean tmpAsc; @@ -562,7 +546,7 @@ public final int compare(Object o1, Object o2){ val1 = ""; } } else { - log.warn( "IndividualJena.sortObjectPropertiesForDisplay passed object property statement with no range entity."); + LOG.warn( "IndividualJena.sortObjectPropertiesForDisplay passed object property statement with no range entity."); } if( e2 != null ){ @@ -576,7 +560,7 @@ public final int compare(Object o1, Object o2){ val2 = ""; } } else { - log.warn( "IndividualJena.sortObjectPropertyStatementsForDisplay() was passed an object property statement with no range entity."); + LOG.warn( "IndividualJena.sortObjectPropertyStatementsForDisplay() was passed an object property statement with no range entity."); } int rv = 0; @@ -592,7 +576,7 @@ else if( val1 instanceof Date ) { else rv = 0; } catch (NullPointerException e) { - log.error(e, e); + LOG.error(e, e); } if( cAsc ) @@ -604,18 +588,61 @@ else if( val1 instanceof Date ) { try { getObjectPropertyStatements().sort(comp); } catch (Exception e) { - log.error("Exception sorting object property statements for object property "+this.getURI()); + LOG.error("Exception sorting object property statements for object property "+this.getURI()); } - - } catch (Exception e) { - log.error(e, e); + LOG.error(e, e); } } @Override public void resolveAsFauxPropertyStatements(List list) { - webappDaoFactory.getObjectPropertyStatementDao().resolveAsFauxPropertyStatements(list); + wadf.getObjectPropertyStatementDao().resolveAsFauxPropertyStatements(list); } + /** + * Setup the URI parts from the individual ontology. + * + * @param ind The individual ontology resource. + */ + protected void setupURIParts(OntResource ind) { + if (ind != null) { + if (ind.isAnon()) { + this.setNamespace(PSEUDO_BNODE_NS); + this.setLocalName(ind.getId().toString()); + } else { + this.URI = ind.getURI(); + this.namespace = ind.getNameSpace(); + this.localName = ind.getLocalName(); + } + } + } + + /** + * Get web application DAO factory. + * + * @return The web application DAO factory. + */ + protected WebappDaoFactoryJena getWebappDaoFactory() { + return wadf; + } + + /** + * Get the individual ontology resource. + * + * @return The ontology resource. + */ + protected OntResource getInd() { + return ind; + } + + /** + * Set the individual ontology resource. + * + * @param The ontology resource. + */ + protected void setInd(OntResource ind) { + this.ind = ind; + } + } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java deleted file mode 100644 index 8abeaa3d17..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java +++ /dev/null @@ -1,1063 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import static edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode.ASSERTIONS_ONLY; - -import java.sql.Timestamp; -import java.text.Collator; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import edu.cornell.mannlib.vitro.webapp.rdfservice.ResultSetConsumer; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.joda.time.DateTime; - -import org.apache.jena.ontology.OntModel; -import org.apache.jena.ontology.OntModelSpec; -import org.apache.jena.ontology.OntResource; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryExecutionFactory; -import org.apache.jena.query.QueryFactory; -import org.apache.jena.query.QuerySolution; -import org.apache.jena.query.ResultSet; -import org.apache.jena.rdf.model.Literal; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.rdf.model.StmtIterator; -import org.apache.jena.shared.Lock; -import org.apache.jena.vocabulary.RDF; -import org.apache.jena.vocabulary.RDFS; - -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.IndividualImpl; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; -import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; - -public class IndividualSDB extends IndividualImpl implements Individual { - - private static final Log log = LogFactory.getLog( - IndividualSDB.class.getName()); - private OntResource ind = null; - private WebappDaoFactorySDB webappDaoFactory = null; - private Float _searchBoostJena = null; - private boolean retreivedNullRdfsLabel = false; - private DatasetWrapperFactory dwf = null; - private SDBDatasetMode datasetMode = - SDBDatasetMode.ASSERTIONS_AND_INFERENCES; - private String individualURI = null; - private Model model = null; - private Boolean _hasThumb = null; - - public IndividualSDB(String individualURI, - DatasetWrapperFactory datasetWrapperFactory, - SDBDatasetMode datasetMode, - WebappDaoFactorySDB wadf, - Model initModel) { - this.individualURI = individualURI; - this.webappDaoFactory = wadf; - this.dwf = datasetWrapperFactory; - - try { - initModel.getLock().enterCriticalSection(Lock.READ); - String getStatements = - "CONSTRUCT \n" + - "{ <"+individualURI+"> <" + RDFS.label.getURI() + - "> ?ooo. \n" + - "<"+individualURI+"> a ?type . \n" + - "} \n" + - "WHERE { \n" + - "{ <"+individualURI+"> <" + RDFS.label.getURI() + - "> ?ooo } \n" + - " UNION { <"+individualURI+"> a ?type } \n" + - "} "; - this.model = QueryExecutionFactory.create( - QueryFactory.create(getStatements), initModel) - .execConstruct(); - } finally { - initModel.getLock().leaveCriticalSection(); - } - - OntModel ontModel = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, model); - this.ind = ontModel.createOntResource(individualURI); - setUpURIParts(ind); - } - - public IndividualSDB(String individualURI, - DatasetWrapperFactory datasetWrapperFactory, - SDBDatasetMode datasetMode, - WebappDaoFactorySDB wadf, - boolean skipInitialization) throws IndividualNotFoundException { - this.individualURI = individualURI; - this.datasetMode = datasetMode; - this.dwf = datasetWrapperFactory; - this.webappDaoFactory = wadf; - - // Check that individualURI is valid. (Prevent SPARQL injection attack.) - // Valid syntax is defined here: https://www.w3.org/TR/rdf-sparql-query/#rIRI_REF - if (!individualURI.matches("[^<>\"{}|^`\\\\\u0000-\u0020]*")) { - throw new IndividualNotFoundException(); - } - - if (skipInitialization) { - OntModel ontModel = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM); - this.ind = ontModel.createOntResource(individualURI); - } else { - try { - String getStatements = - "CONSTRUCT " + - "{ <"+individualURI+"> <" + RDFS.label.getURI() + - "> ?ooo \n" + - "} WHERE {" + - "{ <"+individualURI+"> <" + RDFS.label.getURI() + - "> ?ooo } \n" + - "}"; - - model = ModelFactory.createDefaultModel(); - webappDaoFactory.getRDFService().sparqlConstructQuery(getStatements, model); - } catch (RDFServiceException e) { - } - - OntModel ontModel = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM, model); - - if (model.isEmpty() && noTriplesFor(individualURI)) { - throw new IndividualNotFoundException(); - } - - this.ind = ontModel.createOntResource(individualURI); - } - setUpURIParts(ind); - } - - private boolean noTriplesFor(String individualURI) { - try { - return !webappDaoFactory.getRDFService().sparqlAskQuery("ASK { <" + individualURI + "> ?p ?o }"); - } catch (RDFServiceException rse) { - } - - return true; - } - - static final boolean SKIP_INITIALIZATION = true; - - public IndividualSDB(String individualURI, - DatasetWrapperFactory datasetWrapperFactory, - SDBDatasetMode datasetMode, - WebappDaoFactorySDB wadf) throws IndividualNotFoundException { - this(individualURI, - datasetWrapperFactory, - datasetMode, - wadf, - !SKIP_INITIALIZATION); - } - - public class IndividualNotFoundException extends Exception {} - - private void setUpURIParts(OntResource ind) { - if (ind != null) { - if (ind.isAnon()) { - this.setNamespace(VitroVocabulary.PSEUDO_BNODE_NS); - this.setLocalName(ind.getId().toString()); - } else { - this.URI = ind.getURI(); - this.namespace = ind.getNameSpace(); - this.localName = ind.getLocalName(); - } - } else if (individualURI != null) { - log.warn("Null individual returned for URI " + individualURI); - } - } - - private DatasetWrapper getDatasetWrapper() { - return this.dwf.getDatasetWrapper(); - } - - public String getName() { - if (this.name != null) { - return name; - } else { - ind.getOntModel().enterCriticalSection(Lock.READ); - - try { - this.name = webappDaoFactory.getJenaBaseDao().getLabelOrId(ind); - if (this.name == null) { - this.name = "[null]"; - } - return this.name; - - } finally { - - ind.getOntModel().leaveCriticalSection(); - } - } - } - - public String getRdfsLabel() { - if (this.rdfsLabel != null) { - return rdfsLabel; - } else if( this.rdfsLabel == null && retreivedNullRdfsLabel ){ - return null; - } else { - - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - this.rdfsLabel = webappDaoFactory.getJenaBaseDao().getLabel(ind); - retreivedNullRdfsLabel = this.rdfsLabel == null; - return this.rdfsLabel; - } finally { - - ind.getOntModel().leaveCriticalSection(); - } - } - } - - public String getVClassURI() { - if (this.vClassURI != null) { - return vClassURI; - } else { - List clist = getVClasses(true); - return (clist.size() > 0) ? clist.get(0).getURI() : null; - } - } - - public VClass getVClass() { - if (this.vClass != null) { - return this.vClass; - } else { - List clist = getVClasses(true); - return (clist.size() > 0) ? clist.get(0) : null ; - } - } - - @Override - public List getMostSpecificTypeURIs() { - final List typeURIs = new ArrayList(); - if (this.getURI() == null) { - return typeURIs; - } else { - String queryStr = "SELECT ?type WHERE { <" + this.getURI() + "> <" + - VitroVocabulary.MOST_SPECIFIC_TYPE + "> ?type }"; - try { - webappDaoFactory.getRDFService().sparqlSelectQuery(queryStr, new ResultSetConsumer() { - @Override - protected void processQuerySolution(QuerySolution qs) { - RDFNode node = qs.get("type"); - if (node.isURIResource()) { - typeURIs.add(node.asResource().getURI()); - } - } - }); - - return typeURIs; - } catch (RDFServiceException e) { - throw new RuntimeException(e); - } - } - } - - public Timestamp getModTime() { - if (modTime != null) { - return modTime; - } else { - - ind.getOntModel().enterCriticalSection(Lock.READ); - try { - Date modDate = webappDaoFactory.getJenaBaseDao() - .getPropertyDateTimeValue( - ind,webappDaoFactory.getJenaBaseDao().MODTIME); - if (modDate != null) { - modTime = new Timestamp(modDate.getTime()); - } - return modTime; - } finally { - - ind.getOntModel().leaveCriticalSection(); - } - } - } - - public Float getSearchBoost(){ - if( this._searchBoostJena != null ){ - return this._searchBoostJena; - }else{ - String getPropertyValue = - "SELECT ?value \n" + - "WHERE { \n" + - "<" +individualURI+ "> <" +webappDaoFactory.getJenaBaseDao().SEARCH_BOOST_ANNOT+ "> ?value \n" + - "}"; - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - QueryExecution qe = QueryExecutionFactory.create( - QueryFactory.create(getPropertyValue), dataset); - try{ - ResultSet rs = qe.execSelect(); - if(rs.hasNext()){ - QuerySolution qs = rs.nextSolution(); - if(qs.get("value") !=null){ - Literal value = qs.get("value").asLiteral(); - searchBoost = Float.parseFloat(value.getLexicalForm()); - return searchBoost; - } - } else{ - return null; - } - } catch (Exception e){ - log.error(e,e); - return null; - } finally{ - qe.close(); - dataset.getLock().leaveCriticalSection(); - w.close(); - } - } - return null; - } - - @Override - public String getMainImageUri() { - if (this.mainImageUri != NOT_INITIALIZED) { - return mainImageUri; - } else { - List mainImgStmts = - getObjectPropertyStatements(VitroVocabulary.IND_MAIN_IMAGE); - if (mainImgStmts != null && mainImgStmts.size() > 0) { - // arbitrarily return the first value in the list - mainImageUri = mainImgStmts.get(0).getObjectURI(); - return mainImageUri; - } - return null; - } - } - - @Override - public String getImageUrl() { - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.instanceFromEntityUri( - webappDaoFactory, this); - log.trace("figured imageInfo for " + getURI() + ": '" - + this.imageInfo + "'"); - } - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; - log.trace("imageInfo for " + getURI() + " is empty."); - } - return this.imageInfo.getMainImage().getBytestreamAliasUrl(); - } - - @Override - public String getThumbUrl() { - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.instanceFromEntityUri( - webappDaoFactory, this); - log.trace("figured imageInfo for " + getURI() + ": '" - + this.imageInfo + "'"); - } - if (this.imageInfo == null) { - this.imageInfo = ImageInfo.EMPTY_IMAGE_INFO; - log.trace("imageInfo for " + getURI() + " is empty."); - } - return this.imageInfo.getThumbnail().getBytestreamAliasUrl(); - } - - @Override - public boolean hasThumb(){ - if( _hasThumb != null ){ - return _hasThumb; - }else{ - String ask = - "ASK { " + - " <" + individualURI + "> ?mainImage . \n" + - " ?mainImage ?thumbImage . }\n" ; - try{ - _hasThumb = webappDaoFactory.getRDFService().sparqlAskQuery(ask); - }catch(Exception ex){ - _hasThumb = false; - log.error(ex,ex); - } - return _hasThumb; - } - } - - public List getObjectPropertyStatements() { - if (this.objectPropertyStatements != null) { - return this.objectPropertyStatements; - } else { - try { - webappDaoFactory.getObjectPropertyStatementDao() - .fillExistingObjectPropertyStatements(this); - } catch (Exception e) { - log.error("Could not fill existing ObjectPropertyStatements for " - + this.getURI(), e); - } - return this.objectPropertyStatements; - } - } - - @Override - public List getObjectPropertyStatements(String propertyURI) { - if (propertyURI == null) { - return null; - } - List objectPropertyStatements = new ArrayList - (); - Model tempModel = ModelFactory.createDefaultModel(); - OntModel ontModel = ModelFactory.createOntologyModel( - OntModelSpec.OWL_MEM); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - QueryExecution qexec = null; - try { - String valuesOfProperty = - "CONSTRUCT{ <" + this.individualURI + "> <" + propertyURI + "> ?object }" + - "WHERE{ <" + this.individualURI + "> <" + propertyURI + "> ?object } \n"; - qexec = QueryExecutionFactory.create(QueryFactory.create(valuesOfProperty), dataset); - tempModel = qexec.execConstruct(); - ontModel.add(tempModel.listStatements()); - Resource ontRes = ontModel.getResource(this.individualURI); - StmtIterator sit = ontRes.listProperties(ontRes.getModel().getProperty(propertyURI)); - while (sit.hasNext()) { - Statement s = sit.nextStatement(); - if (!s.getSubject().canAs(OntResource.class) || !s.getObject().canAs(OntResource.class)) { - continue; - } - Individual subj = null; - try { - subj = new IndividualSDB( - s.getSubject().as(OntResource.class).getURI(), - this.dwf, datasetMode, webappDaoFactory); - } catch (IndividualNotFoundException e) { - // leave null subject - } - Individual obj = null; - try { - obj = new IndividualSDB( - s.getObject().as(OntResource.class).getURI(), - this.dwf, datasetMode, webappDaoFactory); - } catch (IndividualNotFoundException e) { - // leave null object - } - ObjectProperty op = webappDaoFactory.getObjectPropertyDao().getObjectPropertyByURI(s.getPredicate().getURI()); - // We don't want to filter out statements simply because we - // can't find a type for the property, so we'll just make a - // new ObjectProperty bean if we can't get one from the DAO. - if (op == null) { - op = new ObjectProperty(); - op.setURI(propertyURI); - } - if (subj != null && obj != null) { - ObjectPropertyStatement ops = new ObjectPropertyStatementImpl(); - ops.setSubject(subj); - ops.setSubjectURI(subj.getURI()); - ops.setObject(obj); - ops.setObjectURI(obj.getURI()); - ops.setProperty(op); - ops.setPropertyURI(op.getURI()); - objectPropertyStatements.add(ops); - } - } - } finally { - if(qexec!=null) qexec.close(); - tempModel.close(); - ontModel.close(); - dataset.getLock().leaveCriticalSection(); - w.close(); - } - return objectPropertyStatements; - } - - @Override - public List getRelatedIndividuals(String propertyURI) { - if (propertyURI == null) { - return null; - } - List relatedIndividuals = new ArrayList(); - - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - String valuesOfProperty = - "SELECT ?object " + - "WHERE{ <" + this.individualURI + "> <" + - propertyURI + "> ?object } \n"; - ResultSet values = QueryExecutionFactory.create( - QueryFactory.create(valuesOfProperty), dataset) - .execSelect(); - QuerySolution result = null; - while (values.hasNext()) { - result = values.next(); - RDFNode value = result.get("object"); - try { - if (value.canAs(OntResource.class)) { - relatedIndividuals.add( - new IndividualSDB( - value.as(OntResource.class).getURI(), - this.dwf, - datasetMode, - webappDaoFactory) ); - } - } catch (IndividualNotFoundException e) { - // don't add to the list - } - } - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - return relatedIndividuals; - } - - @Override - public Individual getRelatedIndividual(String propertyURI) { - if (propertyURI == null) { - return null; - } - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - String valueOfProperty = - "SELECT ?object " + - "WHERE{ <" + this.individualURI + "> <" + - propertyURI + "> ?object } \n"; - QueryExecution qe = QueryExecutionFactory.create( - QueryFactory.create(valueOfProperty), dataset); - try { - ResultSet results = qe.execSelect(); - if (results.hasNext()) { - QuerySolution result = results.next(); - RDFNode value = result.get("object"); - if (value != null && value.canAs(OntResource.class)) { - try { - return new IndividualSDB( - value.as(OntResource.class).getURI(), - dwf, datasetMode, webappDaoFactory); - } catch (IndividualNotFoundException e) { - return null; - } - } - } - return null; - } finally { - qe.close(); - } - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - } - - public List getObjectPropertyList() { - if (this.propertyList != null) { - return this.propertyList; - } else { - try { - webappDaoFactory.getObjectPropertyDao() - .fillObjectPropertiesForIndividual( this ); - } catch (Exception e) { - log.error("Could not fillEntityProperties for " + this.getURI(), e); - } - return this.propertyList; - } - } - - @Override - public List getPopulatedObjectPropertyList() { - if (populatedObjectPropertyList == null) { - populatedObjectPropertyList = webappDaoFactory - .getObjectPropertyDao().getObjectPropertyList(this); - } - return populatedObjectPropertyList; - } - - @Override - public Map getObjectPropertyMap() { - if (this.objectPropertyMap != null) { - return objectPropertyMap; - } else { - Map map = new HashMap(); - if (this.propertyList == null) { - getObjectPropertyList(); - } - for (ObjectProperty op : this.propertyList) { - if (op.getURI() != null) { - map.put(op.getURI(), op); - } - } - this.objectPropertyMap = map; - return map; - } - } - - public List getDataPropertyStatements() { - if (this.dataPropertyStatements != null) { - return this.dataPropertyStatements; - } else { - try { - webappDaoFactory.getDataPropertyStatementDao() - .fillExistingDataPropertyStatementsForIndividual(this); - } catch (Exception e) { - log.error("Could not fill existing DataPropertyStatements for " - + this.getURI(), e); - } - return this.dataPropertyStatements; - } - } - - public List getDataPropertyList() { - if (this.datatypePropertyList != null) { - return this.datatypePropertyList; - } else { - try { - webappDaoFactory.getDataPropertyDao() - .fillDataPropertiesForIndividual( this ); - } catch (Exception e) { - log.error("Could not fill data properties for " + this.getURI(), e); - } - return this.datatypePropertyList; - } - } - - @Override - public List getPopulatedDataPropertyList() { - if (populatedDataPropertyList == null) { - populatedDataPropertyList = webappDaoFactory.getDataPropertyDao() - .getDataPropertyList(this); - } - return populatedDataPropertyList; - } - - @Override - public Map getDataPropertyMap() { - if (this.dataPropertyMap != null) { - return dataPropertyMap; - } else { - Map map = new HashMap(); - if (this.datatypePropertyList == null) { - getDataPropertyList(); - } - for (DataProperty dp : this.datatypePropertyList) { - if (dp.getURI() != null) { - map.put(dp.getURI(), dp); - } - } - this.dataPropertyMap = map; - return map; - } - } - - @Override - public List getDataPropertyStatements(String propertyUri) { - List stmts = this.dataPropertyStatements; - if (stmts == null) { - return sparqlForDataPropertyStatements(propertyUri); - } else { - List stmtsForProp = new ArrayList(); - for (DataPropertyStatement stmt : stmts) { - if (stmt.getDatapropURI().equals(propertyUri)) { - stmtsForProp.add(stmt); - } - } - return stmtsForProp; - } - } - - @Override - public String getDataValue(String propertyUri) { - if (propertyUri == null) { - log.error("Cannot retrieve value for null property"); - return null; - } else if (this.getURI() == null) { - log.error("Cannot retrieve value of property " + propertyUri + - " for anonymous individual"); - return null; - } else { - List stmts = sparqlForDataPropertyStatements( - propertyUri); - if (stmts != null && stmts.size() > 0) { - return stmts.get(0).getData(); - } - } - return null; // not found - } - - @Override - public List getDataValues(String propertyUri) { - List values = new ArrayList(); - if (propertyUri == null) { - log.error("Cannot retrieve value for null property"); - return null; - } else if (this.getURI() == null) { - log.error("Cannot retrieve value of property " + propertyUri + - " for anonymous individual"); - return null; - } else { - List stmts = sparqlForDataPropertyStatements( - propertyUri); - if (stmts != null) { - for (DataPropertyStatement stmt : stmts) { - values.add(stmt.getData()); - } - } - return values; - } - } - - private List sparqlForDataPropertyStatements(final String propertyUri) { - final List stmts = new ArrayList(); - final IndividualSDB individualSDB = this; - - String queryStr = "SELECT (str(?value) as ?valueString) WHERE { <" - + this.getURI() + "> <" + propertyUri + "> ?value }"; - try { - webappDaoFactory.getRDFService().sparqlSelectQuery( - queryStr, new ResultSetConsumer() { - @Override - protected void processQuerySolution(QuerySolution qs) { - RDFNode node = qs.get("valueString"); - if (!node.isLiteral()) { - log.debug("Ignoring non-literal value for " + node + - " for property " + propertyUri); - } else { - Literal lit = node.asLiteral(); - DataPropertyStatement stmt = new DataPropertyStatementImpl(); - - stmt.setData(lit.getLexicalForm()); - stmt.setDatatypeURI(lit.getDatatypeURI()); - stmt.setLanguage(lit.getLanguage()); - stmt.setDatapropURI(propertyUri); - stmt.setIndividualURI(individualSDB.getURI()); - stmt.setIndividual(individualSDB); - stmts.add(stmt); - } - } - }); - } catch (RDFServiceException e) { - log.error(e,e); - throw new RuntimeException(e); - } - return stmts; - } - - public List getExternalIds() { - if (this.externalIds != null) { - return this.externalIds; - } else { - try { - List dpsList = - new ArrayList(); - dpsList.addAll(webappDaoFactory.getIndividualDao() - .getExternalIds(this.getURI(), null)); - this.externalIds = dpsList; - } catch (Exception e) { - log.error("Could not fill external IDs for " + this.getURI(), e); - } - return this.externalIds; - } - } - - @Override - public List getVClasses() { - return getVClasses(false); - } - - @Override - public List getVClasses(boolean assertedOnly) { - if (assertedOnly) { - if (directVClasses != null) { - return directVClasses; - } else { - directVClasses = getMyVClasses(true); - return directVClasses; - } - } else { - if (allVClasses != null) { - return allVClasses; - } else { - allVClasses = getMyVClasses(false); - return allVClasses; - } - } - } - - private List getMyVClasses(boolean assertedOnly) { - List vClassList = new ArrayList(); - Model tempModel = null; - if (ind.getModel().contains((Resource) null, RDF.type, (RDFNode) null)){ - tempModel = ind.getModel(); - } else { - tempModel = ModelFactory.createDefaultModel(); - String getTypesQuery = buildMyVClassesQuery(assertedOnly); - - RDFService service = webappDaoFactory.getRDFService(); - try { - service.sparqlConstructQuery(getTypesQuery, tempModel); - } catch (RDFServiceException e) { - throw new RuntimeException(e); - } - } - StmtIterator stmtItr = tempModel.listStatements( - (Resource) null, RDF.type, (RDFNode) null); - LinkedList list = new LinkedList(); - while(stmtItr.hasNext()){ - Statement stmt = stmtItr.nextStatement(); - if (stmt.getObject().isResource() && !stmt.getObject().isAnon()) { - list.add(((Resource) stmt.getObject()).getURI()); - } - } - Iterator itr = null; - VClassDao checkSubClass = this.webappDaoFactory.getVClassDao(); - boolean directTypes = false; - String currentType = null; - ArrayList done = new ArrayList(); - - /* Loop for comparing starts here */ - if(assertedOnly){ - while(!directTypes){ - itr = list.listIterator(); - - do{ - if(itr.hasNext()){ - currentType = itr.next();} - else{ - directTypes = true; // get next element for comparison - break;} - }while(done.contains(currentType)); - - if(directTypes) - break; - // check to see if it's all over otherwise start comparing - else - itr = list.listIterator(); - - while(itr.hasNext()){ - String nextType = itr.next(); - if(checkSubClass.isSubClassOf(currentType, nextType) - && !currentType.equalsIgnoreCase(nextType)){ - itr.remove(); - } - } - - done.add(currentType); // add the uri to done list. - } - } - - /* Loop for comparing ends here */ - Iterator typeIt = list.iterator(); - - for (Iterator it = typeIt; it.hasNext();) { - Resource type = ResourceFactory - .createResource(it.next().toString()); - String typeURI = (!type.isAnon()) - ? type.getURI() - : VitroVocabulary.PSEUDO_BNODE_NS - + type.getId().toString(); - if (type.getNameSpace() == null || - (!webappDaoFactory.getNonuserNamespaces() - .contains(type.getNameSpace())) ) { - VClass vc = webappDaoFactory.getVClassDao() - .getVClassByURI(type.getURI()); - if (vc != null) { - vClassList.add(vc); - } - } - } - - try { - Collections.sort(vClassList); - } catch (Exception e) { - log.error("Unable to sort VClass list", e); - } - - return vClassList; - } - - /** - * If we are restricting to asserted types, either by request or by dataset - * mode, then filter by graph and include a UNION clause to support - * retrieving inferred types from the unnamed base graph, as in Sesame and - * OWLIM. - */ - private String buildMyVClassesQuery(boolean assertedOnly) { - SDBDatasetMode queryMode = assertedOnly ? ASSERTIONS_ONLY : datasetMode; - - String filterBlock = WebappDaoFactorySDB.getFilterBlock(new String[] { "?g" }, queryMode); - - if (filterBlock.isEmpty()) { - return - "CONSTRUCT { <" + this.individualURI + "> " + "<" + RDF.type + "> ?types }\n" + - "WHERE { <" + this.individualURI +"> <" +RDF.type+ "> ?types } \n"; - } else { - String unionBlock = (queryMode.equals(ASSERTIONS_ONLY)) ? - "" : - "UNION { <" + this.individualURI +"> <" +RDF.type+ "> ?types }"; - return - "CONSTRUCT{ <" + this.individualURI + "> " + "<" + RDF.type + "> ?types }\n" + - "WHERE{ { GRAPH ?g" - + " { <" + this.individualURI +"> <" +RDF.type+ "> ?types } \n" - + filterBlock - + "} \n" - + unionBlock - + "} \n"; - } - } - - /** - * The base method in {@link IndividualImpl} is adequate if the reasoner is - * up to date. - * - * If the base method returns false, check directly to see if - * any of the super classes of the direct classes will satisfy this request. - */ - @Override - public boolean isVClass(String uri) { - if (uri == null || this.getURI() == null) { - return false; - } - String queryString = "ASK { <" + this.getURI() + "> a <" + uri + "> }"; - try { - return webappDaoFactory.getRDFService().sparqlAskQuery(queryString); - } catch (RDFServiceException e) { - throw new RuntimeException(e); - } - } - - /** - * Overriding the base method so that we can do the sorting by arbitrary property here. An - * IndividualSDB has a reference back to the model; everything else is just a dumb bean (for now). - */ - @Override - protected void sortEnts2EntsForDisplay(){ - if( getObjectPropertyList() == null ) return; - - for (ObjectProperty prop : getObjectPropertyList()) { - /* if (prop.getObjectIndividualSortPropertyURI()==null) { - prop.sortObjectPropertyStatementsForDisplay(prop,prop.getObjectPropertyStatements()); - } else {*/ - prop.sortObjectPropertyStatementsForDisplay(prop, prop.getObjectPropertyStatements()); - /* }*/ - } - } - - private Collator collator = Collator.getInstance(); - - private void sortObjectPropertyStatementsForDisplay(ObjectProperty prop) { - try { - log.info("Doing special sort for "+prop.getDomainPublic()); - final String sortPropertyURI = prop.getObjectIndividualSortPropertyURI(); - String tmpDir; - boolean tmpAsc; - - tmpDir = prop.getDomainEntitySortDirection(); - - //valid values are "desc" and "asc", anything else will default to ascending - tmpAsc = !"desc".equalsIgnoreCase(tmpDir); - - final boolean dir = tmpAsc; - Comparator comp = new Comparator(){ - final boolean cAsc = dir; - - public final int compare(Object o1, Object o2){ - ObjectPropertyStatement e2e1= (ObjectPropertyStatement)o1, e2e2=(ObjectPropertyStatement)o2; - Individual e1 , e2; - e1 = e2e1 != null ? e2e1.getObject():null; - e2 = e2e2 != null ? e2e2.getObject():null; - - Object val1 = null, val2 = null; - if( e1 != null ){ - try { - DataProperty dp = e1.getDataPropertyMap().get(sortPropertyURI); - if (dp.getDataPropertyStatements() != null && dp.getDataPropertyStatements().size()>0) { - val1 = dp.getDataPropertyStatements().get(0).getData(); - } - } - catch (Exception e) { - val1 = ""; - } - } else { - log.warn( "IndividualSDB.sortObjectPropertiesForDisplay passed object property statement with no range entity."); - } - - if( e2 != null ){ - try { - DataProperty dp = e2.getDataPropertyMap().get(sortPropertyURI); - if (dp.getDataPropertyStatements() != null && dp.getDataPropertyStatements().size()>0) { - val2 = dp.getDataPropertyStatements().get(0).getData(); - } - } - catch (Exception e) { - val2 = ""; - } - } else { - log.warn( "IndividualSDB.sortObjectPropertyStatementsForDisplay() was passed an object property statement with no range entity."); - } - - int rv = 0; - try { - if( val1 instanceof String ) - rv = collator.compare( ((String)val1) , ((String)val2) ); - //rv = ((String)val1).compareTo((String)val2); - else if( val1 instanceof Date ) { - DateTime dt1 = new DateTime(val1); - DateTime dt2 = new DateTime(val2); - rv = dt1.compareTo(dt2); - } - else - rv = 0; - } catch (NullPointerException e) { - log.error(e, e); - } - - if( cAsc ) - return rv; - else - return rv * -1; - } - }; - try { - getObjectPropertyStatements().sort(comp); - } catch (Exception e) { - log.error("Exception sorting object property statements for object property "+this.getURI()); - } - - - } catch (Exception e) { - log.error(e, e); - } - } - - @Override - public void resolveAsFauxPropertyStatements(List list) { - webappDaoFactory.getObjectPropertyStatementDao().resolveAsFauxPropertyStatements(list); - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java index 6ba1b1134b..5cfa0d9f43 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java @@ -87,7 +87,6 @@ public JenaBaseDao(WebappDaoFactoryJena wadf) { this.NONUSER_NAMESPACES = wadf.getNonuserNamespaces(); this.PREFERRED_LANGUAGES = wadf.getPreferredLanguages(); this.webappDaoFactory = wadf; - } /* ******************** accessors ************************** */ @@ -118,19 +117,18 @@ protected String getPropertyStringValue(OntResource res, Property dataprop) { try { ClosableIterator stateIt = res.getModel().listStatements(res,dataprop,(Literal)null); try { - if (stateIt.hasNext()) + if (stateIt.hasNext()) { return ((Literal)stateIt.next().getObject()).getString(); - else - return null; + } } finally { stateIt.close(); } } catch (Exception e) { - return null; + log.debug(e); } - } else { - return null; } + + return null; } /** @@ -148,21 +146,20 @@ protected void addPropertyStringValue(Resource res, Property dataprop, String va protected Boolean getPropertyBooleanValue(OntResource res, Property dataprop) { if (dataprop != null) { try { - ClosableIterator stateIt = getOntModel().listStatements(res,dataprop,(Literal)null); + StmtIterator stateIt = getOntModel().listStatements(res,dataprop,(Literal)null); try { - if (stateIt.hasNext()) + if (stateIt.hasNext()) { return ((Literal)((Statement)stateIt.next()).getObject()).getBoolean(); - else - return null; + } } finally { stateIt.close(); } } catch (Exception e) { - return null; + log.debug(e); } - } else { - return null; } + + return null; } /** @@ -920,8 +917,8 @@ protected String getLabel(OntResource r){ return label; } - protected Literal getLabelLiteral(String individualUri) { - OntResource resource = webappDaoFactory.getOntModel().createOntResource(individualUri); + protected Literal getLabelLiteral(String individualURI) { + OntResource resource = webappDaoFactory.getOntModel().createOntResource(individualURI); return getLabelLiteral(resource); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java index 9ae00d59e5..78df14bb2a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java @@ -58,10 +58,10 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp private static final Log log = LogFactory.getLog(ObjectPropertyDaoJena.class.getName()); public ObjectPropertyDaoJena(RDFService rdfService, - DatasetWrapperFactory dwf, + DatasetWrapper dw, Map customListViewConfigFileMap, WebappDaoFactoryJena wadf) { - super(rdfService, dwf, wadf); + super(rdfService, dw, wadf); this.customListViewConfigFileMap = customListViewConfigFileMap; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoDB.java new file mode 100644 index 0000000000..48a51713e2 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoDB.java @@ -0,0 +1,262 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import static edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ModelSerializationFormat.N3; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.ModelFactory; +import org.apache.jena.rdf.model.NodeIterator; +import org.apache.jena.rdf.model.RDFNode; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; +import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; +import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils; + +/** + * An extension of {@link ObjectPropertyStatementDaoJena} for databases, such as TDB. + */ +public class ObjectPropertyStatementDaoDB extends ObjectPropertyStatementDaoJena implements ObjectPropertyStatementDao { + private static final Log LOG = LogFactory.getLog(ObjectPropertyStatementDaoDB.class); + + // Get the types of the base entity. + private static final String SUBJECT_TYPE_QUERY = + "PREFIX rdf: \n" + + "CONSTRUCT { \n" + + " ?uri rdf:type ?type . \n" + + "} WHERE { \n" + + " ?uri rdf:type ?type . \n" + + "} \n"; + + // Get the types of all objects of properties. + private static final String OBJECT_TYPE_QUERY = + "PREFIX rdf: \n" + + "CONSTRUCT { \n" + + " ?uri ?p ?o . \n" + + " ?o rdf:type ?type . \n" + + "} WHERE { \n" + + " ?uri ?p ?o . \n" + + " ?o rdf:type ?type . \n" + + "} \n"; + + // Get the labels of all objects of properties. + private static final String OBJECT_LABEL_QUERY = + "PREFIX rdfs: \n" + + "CONSTRUCT { \n" + + " ?uri ?p ?o . \n" + + " ?o rdfs:label ?label . \n" + + "} WHERE { \n" + + " ?uri ?p ?o . \n" + + " ?o rdfs:label ?label . \n" + + "} \n"; + + private final WebappDaoFactoryDB wadf; + private final DatasetMode mode; + + /** + * Initialize the object property statement DAO. + * + * @param rdfService The rdf service. + * @param dwf The data set wrapper. + * @param mode The data set mode. + * @param wadf The web application DAO factory. + */ + public ObjectPropertyStatementDaoDB(RDFService rdfService, DatasetWrapper dw, DatasetMode mode, + WebappDaoFactoryDB wadf) { + + super(rdfService, dw, wadf); + this.wadf = wadf; + this.mode = mode; + } + + /** + * Fill the existing object property statement for the given individual. + * + * @param entity The individual. + * + * @return The filled individual or null. + */ + public Individual fillExistingObjectPropertyStatements(Individual entity) { + if (entity == null || entity.getURI() == null) { + return entity; + } + + List objectPropertyStatements = new ArrayList<>(); + String subjectUri = entity.getURI(); + + Model m = getInfoForObjectsOfThisEntity(subjectUri); + + for (ObjectPropertyPair pair : getRawObjectPropertyPairs(m, + subjectUri)) { + String predicateUri = pair.getPredicateUri(); + String objectUri = pair.getObjectUri(); + + ObjectProperty prop = findRawProperty(predicateUri); + if (prop == null) { + continue; + } + + Individual object = new IndividualDB(objectUri, dw, mode, wadf, m); + objectPropertyStatements.add(createStatement(entity, prop, object)); + } + entity.setObjectPropertyStatements(objectPropertyStatements); + return entity; + } + + /** + * Get the information for objects of the given entity. + * + * Get the types of this entity. Get the related object and the predicates + * by which they are related. Get the types and labels of those related + * objects. + * + * @param subjectUri The URL representing the entity. + * + * @return The model representing the information for objects. + */ + private Model getInfoForObjectsOfThisEntity(String subjectUri) { + Model m = ModelFactory.createDefaultModel(); + + try { + m.add(RDFServiceUtils.parseModel(rdfService.sparqlConstructQuery( + substituteUri(subjectUri, SUBJECT_TYPE_QUERY), N3), N3)); + m.add(RDFServiceUtils.parseModel(rdfService.sparqlConstructQuery( + substituteUri(subjectUri, OBJECT_TYPE_QUERY), N3), N3)); + m.add(RDFServiceUtils.parseModel(rdfService.sparqlConstructQuery( + substituteUri(subjectUri, OBJECT_LABEL_QUERY), N3), N3)); + } catch (RDFServiceException e) { + LOG.warn("Failed to fill object property statements for '" + subjectUri + "'", e); + } + + return m; + } + + /** + * Substitute the "?uri" text with a given URI string in the query. + * + * @param uri The URI to replace with. + * @param query The query to be updated. + * + * @return The altered query. + */ + private String substituteUri(String uri, String query) { + return query.replace("?uri", "<" + uri + "> "); + } + + /** + * Get types for some model and URI. + * + * @param m The model. + * @param uri The URI. + * + * @return A set of types. + */ + private Set getTypes(Model m, String uri) { + Set typeUris = new HashSet<>(); + + NodeIterator iter = m.listObjectsOfProperty(m.createResource(uri), RDF.type); + for (RDFNode typeNode : iter.toSet()) { + if (typeNode.isURIResource()) { + typeUris.add(typeNode.asResource().getURI()); + } + } + + return typeUris; + } + + /** + * Get raw object property pairs. + * + * @param m The model. + * @param subjectUri The subject URI. + * + * @return An array of object property pairs. + */ + private List getRawObjectPropertyPairs(Model m, String subjectUri) { + List list = new ArrayList<>(); + + StmtIterator iter = m.listStatements(m.createResource(subjectUri), null, (RDFNode) null); + for (Statement stmt : iter.toList()) { + if (wadf.getNonuserNamespaces().contains(stmt.getPredicate().getNameSpace())) { + continue; + } + + if (!stmt.getObject().isURIResource()) { + continue; + } + + list.add(new ObjectPropertyPair(stmt.getPredicate().getURI(), + stmt.getObject().asResource().getURI())); + } + + return list; + } + + /** + * Find the raw property for some predicate URI. + * + * @param predicateUri The predicate URI. + * + * @return The raw object property. + */ + private ObjectProperty findRawProperty(String predicateURI) { + return wadf.getObjectPropertyDao().getObjectPropertyByURI(predicateURI); + } + + /** + * Create a statement from the given triple. + * + * @param entity The individual subject. + * @param prop The individual property. + * @param object The individual object (value). + * + * @return The object property statement. + */ + private ObjectPropertyStatement createStatement(Individual entity, ObjectProperty prop, + Individual object) { + + ObjectPropertyStatementImpl ops = new ObjectPropertyStatementImpl(); + ops.setSubject(entity); + ops.setProperty(prop); + ops.setObject(object); + return ops; + } + + /** + * Helper class for a predicate URI and an object pair URI. + */ + private static class ObjectPropertyPair { + private final String predicateURI; + private final String objectURI; + + public ObjectPropertyPair(String predicateUri, String objectUri) { + this.predicateURI = predicateUri; + this.objectURI = objectUri; + } + + public String getPredicateUri() { + return predicateURI; + } + + public String getObjectUri() { + return objectURI; + } + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java index e54ec61a3d..d463e5e9c6 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java @@ -55,15 +55,15 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec private static final Log log = LogFactory.getLog(ObjectPropertyStatementDaoJena.class); - protected DatasetWrapperFactory dwf; + protected DatasetWrapper dw; protected RDFService rdfService; public ObjectPropertyStatementDaoJena(RDFService rdfService, - DatasetWrapperFactory dwf, + DatasetWrapper dw, WebappDaoFactoryJena wadf) { super(wadf); + this.dw = dw; this.rdfService = rdfService; - this.dwf = dwf; } @Override @@ -435,13 +435,11 @@ private Model constructModelForSelectQueries(String subjectUri, return constructedModel; } - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); + Dataset dataset = dw.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); QueryExecution qe = null; try { - qe = QueryExecutionFactory.create( - query, dataset); + qe = QueryExecutionFactory.create(query, dataset); qe.execConstruct(constructedModel); } catch (Exception e) { log.error("Error getting constructed model for subject " @@ -451,7 +449,7 @@ private Model constructModelForSelectQueries(String subjectUri, qe.close(); } dataset.getLock().leaveCriticalSection(); - w.close(); + dw.close(); } } else { rdfService.sparqlConstructQuery(queryString, constructedModel); @@ -507,8 +505,7 @@ public Map getMostSpecificTypesInClassgroupsForIndividual(String Map result = new LinkedHashMap(); Map> types = new LinkedHashMap>(); - DatasetWrapper w = dwf.getDatasetWrapper(); - Dataset dataset = w.getDataset(); + Dataset dataset = dw.getDataset(); dataset.getLock().enterCriticalSection(Lock.READ); QueryExecution qexec = null; try { @@ -552,7 +549,7 @@ public Map getMostSpecificTypesInClassgroupsForIndividual(String if (qexec != null) { qexec.close(); } - w.close(); + dw.close(); } } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoSDB.java deleted file mode 100644 index 905900a1a6..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoSDB.java +++ /dev/null @@ -1,206 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import static edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService.ModelSerializationFormat.N3; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; -import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; -import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.RDFServiceUtils; - -public class ObjectPropertyStatementDaoSDB extends - ObjectPropertyStatementDaoJena implements ObjectPropertyStatementDao { - private static final Log log = LogFactory - .getLog(ObjectPropertyStatementDaoSDB.class); - - // Get the types of the base entity. - private static final String SUBJECT_TYPE_QUERY = "" - + "PREFIX rdf: \n" - + "CONSTRUCT { \n" // - + " ?uri rdf:type ?type . \n" // - + "} WHERE { \n" // - + " ?uri rdf:type ?type . \n" // - + "} \n"; - - // Get the types of all objects of properties. - private static final String OBJECT_TYPE_QUERY = "" - + "PREFIX rdf: \n" - + "CONSTRUCT { \n" // - + " ?uri ?p ?o . \n" // - + " ?o rdf:type ?type . \n" // - + "} WHERE { \n" // - + " ?uri ?p ?o . \n" // - + " ?o rdf:type ?type . \n" // - + "} \n"; - - // Get the labels of all objects of properties. - private static final String OBJECT_LABEL_QUERY = "" - + "PREFIX rdfs: \n" - + "CONSTRUCT { \n" // - + " ?uri ?p ?o . \n" // - + " ?o rdfs:label ?label . \n" // - + "} WHERE { \n" // - + " ?uri ?p ?o . \n" // - + " ?o rdfs:label ?label . \n" // - + "} \n"; - - private final WebappDaoFactorySDB wadf; - private final SDBDatasetMode datasetMode; - - public ObjectPropertyStatementDaoSDB(RDFService rdfService, - DatasetWrapperFactory dwf, SDBDatasetMode datasetMode, - WebappDaoFactorySDB wadf) { - super(rdfService, dwf, wadf); - this.wadf = wadf; - this.datasetMode = datasetMode; - } - - @Override - public Individual fillExistingObjectPropertyStatements(Individual entity) { - if (entity == null || entity.getURI() == null) - return entity; - else { - List objectPropertyStatements = new ArrayList<>(); - String subjectUri = entity.getURI(); - - Model m = getInfoForObjectsOfThisEntity(subjectUri); - - Set subjectTypes = getTypes(m, subjectUri); - for (ObjectPropertyPair pair : getRawObjectPropertyPairs(m, - subjectUri)) { - String predicateUri = pair.getPredicateUri(); - String objectUri = pair.getObjectUri(); - Set objectTypes = getTypes(m, objectUri); - - ObjectProperty prop = findRawProperty(predicateUri); - if (prop == null) { - continue; - } - - Individual object = new IndividualSDB(objectUri, dwf, - datasetMode, wadf, m); - objectPropertyStatements.add(createStatement(entity, prop, - object)); - } - entity.setObjectPropertyStatements(objectPropertyStatements); - return entity; - } - } - - /** - * Get the types of this entity. Get the related object and the predicates - * by which they are related. Get the types and labels of those related - * objects. - */ - private Model getInfoForObjectsOfThisEntity(String subjectUri) { - Model m = ModelFactory.createDefaultModel(); - try { - m.add(RDFServiceUtils.parseModel( - rdfService.sparqlConstructQuery( - substituteUri(subjectUri, SUBJECT_TYPE_QUERY), N3), - N3)); - m.add(RDFServiceUtils.parseModel( - rdfService.sparqlConstructQuery( - substituteUri(subjectUri, OBJECT_TYPE_QUERY), N3), - N3)); - m.add(RDFServiceUtils.parseModel( - rdfService.sparqlConstructQuery( - substituteUri(subjectUri, OBJECT_LABEL_QUERY), N3), - N3)); - } catch (RDFServiceException e) { - log.warn("Failed to fill object property statements for '" - + subjectUri + "'", e); - } - return m; - } - - private String substituteUri(String uri, String query) { - return query.replace("?uri", "<" + uri + "> "); - } - - private Set getTypes(Model m, String uri) { - Set typeUris = new HashSet<>(); - for (RDFNode typeNode : m.listObjectsOfProperty(m.createResource(uri), - RDF.type).toSet()) { - if (typeNode.isURIResource()) { - typeUris.add(typeNode.asResource().getURI()); - } - } - return typeUris; - } - - private List getRawObjectPropertyPairs(Model m, - String subjectUri) { - List list = new ArrayList<>(); - for (Statement stmt : m.listStatements(m.createResource(subjectUri), - null, (RDFNode) null).toList()) { - if (wadf.getNonuserNamespaces().contains( - stmt.getPredicate().getNameSpace())) { - continue; - } - if (!stmt.getObject().isURIResource()) { - continue; - } - list.add(new ObjectPropertyPair(stmt.getPredicate().getURI(), stmt - .getObject().asResource().getURI())); - } - return list; - } - - private ObjectProperty findRawProperty(String predicateUri) { - return wadf.getObjectPropertyDao().getObjectPropertyByURI(predicateUri); - } - - private ObjectPropertyStatement createStatement(Individual entity, - ObjectProperty prop, Individual object) { - ObjectPropertyStatementImpl ops = new ObjectPropertyStatementImpl(); - ops.setSubject(entity); - ops.setProperty(prop); - ops.setObject(object); - return ops; - } - - // ---------------------------------------------------------------------- - // Helper classes - // ---------------------------------------------------------------------- - - private static class ObjectPropertyPair { - private final String predicateUri; - private final String objectUri; - - public ObjectPropertyPair(String predicateUri, String objectUri) { - this.predicateUri = predicateUri; - this.objectUri = objectUri; - } - - public String getPredicateUri() { - return predicateUri; - } - - public String getObjectUri() { - return objectUri; - } - - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java index 8f3b1de99e..453dd7a0ce 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java @@ -73,14 +73,14 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { } protected RDFService rdfService; - protected DatasetWrapperFactory dwf; + protected DatasetWrapper dw; public PropertyDaoJena(RDFService rdfService, - DatasetWrapperFactory dwf, + DatasetWrapper dw, WebappDaoFactoryJena wadf) { super(wadf); + this.dw = dw; this.rdfService = rdfService; - this.dwf = dwf; } @Override diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyInstanceDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyInstanceDaoJena.java index 4d10b9aad1..2d86d6766d 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyInstanceDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyInstanceDaoJena.java @@ -33,9 +33,9 @@ public class PropertyInstanceDaoJena extends PropertyDaoJena implements PropertyInstanceDao { public PropertyInstanceDaoJena(RDFService rdfService, - DatasetWrapperFactory dwf, + DatasetWrapper dw, WebappDaoFactoryJena wadf) { - super(rdfService, dwf, wadf); + super(rdfService, dw, wadf); } public void deleteObjectPropertyStatement(String subjectURI, String propertyURI, String objectURI) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphConnectionGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphConnectionGenerator.java deleted file mode 100644 index 0e2b010ee5..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphConnectionGenerator.java +++ /dev/null @@ -1,47 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class SDBGraphConnectionGenerator { - - private final static Log log = LogFactory.getLog( - SDBGraphConnectionGenerator.class); - - private DataSource ds = null; - private Connection connection = null; - - public SDBGraphConnectionGenerator(DataSource dataSource) { - this.ds = dataSource; - } - - public Connection generateConnection() throws SQLException { - if ( this.connection == null ) { - this.connection = ds.getConnection(); - } else if ( this.connection.isClosed() ) { - try { - this.connection.close(); - } catch (SQLException e) { - // The connection will throw an "Already closed" - // SQLException that we need to catch. We need to - // make this extra call to .close() in order to make - // sure that the connection is returned to the pool. - // This depends on the particular behavior of version - // 1.4 of the Apache Commons connection pool library. - // Earlier versions threw the exception right away, - // making this impossible. Future versions may do the - // same. - } - this.connection = ds.getConnection(); - } - return connection; - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphGenerator.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphGenerator.java deleted file mode 100644 index 23042ccf32..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/SDBGraphGenerator.java +++ /dev/null @@ -1,65 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.jena.graph.Graph; -import org.apache.jena.sdb.SDBFactory; -import org.apache.jena.sdb.Store; -import org.apache.jena.sdb.StoreDesc; - -public class SDBGraphGenerator implements SQLGraphGenerator { - - private static final Log log = LogFactory.getLog(SDBGraphGenerator.class.getName()); - - private SDBGraphConnectionGenerator connGen; - private Connection connection; - private StoreDesc storeDesc; - private String graphID; - - public SDBGraphGenerator(DataSource dataSource, StoreDesc storeDesc, - String graphID) { - this.connGen = new SDBGraphConnectionGenerator(dataSource); - this.storeDesc = storeDesc; - this.graphID = graphID; - } - - public SDBGraphGenerator(SDBGraphConnectionGenerator connectionGenerator, - StoreDesc storeDesc, String graphID) { - this.connGen = connectionGenerator; - this.storeDesc = storeDesc; - this.graphID = graphID; - } - - public boolean isGraphClosed() { - try { - return (connection == null || connection.isClosed()); - } catch (SQLException e) { - throw new RuntimeException(e); - } - } - - public Graph generateGraph() { - try { - this.connection = connGen.generateConnection(); - Store store = SDBFactory.connectStore(connection, storeDesc); - return SDBFactory.connectNamedGraph(store, graphID); - } catch (SQLException e) { - String errMsg = "Unable to generate SDB graph"; - log.error(errMsg, e); - throw new RuntimeException(errMsg, e); - } - } - - public Connection getConnection() { - return connection; - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/StaticDatasetFactory.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/StaticDatasetFactory.java deleted file mode 100644 index 4f8ff6747b..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/StaticDatasetFactory.java +++ /dev/null @@ -1,19 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import org.apache.jena.query.Dataset; - -public class StaticDatasetFactory implements DatasetWrapperFactory { - - private Dataset _dataset; - - public StaticDatasetFactory (Dataset dataset) { - _dataset = dataset; - } - - public DatasetWrapper getDatasetWrapper() { - return new DatasetWrapper(_dataset); - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoDB.java new file mode 100644 index 0000000000..87d8cd3ce7 --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoDB.java @@ -0,0 +1,187 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import org.apache.jena.query.Dataset; +import org.apache.jena.query.Query; +import org.apache.jena.query.QueryExecution; +import org.apache.jena.query.QueryExecutionFactory; +import org.apache.jena.query.QueryFactory; +import org.apache.jena.query.ResultSet; +import org.apache.jena.query.Syntax; +import org.apache.jena.rdf.model.Literal; +import org.apache.jena.rdf.model.Model; +import org.apache.jena.rdf.model.Property; +import org.apache.jena.rdf.model.Resource; +import org.apache.jena.rdf.model.ResourceFactory; +import org.apache.jena.rdf.model.Statement; +import org.apache.jena.rdf.model.StmtIterator; +import org.apache.jena.shared.Lock; +import org.apache.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; +import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import java.util.Collections; + +/** + * An extension of {@link VClassDaoJena} for databases, such as TDB. + */ +public class VClassDaoDB extends VClassDaoJena { + + private DatasetWrapper dw; + private DatasetMode mode; + + /** + * Initialize VClass DAO. + * + * @param dw The data wrapper. + * @param mode The data set mode. + * @param wadf The web application DAO factory. + * @param isUnderlyingStoreReasoned True if is underlying store reasoned and false otherwise. + */ + public VClassDaoDB(DatasetWrapper dw, DatasetMode mode, WebappDaoFactoryJena wadf, + boolean isUnderlyingStoreReasoned) { + + super(wadf, isUnderlyingStoreReasoned); + this.dw = dw; + this.mode = mode; + } + + /** + * Get the data set wrapper. + * + * @return The data set wrapper. + */ + protected DatasetWrapper getDatasetWrapper() { + return dw; + } + + /** + * Add VClasses to the given group. + * + * @param group the VClass group. + * @param includeUninstantiatedClasses True to include and false otherwise. + * @param getIndividualCount True to get the count and false otherwise. + * + * @deprecated + */ + @Deprecated + public void addVClassesToGroup(VClassGroup group, boolean includeUninstantiatedClasses, boolean getIndividualCount) { + + if (getIndividualCount) { + group.setIndividualCount( getClassGroupInstanceCount(group)); + } + + getOntModel().enterCriticalSection(Lock.READ); + try { + if ((group != null) && (group.getURI() != null)) { + Resource groupRes = ResourceFactory.createResource(group.getURI()); + Property inClassGroup = ResourceFactory.createProperty(VitroVocabulary.IN_CLASSGROUP); + if (inClassGroup != null) { + StmtIterator annotIt = getOntModel().listStatements((Resource)null,inClassGroup, groupRes); + try { + while (annotIt.hasNext()) { + try { + Statement annot = (Statement) annotIt.next(); + Resource cls = annot.getSubject(); + VClass vcw = getVClassByURI(cls.getURI()); + if (vcw != null) { + boolean classIsInstantiated = false; + if (getIndividualCount) { + int count = 0; + String[] graphVars = { "?g" }; + String countQueryStr = "SELECT COUNT(DISTINCT ?s) WHERE \n" + + "{ GRAPH ?g { ?s a <" + cls.getURI() + "> } \n" + + WebappDaoFactoryDB.getFilterBlock(graphVars, mode) + + "} \n"; + Query countQuery = QueryFactory.create(countQueryStr, Syntax.syntaxARQ); + DatasetWrapper w = getDatasetWrapper(); + Dataset dataset = w.getDataset(); + dataset.getLock().enterCriticalSection(Lock.READ); + try { + QueryExecution qe = QueryExecutionFactory.create(countQuery, dataset); + ResultSet rs = qe.execSelect(); + count = Integer.parseInt(((Literal) rs.nextSolution().get(".1")).getLexicalForm()); + } finally { + dataset.getLock().leaveCriticalSection(); + w.close(); + } + vcw.setEntityCount(count); + classIsInstantiated = (count > 0); + } else if (!includeUninstantiatedClasses) { + // Note: to support SDB models, may want to do this with + // SPARQL and LIMIT 1 if SDB can take advantage of it + Model aboxModel = getOntModelSelector().getABoxModel(); + aboxModel.enterCriticalSection(Lock.READ); + try { + StmtIterator countIt = aboxModel.listStatements(null,RDF.type,cls); + try { + if (countIt.hasNext()) { + classIsInstantiated = true; + } + } finally { + countIt.close(); + } + } finally { + aboxModel.leaveCriticalSection(); + } + } + + if (includeUninstantiatedClasses || classIsInstantiated) { + group.add(vcw); + } + } + } catch (ClassCastException cce) { + LOG.error(cce, cce); + } + } + } finally { + annotIt.close(); + } + } + } + Collections.sort(group.getVitroClassList()); + } finally { + getOntModel().leaveCriticalSection(); + } + } + + /** + * Get the VClass group instance count + * + * @param vcg the VClass group. + * + * @return The total number of VClass group instances. + */ + int getClassGroupInstanceCount(VClassGroup vcg){ + int count = 0; + + try { + String queryText = + "SELECT COUNT( DISTINCT ?instance ) WHERE { \n" + + " ?class <" + VitroVocabulary.IN_CLASSGROUP + "> <" + vcg.getURI() + "> .\n" + + " ?instance a ?class . \n" + + "} \n" ; + + Query countQuery = QueryFactory.create(queryText, Syntax.syntaxARQ); + DatasetWrapper dw = getDatasetWrapper(); + Dataset dataset = dw.getDataset(); + + dataset.getLock().enterCriticalSection(Lock.READ); + try { + QueryExecution qe = QueryExecutionFactory.create(countQuery, dataset); + ResultSet rs = qe.execSelect(); + count = Integer.parseInt(((Literal) rs.nextSolution().get(".1")).getLexicalForm()); + } finally { + dataset.getLock().leaveCriticalSection(); + dw.close(); + } + } catch (Exception e) { + LOG.error("error in getClassGroupInstanceCount()", e); + } + + return count; + } + +} \ No newline at end of file diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java index 20b207d019..8c69714ced 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java @@ -67,7 +67,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao { - protected static final Log log = LogFactory.getLog(VClassDaoJena.class); + protected static final Log LOG = LogFactory.getLog(VClassDaoJena.class); private final I18nBundle i18n; private boolean isUnderlyingStoreReasoned = false; @@ -200,7 +200,7 @@ public String getLabelForClass(OntClass cls,boolean withPrefix,boolean forPickLi return getLabelOrId(cls); } } catch (Exception e) { - log.error(e, e); + LOG.error(e, e); return "???"; } finally { cls.getModel().leaveCriticalSection(); @@ -264,7 +264,7 @@ public List getDisjointWithClassURIs(String classURI) { } catch (ProfileException pe) { // Current language profile does not support disjointWith axioms. // We'd prefer to return an empty list instead of throwing an exception. - log.error(pe, pe); + LOG.error(pe, pe); } finally { getOntModel().leaveCriticalSection(); } @@ -480,7 +480,7 @@ public List getAllVclasses() { } } } catch (ClassCastException cce) { - log.error(cce, cce); + LOG.error(cce, cce); } } } finally { @@ -532,7 +532,7 @@ private Iterator smarterListHierarchyRootClasses(OntModel ontModel, St rootClassList.add(ontClass.as(OntClass.class)); } } catch (ClassCastException cce) { - log.error(cce, cce); + LOG.error(cce, cce); } } } finally { @@ -639,7 +639,7 @@ public List getSuperClassURIs(String classURI, boolean direct) { supURIs.add(getClassURIStr(cls)); } } catch (Exception e) { - log.debug(e,e); + LOG.debug(e,e); // we'll try this again using a different method // that doesn't try to convert to OntClass supURIs.clear(); @@ -857,8 +857,6 @@ public void addVClassesToGroup(VClassGroup group, boolean includeUninstantiatedC vcw.setEntityCount(count); classIsInstantiated = (count > 0); } else if (!includeUninstantiatedClasses) { - // Note: to support SDB models, may want to do this with - // SPARQL and LIMIT 1 if SDB can take advantage of it Model aboxModel = getOntModelSelector().getABoxModel(); aboxModel.enterCriticalSection(Lock.READ); try { @@ -880,7 +878,7 @@ public void addVClassesToGroup(VClassGroup group, boolean includeUninstantiatedC } } } catch (ClassCastException cce) { - log.error(cce, cce); + LOG.error(cce, cce); } } } finally { @@ -909,7 +907,7 @@ int getClassGroupInstanceCount(VClassGroup vcg){ ResultSet rs =qe.execSelect(); count = Integer.parseInt(((Literal) rs.nextSolution().get(".1")).getLexicalForm()); }catch(Exception ex){ - log.error(ex,ex); + LOG.error(ex,ex); } finally { ontModel.leaveCriticalSection(); } @@ -946,7 +944,7 @@ public int insertNewVClass(VClass cls, OntModel ontModel) throws InsertException ontCls.removeAll(RDFS.label); } } catch (Exception e) { - log.error("error setting label for class "+cls.getURI()); + LOG.error("error setting label for class "+cls.getURI()); } try { if (cls.getGroupURI() != null && cls.getGroupURI().length()>0) { @@ -954,11 +952,11 @@ public int insertNewVClass(VClass cls, OntModel ontModel) throws InsertException if (badURIErrorStr == null) { ontCls.addProperty(IN_CLASSGROUP, getOntModel().getResource(cls.getGroupURI())); } else { - log.error(badURIErrorStr); + LOG.error(badURIErrorStr); } } } catch (Exception e) { - log.error("error linking class "+cls.getURI()+" to class group"); + LOG.error("error linking class "+cls.getURI()+" to class group"); } updatePlainLiteralValue(ontCls, SHORTDEF, cls.getShortDef()); updatePlainLiteralValue(ontCls, EXAMPLE_ANNOT, cls.getExample()); @@ -971,7 +969,7 @@ public int insertNewVClass(VClass cls, OntModel ontModel) throws InsertException try { ontCls.addProperty(HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT, ResourceFactory.createResource(cls.getHiddenFromDisplayBelowRoleLevel().getURI())); } catch (Exception e) { - log.error("error adding HiddenFromDisplayBelowRoleLevel annotation to class "+cls.getURI()); + LOG.error("error adding HiddenFromDisplayBelowRoleLevel annotation to class "+cls.getURI()); } } @@ -980,7 +978,7 @@ public int insertNewVClass(VClass cls, OntModel ontModel) throws InsertException try { ontCls.addProperty(PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT, ResourceFactory.createResource(cls.getProhibitedFromUpdateBelowRoleLevel().getURI())); } catch (Exception e) { - log.error("error adding ProhibitedFromUpdateBelowRoleLevel annotation to class "+cls.getURI()); + LOG.error("error adding ProhibitedFromUpdateBelowRoleLevel annotation to class "+cls.getURI()); } } @@ -989,7 +987,7 @@ public int insertNewVClass(VClass cls, OntModel ontModel) throws InsertException try { ontCls.addProperty(HIDDEN_FROM_PUBLISH_BELOW_ROLE_LEVEL_ANNOT, ResourceFactory.createResource(cls.getHiddenFromPublishBelowRoleLevel().getURI())); } catch (Exception e) { - log.error("error adding HiddenFromPublishBelowRoleLevel annotation to class "+cls.getURI()); + LOG.error("error adding HiddenFromPublishBelowRoleLevel annotation to class "+cls.getURI()); } } @@ -1043,7 +1041,7 @@ public void updateVClass(VClass cls, OntModel ontModel) { updatePropertyStringValue(ontCls,PROPERTY_CUSTOMSHORTVIEWANNOT,cls.getCustomShortView(),ontModel); updatePropertyStringValue(ontCls,PROPERTY_CUSTOMSEARCHVIEWANNOT,cls.getCustomSearchView(),ontModel); } else { - log.error("error: cannot find jena class "+cls.getURI()+" for updating"); + LOG.error("error: cannot find jena class "+cls.getURI()+" for updating"); } } finally { getOntModel().getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),false)); @@ -1063,13 +1061,13 @@ public void deleteClasses2Classes( Classes2Classes c2c, OntModel ontModel ) OntResource subclass = getOntClass(ontModel,c2c.getSubclassURI()); OntResource superclass = getOntClass(ontModel,c2c.getSuperclassURI()); if(subclass == null || superclass == null) { - log.warn("unable to delete " + c2c.getSubclassURI() + + LOG.warn("unable to delete " + c2c.getSubclassURI() + " rdfs:subClassOf " + c2c.getSuperclassURI()); if (subclass == null) { - log.warn(c2c.getSubclassURI() + " not found in the model."); + LOG.warn(c2c.getSubclassURI() + " not found in the model."); } if (superclass == null) { - log.warn(c2c.getSuperclassURI() + " not found in the model."); + LOG.warn(c2c.getSuperclassURI() + " not found in the model."); } return; } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoSDB.java deleted file mode 100644 index cc6e7bea7f..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoSDB.java +++ /dev/null @@ -1,162 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - - -import org.apache.jena.query.Dataset; -import org.apache.jena.query.Query; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryExecutionFactory; -import org.apache.jena.query.QueryFactory; -import org.apache.jena.query.ResultSet; -import org.apache.jena.query.Syntax; -import org.apache.jena.rdf.model.Literal; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.Property; -import org.apache.jena.rdf.model.Resource; -import org.apache.jena.rdf.model.ResourceFactory; -import org.apache.jena.rdf.model.Statement; -import org.apache.jena.rdf.model.StmtIterator; -import org.apache.jena.shared.Lock; -import org.apache.jena.vocabulary.RDF; - -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; - -public class VClassDaoSDB extends VClassDaoJena { - - private DatasetWrapperFactory dwf; - private SDBDatasetMode datasetMode; - - public VClassDaoSDB(DatasetWrapperFactory datasetWrapperFactory, - SDBDatasetMode datasetMode, - WebappDaoFactoryJena wadf, boolean isUnderlyingStoreReasoned) { - super(wadf, isUnderlyingStoreReasoned); - this.dwf = datasetWrapperFactory; - this.datasetMode = datasetMode; - } - - protected DatasetWrapper getDatasetWrapper() { - return dwf.getDatasetWrapper(); - } - - @Deprecated - public void addVClassesToGroup(VClassGroup group, boolean includeUninstantiatedClasses, boolean getIndividualCount) { - - if (getIndividualCount) { - group.setIndividualCount( getClassGroupInstanceCount(group)); - } - - getOntModel().enterCriticalSection(Lock.READ); - try { - if ((group != null) && (group.getURI() != null)) { - Resource groupRes = ResourceFactory.createResource(group.getURI()); - Property inClassGroup = ResourceFactory.createProperty(VitroVocabulary.IN_CLASSGROUP); - if (inClassGroup != null) { - StmtIterator annotIt = getOntModel().listStatements((Resource)null,inClassGroup, groupRes); - try { - while (annotIt.hasNext()) { - try { - Statement annot = (Statement) annotIt.next(); - Resource cls = annot.getSubject(); - VClass vcw = getVClassByURI(cls.getURI()); - if (vcw != null) { - boolean classIsInstantiated = false; - if (getIndividualCount) { - int count = 0; - String[] graphVars = { "?g" }; - String countQueryStr = "SELECT COUNT(DISTINCT ?s) WHERE \n" + - "{ GRAPH ?g { ?s a <" + cls.getURI() + "> } \n" + - WebappDaoFactorySDB.getFilterBlock(graphVars, datasetMode) + - "} \n"; - Query countQuery = QueryFactory.create(countQueryStr, Syntax.syntaxARQ); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - QueryExecution qe = QueryExecutionFactory.create(countQuery, dataset); - ResultSet rs = qe.execSelect(); - count = Integer.parseInt(((Literal) rs.nextSolution().get(".1")).getLexicalForm()); - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - vcw.setEntityCount(count); - classIsInstantiated = (count > 0); - } else if (!includeUninstantiatedClasses) { - // Note: to support SDB models, may want to do this with - // SPARQL and LIMIT 1 if SDB can take advantage of it - Model aboxModel = getOntModelSelector().getABoxModel(); - aboxModel.enterCriticalSection(Lock.READ); - try { - StmtIterator countIt = aboxModel.listStatements(null,RDF.type,cls); - try { - if (countIt.hasNext()) { - classIsInstantiated = true; - } - } finally { - countIt.close(); - } - } finally { - aboxModel.leaveCriticalSection(); - } - } - - if (includeUninstantiatedClasses || classIsInstantiated) { - group.add(vcw); - } - } - } catch (ClassCastException cce) { - log.error(cce, cce); - } - } - } finally { - annotIt.close(); - } - } - } - java.util.Collections.sort(group.getVitroClassList()); - } finally { - getOntModel().leaveCriticalSection(); - } - } - -// protected void addIndividualCountToGroups( List cgList ){ -// for( VClassGroup cg : cgList){ -// cg.setIndividualCount(getClassGroupInstanceCount(cg)); -// } -// } - - @Override - int getClassGroupInstanceCount(VClassGroup vcg){ - int count = 0; - try { - String queryText = - "SELECT COUNT( DISTINCT ?instance ) WHERE { \n" + - " ?class <"+VitroVocabulary.IN_CLASSGROUP+"> <"+vcg.getURI() +"> .\n" + - " ?instance a ?class . \n" + - "} \n" ; - - Query countQuery = QueryFactory.create(queryText, Syntax.syntaxARQ); - DatasetWrapper w = getDatasetWrapper(); - Dataset dataset = w.getDataset(); - dataset.getLock().enterCriticalSection(Lock.READ); - try { - QueryExecution qe = QueryExecutionFactory.create(countQuery, dataset); - ResultSet rs = qe.execSelect(); - count = Integer.parseInt(((Literal) rs.nextSolution().get(".1")).getLexicalForm()); - } finally { - dataset.getLock().leaveCriticalSection(); - w.close(); - } - }catch(Exception ex){ - log.error("error in getClassGroupInstanceCount()", ex); - } - - return count; - } - - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryDB.java new file mode 100644 index 0000000000..308919f31b --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryDB.java @@ -0,0 +1,231 @@ +/* $This file is distributed under the terms of the license in LICENSE$ */ + +package edu.cornell.mannlib.vitro.webapp.dao.jena; + +import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; +import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; +import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; +import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; + +/** + * An extension of {@link WebappDaoFactoryJena} for databases, such as TDB. + */ +public class WebappDaoFactoryDB extends WebappDaoFactoryJena { + + private DatasetMode mode; + + /** + * Initializer for web application DAO factory. + * + * @param base The web application DAO factory. + * @param userURI The URI for the user. + */ + public WebappDaoFactoryDB(WebappDaoFactoryDB base, String userURI) { + super(base.ontModelSelector); + + this.ontModelSelector = base.ontModelSelector; + this.config = base.config; + this.userURI = userURI; + this.dw = base.dw; + this.rdfService = base.rdfService; + this.mode = DatasetMode.ASSERTIONS_AND_INFERENCES; + } + + /** + * Initializer for web application DAO factory. + * + * @param rdfService The RDF service. + * @param ontModelSelector The ontology model selector. + */ + public WebappDaoFactoryDB(RDFService rdfService, OntModelSelector ontModelSelector) { + this(rdfService, ontModelSelector, new WebappDaoFactoryConfig()); + } + + /** + * Initializer for web application DAO factory. + * + * @param rdfService The RDF service. + * @param ontModelSelector The ontology model selector. + * @param config The configuration. + */ + public WebappDaoFactoryDB(RDFService rdfService, OntModelSelector ontModelSelector, + WebappDaoFactoryConfig config) { + + this(rdfService, ontModelSelector, config, null); + } + + /** + * Initializer for web application DAO factory. + * + * @param rdfService The RDF service. + * @param ontModelSelector The ontology model selector. + * @param config The configuration. + * @param mode The data set mode. + */ + public WebappDaoFactoryDB(RDFService rdfService, OntModelSelector ontModelSelector, + WebappDaoFactoryConfig config, DatasetMode mode) { + + super(ontModelSelector, config); + + this.dw = new DatasetWrapper(new RDFServiceDataset(rdfService)); + this.rdfService = rdfService; + + if (mode == null) { + this.mode = DatasetMode.ASSERTIONS_AND_INFERENCES; + } else { + this.mode = mode; + } + } + + /** + * Convert class to a named string. + * + * @return The named string with a hash and notable properties. + */ + public String toString() { + return "WebappDaoFactoryDB[" + Integer.toString(hashCode(), 16) + ", " + mode + "]"; + } + + /** + * Get the individual DAO. + * + * @return The individual DAO. + */ + public IndividualDao getIndividualDao() { + if (entityWebappDao != null) { + return entityWebappDao; + } + + return entityWebappDao = new IndividualDaoDB(dw, mode, this); + } + + /** + * Get the data property statement DAO for databases, such as TDB. + * + * @return The data property statement DAO. + */ + public DataPropertyStatementDaoDB getDataPropertyStatementDao() { + if (!hasDataPropertyStatementDao()) { + setDataPropertyStatementDao(new DataPropertyStatementDaoDB(dw, this)); + } + + return (DataPropertyStatementDaoDB) super.getDataPropertyStatementDao(); + } + + /** + * Set the data property statement DAO for databases, such as TDB. + * + * @param propertyStatement The data property statement DAO. + */ + protected void setDataPropertyStatementDao(DataPropertyStatementDaoDB propertyStatement) { + super.setDataPropertyStatementDao(propertyStatement); + } + + /** + * Get the object property statement DAO for databases, such as TDB. + * + * @return The object property statement DAO. + */ + public ObjectPropertyStatementDaoDB getObjectPropertyStatementDao() { + if (!hasObjectPropertyStatementDao()) { + setObjectPropertyStatementDao( + new ObjectPropertyStatementDaoDB(rdfService, dw, mode, this)); + } + + return (ObjectPropertyStatementDaoDB) super.getObjectPropertyStatementDao(); + } + + /** + * Set the data property statement DAO for databases, such as TDB. + * + * @param propertyStatement The data property statement DAO. + */ + protected void setObjectPropertyStatementDao(ObjectPropertyStatementDaoDB propertyStatement) { + super.setObjectPropertyStatementDao(propertyStatement); + } + + /** + * Get the VClass DAO. + * + * @return The VClass DAO. + */ + public VClassDao getVClassDao() { + if (vClassDao != null) { + return vClassDao; + } + + return vClassDao = new VClassDaoDB(dw, mode, this, config.isUnderlyingStoreReasoned()); + } + + /** + * Get the user aware DAO factory. + * + * @param userURI The URI of the user. + * + * @return The user aware DAO factory. + */ + public WebappDaoFactoryDB getUserAwareDaoFactory(String userURI) { + return new WebappDaoFactoryDB(this, userURI); + } + + /** + * Get the RDF Service. + * + * @return The RDF service. + */ + public RDFService getRDFService() { + return this.rdfService; + } + + public static String getFilterBlock(String[] graphVars, DatasetMode datasetMode) { + StringBuilder filterBlock = new StringBuilder(); + + for (String graphVar : graphVars) { + switch (datasetMode) { + case ASSERTIONS_ONLY: + filterBlock.append("FILTER (") + .append("(!bound(").append(graphVar) + .append(")) || (") + .append(graphVar) + .append(" != <") + .append(ModelNames.ABOX_INFERENCES) + .append("> ") + .append("&& ").append(graphVar).append(" != <") + .append(ModelNames.TBOX_INFERENCES) + .append(">") + .append(") ) \n"); + break; + + case INFERENCES_ONLY: + filterBlock.append("FILTER (") + .append("(!bound(").append(graphVar) + .append(")) || (") + .append(graphVar) + .append(" = <") + .append(ModelNames.ABOX_INFERENCES) + .append("> || ").append(graphVar) + .append(" = <") + .append(ModelNames.TBOX_INFERENCES) + .append(">) )\n"); + break; + default: + break; + } + } + + return filterBlock.toString(); + } + + /** + * Close the DAO and the RDF service. + */ + public void close() { + super.close(); + + if (this.rdfService != null) { + this.rdfService.close(); + } + } + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java index 813cf27ad1..d744f4e24a 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java @@ -78,7 +78,7 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { private Map properties = new HashMap(); - protected DatasetWrapperFactory dwf; + protected DatasetWrapper dw; protected RDFService rdfService; @@ -88,7 +88,7 @@ public WebappDaoFactoryJena(WebappDaoFactoryJena base, String userURI) { this.ontModelSelector = base.ontModelSelector; this.config = base.config; this.userURI = userURI; - this.dwf = base.dwf; + this.dw = base.dw; } public WebappDaoFactoryJena(OntModelSelector ontModelSelector, @@ -109,7 +109,7 @@ public WebappDaoFactoryJena(OntModelSelector ontModelSelector, : null; Dataset dataset = makeInMemoryDataset(assertions, inferences); - this.dwf = new StaticDatasetFactory(dataset); + dw = new DatasetWrapper(dataset); this.rdfService = new RDFServiceModel(ontModelSelector.getFullModel()); @@ -331,15 +331,33 @@ public UserAccountsDao getUserAccountsDao() { return userAccountsDao = new UserAccountsDaoJena(this); } - DataPropertyStatementDao dataPropertyStatementDao = null; + private DataPropertyStatementDao dataPropertyStatementDao = null; @Override public DataPropertyStatementDao getDataPropertyStatementDao() { - if( dataPropertyStatementDao == null ) - dataPropertyStatementDao = new DataPropertyStatementDaoJena( - dwf, this); + if (!hasDataPropertyStatementDao()) { + setDataPropertyStatementDao(new DataPropertyStatementDaoJena(dw, this)); + } return dataPropertyStatementDao; } + /** + * Set the data property statement DAO. + * + * @param propertyStatement The data property statement DAO. + */ + protected void setDataPropertyStatementDao(DataPropertyStatementDao propertyStatement) { + this.dataPropertyStatementDao = propertyStatement; + } + + /** + * Check if the data property statement DAO is defined. + * + * @return True if defined, false if null. + */ + protected boolean hasDataPropertyStatementDao() { + return dataPropertyStatementDao != null; + } + DatatypeDao datatypeDao = null; @Override public DatatypeDao getDatatypeDao() { @@ -352,7 +370,7 @@ public DatatypeDao getDatatypeDao() { @Override public DataPropertyDao getDataPropertyDao() { if( dataPropertyDao == null ) - dataPropertyDao = new DataPropertyDaoJena(rdfService, dwf, this); + dataPropertyDao = new DataPropertyDaoJena(rdfService, dw, this); return dataPropertyDao; } @@ -365,13 +383,31 @@ public IndividualDao getEntityDao() { ObjectPropertyStatementDao objectPropertyStatementDao = null; @Override - public ObjectPropertyStatementDao getObjectPropertyStatementDao() { - if( objectPropertyStatementDao == null ) - objectPropertyStatementDao = new ObjectPropertyStatementDaoJena( - rdfService, dwf, this); + public ObjectPropertyStatementDao getObjectPropertyStatementDao() { + if (!hasObjectPropertyStatementDao()) { + setObjectPropertyStatementDao(new ObjectPropertyStatementDaoJena(rdfService, dw, this)); + } return objectPropertyStatementDao; } + /** + * Set the object property statement DAO. + * + * @param propertyStatement The object property statement DAO. + */ + protected void setObjectPropertyStatementDao(ObjectPropertyStatementDao propertyStatement) { + this.objectPropertyStatementDao = propertyStatement; + } + + /** + * Check if the object property statement DAO is defined. + * + * @return True if defined, false if null. + */ + protected boolean hasObjectPropertyStatementDao() { + return objectPropertyStatementDao != null; + } + private OntologyDao ontologyDao = null; @Override public OntologyDao getOntologyDao() { @@ -385,7 +421,7 @@ public OntologyDao getOntologyDao() { public ObjectPropertyDao getObjectPropertyDao() { if( objectPropertyDao == null ) objectPropertyDao = new ObjectPropertyDaoJena( - rdfService, dwf, config.customListViewConfigFileMap, this); + rdfService, dw, config.customListViewConfigFileMap, this); return objectPropertyDao; } @@ -402,7 +438,7 @@ public FauxPropertyDao getFauxPropertyDao() { @Override public PropertyInstanceDao getPropertyInstanceDao() { if( propertyInstanceDao == null ) - propertyInstanceDao = new PropertyInstanceDaoJena(rdfService, dwf, this); + propertyInstanceDao = new PropertyInstanceDaoJena(rdfService, dw, this); return propertyInstanceDao; } @@ -484,7 +520,7 @@ public WebappDaoFactoryJena (WebappDaoFactoryJena base) { } this.config = base.config; this.userURI = base.userURI; - this.dwf = base.dwf; + this.dw = base.dw; } /** diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactorySDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactorySDB.java deleted file mode 100644 index 7a140f2c3d..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactorySDB.java +++ /dev/null @@ -1,186 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.sql.Connection; -import java.sql.SQLException; - -import org.apache.commons.dbcp2.BasicDataSource; - -import org.apache.jena.query.Dataset; -import org.apache.jena.sdb.SDBFactory; -import org.apache.jena.sdb.Store; -import org.apache.jena.sdb.StoreDesc; -import org.apache.jena.sdb.sql.SDBConnection; - -import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; -import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao; -import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; -import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; - -public class WebappDaoFactorySDB extends WebappDaoFactoryJena { - - private SDBDatasetMode datasetMode = SDBDatasetMode.ASSERTIONS_AND_INFERENCES; - - public WebappDaoFactorySDB(RDFService rdfService, - OntModelSelector ontModelSelector) { - this(rdfService, ontModelSelector, new WebappDaoFactoryConfig()); - } - - public WebappDaoFactorySDB(RDFService rdfService, - OntModelSelector ontModelSelector, - WebappDaoFactoryConfig config) { - this(rdfService, ontModelSelector, config, null); - } - - public WebappDaoFactorySDB(RDFService rdfService, - OntModelSelector ontModelSelector, - WebappDaoFactoryConfig config, - SDBDatasetMode datasetMode) { - super(ontModelSelector, config); - this.dwf = new StaticDatasetFactory(new RDFServiceDataset(rdfService)); - this.rdfService = rdfService; - if (datasetMode != null) { - this.datasetMode = datasetMode; - } - } - - @Override - public String toString() { - return "WebappDaoFactorySDB[" + Integer.toString(hashCode(), 16) + ", " - + datasetMode + "]"; - } - - public WebappDaoFactorySDB(WebappDaoFactorySDB base, String userURI) { - super(base.ontModelSelector); - this.ontModelSelector = base.ontModelSelector; - this.config = base.config; - this.userURI = userURI; - this.dwf = base.dwf; - this.rdfService = base.rdfService; - } - - @Override - public IndividualDao getIndividualDao() { - if (entityWebappDao != null) - return entityWebappDao; - else - return entityWebappDao = new IndividualDaoSDB( - dwf, datasetMode, this); - } - - @Override - public DataPropertyStatementDao getDataPropertyStatementDao() { - if (dataPropertyStatementDao != null) - return dataPropertyStatementDao; - else - return dataPropertyStatementDao = new DataPropertyStatementDaoSDB( - dwf, datasetMode, this); - } - - @Override - public ObjectPropertyStatementDao getObjectPropertyStatementDao() { - if (objectPropertyStatementDao != null) - return objectPropertyStatementDao; - else - return objectPropertyStatementDao = - new ObjectPropertyStatementDaoSDB(rdfService, dwf, datasetMode, this); - } - - @Override - public VClassDao getVClassDao() { - if (vClassDao != null) - return vClassDao; - else - return vClassDao = new VClassDaoSDB(dwf, datasetMode, this, config.isUnderlyingStoreReasoned()); - } - - @Override - public WebappDaoFactory getUserAwareDaoFactory(String userURI) { - return new WebappDaoFactorySDB(this, userURI); - } - - public RDFService getRDFService() { - return this.rdfService; - } - - public enum SDBDatasetMode { - ASSERTIONS_ONLY, INFERENCES_ONLY, ASSERTIONS_AND_INFERENCES - } - - public static String getFilterBlock(String[] graphVars, - SDBDatasetMode datasetMode) { - StringBuilder filterBlock = new StringBuilder(); - for (String graphVar : graphVars) { - switch (datasetMode) { - case ASSERTIONS_ONLY: - filterBlock.append("FILTER (") - .append("(!bound(").append(graphVar) - .append(")) || (") - .append(graphVar) - .append(" != <") - .append(ModelNames.ABOX_INFERENCES) - .append("> ") - .append("&& ").append(graphVar).append(" != <") - .append(ModelNames.TBOX_INFERENCES) - .append(">") - .append(") ) \n"); - break; - case INFERENCES_ONLY: - filterBlock.append("FILTER (") - .append("(!bound(").append(graphVar) - .append(")) || (") - .append(graphVar) - .append(" = <") - .append(ModelNames.ABOX_INFERENCES) - .append("> || ").append(graphVar) - .append(" = <") - .append(ModelNames.TBOX_INFERENCES) - .append(">) )\n"); - break; - default: - break; - } - } - return filterBlock.toString(); - } - - @Override - public void close() { - super.close(); - if (this.rdfService != null) { - this.rdfService.close(); - } - } - - private class ReconnectingDatasetFactory implements DatasetWrapperFactory { - - private BasicDataSource _bds; - private StoreDesc _storeDesc; - - public ReconnectingDatasetFactory(BasicDataSource bds, - StoreDesc storeDesc) { - _bds = bds; - _storeDesc = storeDesc; - } - - public DatasetWrapper getDatasetWrapper() { - try { - Connection sqlConn = _bds.getConnection(); - SDBConnection conn = new SDBConnection(sqlConn) ; - Store store = SDBFactory.connectStore(conn, _storeDesc); - Dataset dataset = SDBFactory.connectDataset(store); - return new DatasetWrapper(dataset, conn); - } catch (SQLException sqe) { - throw new RuntimeException( - "Unable to connect to database", sqe); - } - } - - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/exception/IndividualNotFoundException.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/exception/IndividualNotFoundException.java new file mode 100644 index 0000000000..4928b57e9a --- /dev/null +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/dao/jena/exception/IndividualNotFoundException.java @@ -0,0 +1,10 @@ +package edu.cornell.mannlib.vitro.webapp.dao.jena.exception; + +/** + * A generic not found exception for an Individual. + */ +public class IndividualNotFoundException extends Exception { + + private static final long serialVersionUID = 1L; + +} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/ContextModelAccessImpl.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/ContextModelAccessImpl.java index 320c6c236a..273e046526 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/ContextModelAccessImpl.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/ContextModelAccessImpl.java @@ -36,10 +36,10 @@ import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; +import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetMode; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryDB; import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.ReasoningOption; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.WhichService; @@ -247,15 +247,17 @@ private Map populateWadfMap() { Map map = new EnumMap<>( ReasoningOption.class); - map.put(ASSERTIONS_ONLY, new WebappDaoFactorySDB(rdfService, - getOntModelSelector(ASSERTIONS_ONLY), config, - SDBDatasetMode.ASSERTIONS_ONLY)); - map.put(INFERENCES_ONLY, new WebappDaoFactorySDB(rdfService, - getOntModelSelector(INFERENCES_ONLY), config, - SDBDatasetMode.INFERENCES_ONLY)); - map.put(ASSERTIONS_AND_INFERENCES, new WebappDaoFactorySDB(rdfService, - getOntModelSelector(ASSERTIONS_AND_INFERENCES), config, - SDBDatasetMode.ASSERTIONS_AND_INFERENCES)); + + map.put(ASSERTIONS_ONLY, new WebappDaoFactoryDB(rdfService, + getOntModelSelector(ASSERTIONS_ONLY), config, + DatasetMode.ASSERTIONS_ONLY)); + map.put(INFERENCES_ONLY, new WebappDaoFactoryDB(rdfService, + getOntModelSelector(INFERENCES_ONLY), config, + DatasetMode.INFERENCES_ONLY)); + map.put(ASSERTIONS_AND_INFERENCES, new WebappDaoFactoryDB(rdfService, + getOntModelSelector(ASSERTIONS_AND_INFERENCES), config, + DatasetMode.ASSERTIONS_AND_INFERENCES)); + log.debug("WebappdaoFactoryMap: " + map); return Collections.unmodifiableMap(map); } diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/RequestModelAccessImpl.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/RequestModelAccessImpl.java index 63d70691cc..e12b0682ed 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/RequestModelAccessImpl.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/modelaccess/impl/RequestModelAccessImpl.java @@ -30,11 +30,12 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactoryConfig; import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.HideFromDisplayByPolicyFilter; +import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetMode; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelector; import edu.cornell.mannlib.vitro.webapp.dao.jena.OntModelSelectorImpl; import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactorySDB.SDBDatasetMode; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryDB; +import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; import edu.cornell.mannlib.vitro.webapp.filters.ModelSwitcher; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.DatasetOption; import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess.LanguageOption; @@ -317,25 +318,25 @@ private WebappDaoFactory createWebappDaoFactory(WebappDaoFactoryKey key) { } RDFService rdfService = getRDFService(key.rdfServiceKey()); - OntModelSelector ontModelSelector = getOntModelSelector(key - .ontModelSelectorKey()); + OntModelSelector ontModelSelector = getOntModelSelector(key.ontModelSelectorKey()); WebappDaoFactoryConfig config = source.getWebappDaoFactoryConfig(); - switch (key.getReasoningOption()) { - case ASSERTIONS_ONLY: - return new WebappDaoFactorySDB(rdfService, ontModelSelector, - config, SDBDatasetMode.ASSERTIONS_ONLY); - case INFERENCES_ONLY: - return new WebappDaoFactorySDB(rdfService, ontModelSelector, - config, SDBDatasetMode.INFERENCES_ONLY); - default: // ASSERTIONS_AND_INFERENCES - // TODO Do model switching and replace the WebappDaoFactory with - // a different version if requested by parameters - WebappDaoFactory unswitched = new WebappDaoFactorySDB(rdfService, - ontModelSelector, config); - return new ModelSwitcher().checkForModelSwitching(new VitroRequest( - req), unswitched); - } + switch (key.getReasoningOption()) { + case ASSERTIONS_ONLY: + return new WebappDaoFactoryDB(rdfService, ontModelSelector, config, + DatasetMode.ASSERTIONS_ONLY); + case INFERENCES_ONLY: + return new WebappDaoFactoryDB(rdfService, ontModelSelector, config, + DatasetMode.INFERENCES_ONLY); + default: + // ASSERTIONS_AND_INFERENCES + // TODO Do model switching and replace the WebappDaoFactory with + // a different version if requested by parameters + WebappDaoFactory unswitched = + new WebappDaoFactoryDB(rdfService, ontModelSelector, config); + + return new ModelSwitcher().checkForModelSwitching(new VitroRequest(req), unswitched); + } } private WebappDaoFactory addPolicyAwareness(WebappDaoFactory unaware) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java index 09a98a6479..61f8b51a14 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/RDFServiceJena.java @@ -38,7 +38,6 @@ import org.apache.jena.rdf.model.Resource; import org.apache.jena.rdf.model.Statement; import org.apache.jena.rdf.model.StmtIterator; -import org.apache.jena.sdb.SDB; import org.apache.jena.shared.Lock; import org.apache.jena.sparql.core.Quad; @@ -574,30 +573,26 @@ public void serializeGraph(String graphURI, OutputStream outputStream) } private void serialize(OutputStream outputStream, String query) throws RDFServiceException { - DatasetWrapper dw = getDatasetWrapper(); - try { - Dataset d = dw.getDataset(); - Query q = createQuery(query); - QueryExecution qe = createQueryExecution(query, q, d); - // These properties only help for SDB, but shouldn't hurt for TDB. - qe.getContext().set(SDB.jdbcFetchSize, Integer.MIN_VALUE); - qe.getContext().set(SDB.jdbcStream, true); - qe.getContext().set(SDB.streamGraphAPI, true); - try { - ResultSet resultSet = qe.execSelect(); - if (resultSet.getResultVars().contains("g")) { - Iterator quads = new ResultSetQuadsIterator(resultSet); - RDFDataMgr.writeQuads(outputStream, quads); - } else { - Iterator triples = new ResultSetTriplesIterator(resultSet); - RDFDataMgr.writeTriples(outputStream, triples); - } - } finally { - qe.close(); - } - } finally { - dw.close(); - } + DatasetWrapper dw = getDatasetWrapper(); + try { + Dataset d = dw.getDataset(); + Query q = createQuery(query); + QueryExecution qe = createQueryExecution(query, q, d); + try { + ResultSet resultSet = qe.execSelect(); + if (resultSet.getResultVars().contains("g")) { + Iterator quads = new ResultSetQuadsIterator(resultSet); + RDFDataMgr.writeQuads(outputStream, quads); + } else { + Iterator triples = new ResultSetTriplesIterator(resultSet); + RDFDataMgr.writeTriples(outputStream, triples); + } + } finally { + qe.close(); + } + } finally { + dw.close(); + } } /** diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java index 4b910b568c..a750ec93de 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/model/RDFServiceModel.java @@ -3,7 +3,6 @@ package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model; import java.io.ByteArrayInputStream; -import java.util.Iterator; import org.apache.commons.io.IOUtils; import org.apache.commons.logging.Log; @@ -58,8 +57,7 @@ protected DatasetWrapper getDatasetWrapper() { d.addNamedModel(this.modelName, model); } } - DatasetWrapper datasetWrapper = new DatasetWrapper(d); - return datasetWrapper; + return new DatasetWrapper(d); } @Override @@ -73,8 +71,6 @@ public boolean changeSetUpdate(ChangeSet changeSet) return false; } - //Dataset dataset = getDatasetWrapper().getDataset(); - try { for (Object o : changeSet.getPreChangeEvents()) { this.notifyListenersOfEvent(o); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceFactorySDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceFactorySDB.java deleted file mode 100644 index f69a615b4b..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceFactorySDB.java +++ /dev/null @@ -1,80 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb; - -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.jena.rdf.model.ModelChangedListener; -import org.apache.jena.sdb.StoreDesc; - -import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeListener; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; - -public class RDFServiceFactorySDB implements RDFServiceFactory { - - private final static Log log = LogFactory.getLog(RDFServiceFactorySDB.class); - - private DataSource ds; - private StoreDesc storeDesc; - private RDFService longTermRDFService; - - public RDFServiceFactorySDB(DataSource dataSource, StoreDesc storeDesc) { - this.ds = dataSource; - this.storeDesc = storeDesc; - this.longTermRDFService = new RDFServiceSDB(dataSource, storeDesc); - } - - @Override - public RDFService getRDFService() { - return this.longTermRDFService; - } - - @Override - public RDFService getShortTermRDFService() { - try { - RDFService rdfService = new RDFServiceSDB(ds.getConnection(), storeDesc); - for (ChangeListener cl : ((RDFServiceSDB) longTermRDFService) - .getRegisteredListeners() ) { - rdfService.registerListener(cl); - } - for (ModelChangedListener cl : ((RDFServiceSDB) longTermRDFService) - .getRegisteredJenaModelChangedListeners() ) { - rdfService.registerJenaModelChangedListener(cl); - } - return rdfService; - } catch (Exception e) { - log.error(e,e); - throw new RuntimeException(e); - } - } - - @Override - public void registerListener(ChangeListener changeListener) - throws RDFServiceException { - this.longTermRDFService.registerListener(changeListener); - } - - @Override - public void unregisterListener(ChangeListener changeListener) - throws RDFServiceException { - this.longTermRDFService.unregisterListener(changeListener); - } - - @Override - public void registerJenaModelChangedListener(ModelChangedListener changeListener) - throws RDFServiceException { - this.longTermRDFService.registerJenaModelChangedListener(changeListener); - } - - @Override - public void unregisterJenaModelChangedListener(ModelChangedListener changeListener) - throws RDFServiceException { - this.longTermRDFService.unregisterJenaModelChangedListener(changeListener); - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceSDB.java deleted file mode 100644 index d66efc94c6..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/rdfservice/impl/jena/sdb/RDFServiceSDB.java +++ /dev/null @@ -1,343 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb; - -import java.io.IOException; -import java.sql.Connection; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -import javax.sql.DataSource; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.jena.datatypes.RDFDatatype; -import org.apache.jena.datatypes.TypeMapper; -import org.apache.jena.datatypes.xsd.XSDDatatype; -import org.apache.jena.graph.Node; -import org.apache.jena.graph.NodeFactory; -import org.apache.jena.graph.Triple; -import org.apache.jena.query.Dataset; -import org.apache.jena.query.Query; -import org.apache.jena.query.QueryExecution; -import org.apache.jena.query.QueryExecutionFactory; -import org.apache.jena.rdf.model.Model; -import org.apache.jena.rdf.model.ModelFactory; -import org.apache.jena.rdf.model.RDFNode; -import org.apache.jena.sdb.SDBFactory; -import org.apache.jena.sdb.Store; -import org.apache.jena.sdb.StoreDesc; -import org.apache.jena.sdb.layout2.NodeLayout2; -import org.apache.jena.sdb.layout2.ValueType; -import org.apache.jena.sdb.sql.SDBConnection; - -import edu.cornell.mannlib.vitro.webapp.dao.jena.DatasetWrapper; -import edu.cornell.mannlib.vitro.webapp.dao.jena.StaticDatasetFactory; -import edu.cornell.mannlib.vitro.webapp.rdfservice.ChangeSet; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceException; -import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.RDFServiceJena; -import org.apache.jena.sdb.store.DatabaseType; -import org.apache.jena.sdb.store.LayoutType; - -public class RDFServiceSDB extends RDFServiceJena implements RDFService { - - private final static Log log = LogFactory.getLog(RDFServiceSDB.class); - - private DataSource ds; - private StoreDesc storeDesc; - private Connection conn; - private StaticDatasetFactory staticDatasetFactory; - - public RDFServiceSDB(DataSource dataSource, StoreDesc storeDesc) { - this.ds = dataSource; - this.storeDesc = storeDesc; - } - - public RDFServiceSDB(Connection conn, StoreDesc storeDesc) { - this.conn = conn; - this.storeDesc = storeDesc; - this.staticDatasetFactory = new StaticDatasetFactory(getDataset( - new SDBConnection(conn))); - } - - @Override - protected DatasetWrapper getDatasetWrapper() { - try { - if (staticDatasetFactory != null) { - return staticDatasetFactory.getDatasetWrapper(); - } - SDBConnection sdbConn = new SDBConnection(ds.getConnection()); - return new DatasetWrapper(getDataset(sdbConn), sdbConn); - } catch (SQLException sqle) { - log.error(sqle, sqle); - throw new RuntimeException(sqle); - } - } - - @Override - public boolean changeSetUpdate(ChangeSet changeSet) - throws RDFServiceException { - - if (changeSet.getPreconditionQuery() != null - && !isPreconditionSatisfied( - changeSet.getPreconditionQuery(), - changeSet.getPreconditionQueryType())) { - return false; - } - - SDBConnection sdbConn = getSDBConnection(); - Dataset dataset = getDataset(sdbConn); - try { - insureThatInputStreamsAreResettable(changeSet); - } catch (IOException e) { - throw new RuntimeException(e); - } - - try { - beginTransaction(sdbConn); - notifyListenersOfPreChangeEvents(changeSet); - applyChangeSetToModel(changeSet, dataset); - commitTransaction(sdbConn); - notifyListenersOfChanges(changeSet); - notifyListenersOfPostChangeEvents(changeSet); - return true; - } catch (Exception e) { - log.error(e, e); - abortTransaction(sdbConn); - throw new RDFServiceException(e); - } finally { - rebuildGraphURICache = true; - close(sdbConn); - } - } - - private SDBConnection getSDBConnection() throws RDFServiceException { - try { - Connection c = (conn != null) ? conn : ds.getConnection(); - return new SDBConnection(c); - } catch (SQLException sqle) { - log.error(sqle, sqle); - throw new RDFServiceException(sqle); - } - } - - private void close(SDBConnection sdbConn) { - if (!sdbConn.getSqlConnection().equals(conn)) { - sdbConn.close(); - } - } - - private Dataset getDataset(SDBConnection sdbConn) { - Store store = SDBFactory.connectStore(sdbConn, storeDesc); - store.getLoader().setUseThreading(false); - return SDBFactory.connectDataset(store); - } - - private void beginTransaction(SDBConnection sdbConn) { - if (sdbConn.getTransactionHandler().transactionsSupported()) { - sdbConn.getTransactionHandler().begin(); - } - } - - private void commitTransaction(SDBConnection sdbConn) { - if (sdbConn.getTransactionHandler().transactionsSupported()) { - sdbConn.getTransactionHandler().commit(); - } - } - - private void abortTransaction(SDBConnection sdbConn) { - if (sdbConn.getTransactionHandler().transactionsSupported()) { - sdbConn.getTransactionHandler().abort(); - } - } - - @Override - protected QueryExecution createQueryExecution(String queryString, Query q, Dataset d) { - return QueryExecutionFactory.create(q, d); - - // This used to execute against the default model if the query included an OPTIONAL - // However, in recent Jena this turns out to be much slower than executing against the dataset directly - } - - @Override - public long countTriples(RDFNode subject, RDFNode predicate, RDFNode object) throws RDFServiceException { - if (LayoutType.LayoutTripleNodesHash.equals(storeDesc.getLayout())) { - if (DatabaseType.MySQL.equals(storeDesc.getDbType()) || - DatabaseType.PostgreSQL.equals(storeDesc.getDbType())) { - SDBConnection sdbConn = getSDBConnection(); - try { - String whereClause = makeWhereClause(subject, predicate, object); - Statement stmt = sdbConn.getSqlConnection().createStatement(); - ResultSet rs = stmt.executeQuery("SELECT count(DISTINCT s,p,o) AS tcount FROM Quads" + (StringUtils.isEmpty(whereClause) ? "" : " WHERE " + whereClause)); - try { - if (rs.next()) { - return rs.getLong("tcount"); - } - } finally { - rs.close(); - } - } catch (SQLException sqle) { - throw new RDFServiceException("Unable to retrieve triples", sqle); - } finally { - close(sdbConn); - } - } - } else { - return super.countTriples(subject, predicate, object); - } - - return super.countTriples(subject, predicate, object); - } - - @Override - public Model getTriples(RDFNode subject, RDFNode predicate, RDFNode object, long limit, long offset) throws RDFServiceException { - if (LayoutType.LayoutTripleNodesHash.equals(storeDesc.getLayout())) { - if (DatabaseType.MySQL.equals(storeDesc.getDbType()) || - DatabaseType.PostgreSQL.equals(storeDesc.getDbType())) { - Model triples = ModelFactory.createDefaultModel(); - - SDBConnection sdbConn = getSDBConnection(); - try { - String whereClause = makeWhereClause(subject, predicate, object); - Statement stmt = sdbConn.getSqlConnection().createStatement(); - ResultSet rs = stmt.executeQuery("SELECT \n" + - "N1.lex AS s_lex,\n" + - "N1.lang AS s_lang,\n" + - "N1.datatype AS s_datatype,\n" + - "N1.type AS s_type,\n" + - "N2.lex AS p_lex,\n" + - "N2.lang AS p_lang,\n" + - "N2.datatype AS p_datatype,\n" + - "N2.type AS p_type,\n" + - "N3.lex AS o_lex,\n" + - "N3.lang AS o_lang,\n" + - "N3.datatype AS o_datatype,\n" + - "N3.type AS o_type\n" + - "FROM\n" + - "(SELECT DISTINCT s,p,o FROM Quads" + - (StringUtils.isEmpty(whereClause) ? "" : " WHERE " + whereClause) + - " ORDER BY s,p,o " + - (limit > 0 ? "LIMIT " + limit : "") + - (offset > 0 ? " OFFSET " + offset : "") + ") Q\n" + - "LEFT OUTER JOIN\n" + - "\tNodes AS N1\n" + - "ON ( Q.s = N1.hash )\n" + - "LEFT OUTER JOIN\n" + - "\tNodes AS N2\n" + - "ON ( Q.p = N2.hash )\n" + - "LEFT OUTER JOIN\n" + - "\tNodes AS N3\n" + - "ON ( Q.o = N3.hash )"); - - try { - while (rs.next()) { - Node subjectNode = makeNode( - rs.getString("s_lex"), - rs.getString("s_datatype"), - rs.getString("s_lang"), - ValueType.lookup(rs.getInt("s_type"))); - - Node predicateNode = makeNode( - rs.getString("p_lex"), - rs.getString("p_datatype"), - rs.getString("p_lang"), - ValueType.lookup(rs.getInt("p_type"))); - - Node objectNode = makeNode( - rs.getString("o_lex"), - rs.getString("o_datatype"), - rs.getString("o_lang"), - ValueType.lookup(rs.getInt("o_type"))); - - triples.add( - triples.asStatement(Triple.create(subjectNode, predicateNode, objectNode)) - ); - } - } finally { - rs.close(); - } - } catch (SQLException sqle) { - throw new RDFServiceException("Unable to retrieve triples", sqle); - } finally { - close(sdbConn); - } - - return triples; - } - } - - return super.getTriples(subject, predicate, object, limit, offset); - } - - @Override - public boolean preferPreciseOptionals() { - return true; - } - - @Override - public void close() { - if (conn != null) { - try { - conn.close(); - } catch (SQLException e) { - log.error(e,e); - } - } - } - - // Copied from Jena SQLBridge2 - private static Node makeNode(String lex, String datatype, String lang, ValueType vType) { - switch(vType) { - case BNODE: - return NodeFactory.createBlankNode(lex); - case URI: - return NodeFactory.createURI(lex); - case STRING: - return NodeFactory.createLiteral(lex, lang); - case XSDSTRING: - return NodeFactory.createLiteral(lex, XSDDatatype.XSDstring); - case INTEGER: - return NodeFactory.createLiteral(lex, XSDDatatype.XSDinteger); - case DOUBLE: - return NodeFactory.createLiteral(lex, XSDDatatype.XSDdouble); - case DATETIME: - return NodeFactory.createLiteral(lex, XSDDatatype.XSDdateTime); - case OTHER: - RDFDatatype dt = TypeMapper.getInstance().getSafeTypeByName(datatype); - return NodeFactory.createLiteral(lex, dt); - default: - log.warn("Unrecognized: (" + lex + ", " + lang + ", " + vType + ")"); - return NodeFactory.createLiteral("UNRECOGNIZED"); - } - } - - private String makeWhereClause(RDFNode subject, RDFNode predicate, RDFNode object) { - StringBuilder whereClause = new StringBuilder(); - if (subject != null) { - if (whereClause.length() > 0) { - whereClause.append(" AND "); - } - whereClause.append("s=").append(NodeLayout2.hash(subject.asNode())); - } - - if (predicate != null) { - if (whereClause.length() > 0) { - whereClause.append(" AND "); - } - whereClause.append("p=").append(NodeLayout2.hash(predicate.asNode())); - } - - if (object != null) { - if (whereClause.length() > 0) { - whereClause.append(" AND "); - } - whereClause.append("o=").append(NodeLayout2.hash(object.asNode())); - } - - return whereClause.length() > 0 ? whereClause.toString() : null; - } -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java index 5b669b7321..e9a3f20ab9 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/reasoner/SimpleReasoner.java @@ -139,7 +139,7 @@ public SimpleReasoner(OntModel tboxModel, OntModel aboxModel, Model inferenceMod this.inferenceModel = inferenceModel; this.fullModel = VitroModelFactory.createUnion(aboxModel, VitroModelFactory.createOntologyModel(inferenceModel)); - Dataset ds = DatasetFactory.createMem(); + Dataset ds = DatasetFactory.createMem(); ds.addNamedModel(ModelNames.ABOX_ASSERTIONS, aboxModel); ds.addNamedModel(ModelNames.ABOX_INFERENCES, inferenceModel); ds.addNamedModel(ModelNames.TBOX_ASSERTIONS, tboxModel); diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java index 80656403b9..da12f226c4 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/servlet/setup/FileGraphSetup.java @@ -147,7 +147,7 @@ private Set getFilegraphPaths(ServletContext ctx, String... strings) { /* * Reads the graphs stored as files in sub-directories of - * 1. updates the SDB store to reflect the current contents of the graph. + * 1. updates the data store to reflect the current contents of the graph. * 2. adds the graph as an in-memory submodel of the base in-memory graph * * Note: no connection needs to be maintained between the in-memory copy of the @@ -160,7 +160,7 @@ private boolean readGraphs(Set pathSet, RDFService rdfService, String type boolean modelChanged = false; // For each file graph in the target directory update or add that graph to - // the Jena SDB, and attach the graph as a submodel of the base model + // the Jena data store, and attach the graph as a submodel of the base model for ( Path p : pathSet ) { count++; // note this will count the empty files too @@ -251,7 +251,7 @@ public boolean updateGraphInDB(RDFService rdfService, Model fileModel, String ty * graphs (of the given type) in the file * system. * @param type (input) - abox or tbox. - * @param kbStore (output) - the SDB store for the application + * @param kbStore (output) - the data store for the application */ public void cleanupDB(Dataset dataset, Set uriSet, String type) { @@ -288,7 +288,7 @@ private Set pathsToURIs(Set paths, String type) { } /* - * Takes a path for a file graph and returns the corresponding SDB URI + * Takes a path for a file graph and returns the corresponding URI * for the graph. The correspondence is by defined convention. */ private String pathToURI(Path path, String type) { diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/ContentTripleSourceSDB.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/ContentTripleSourceSDB.java deleted file mode 100644 index 659b73b0a8..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/ContentTripleSourceSDB.java +++ /dev/null @@ -1,288 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb; - -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.BasicCombinedTripleSource.CONTENT_UNIONS; - -import java.sql.Driver; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Arrays; -import java.util.Enumeration; - -import javax.servlet.ServletContext; -import javax.sql.DataSource; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.jena.query.Dataset; -import org.apache.jena.rdf.model.ModelMaker; -import org.apache.jena.sdb.SDB; -import org.apache.jena.sdb.SDBFactory; -import org.apache.jena.sdb.Store; -import org.apache.jena.sdb.StoreDesc; -import org.apache.jena.sdb.sql.SDBConnection; -import org.apache.jena.sdb.store.DatabaseType; -import org.apache.jena.sdb.store.LayoutType; -import org.apache.jena.sdb.util.StoreUtils; -import org.apache.commons.dbcp2.BasicDataSource; - -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; -import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceDataset; -import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceModelMaker; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames; -import edu.cornell.mannlib.vitro.webapp.modelaccess.adapters.MemoryMappingModelMaker; -import edu.cornell.mannlib.vitro.webapp.modelaccess.adapters.ModelMakerWithPersistentEmptyModels; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.MaskingOntModelCache; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.ModelMakerOntModelCache; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.OntModelCache; -import edu.cornell.mannlib.vitro.webapp.modelaccess.ontmodels.UnionModelsOntModelsCache; -import edu.cornell.mannlib.vitro.webapp.modules.Application; -import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; -import edu.cornell.mannlib.vitro.webapp.modules.tripleSource.ContentTripleSource; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFServiceFactory; -import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb.RDFServiceFactorySDB; -import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.logging.LoggingRDFServiceFactory; -import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetupBase; -import edu.cornell.mannlib.vitro.webapp.utils.logging.ToString; - -/** - * Create the connection to the SDB triple-store. - * - * Do some smoke-tests on the parameters, create the connection pool, and create - * the RDFServiceFactory. - */ -public class ContentTripleSourceSDB extends ContentTripleSource { - private static final Log log = LogFactory - .getLog(ContentTripleSourceSDB.class); - - static final String PROPERTY_DB_URL = "VitroConnection.DataSource.url"; - static final String PROPERTY_DB_USERNAME = "VitroConnection.DataSource.username"; - static final String PROPERTY_DB_PASSWORD = "VitroConnection.DataSource.password"; - static final String PROPERTY_DB_DRIVER_CLASS_NAME = "VitroConnection.DataSource.driver"; - static final String PROPERTY_DB_TYPE = "VitroConnection.DataSource.dbtype"; - static final String PROPERTY_DB_MAX_ACTIVE = "VitroConnection.DataSource.pool.maxActive"; - static final String PROPERTY_DB_MAX_IDLE = "VitroConnection.DataSource.pool.maxIdle"; - static final String PROPERTY_DB_MAX_IDLE_TIME = "VitroConnection.DataSource.pool.maxIdleTime"; - static final String PROPERTY_DB_MAX_IDLE_TIME_EXCESS = "VitroConnection.DataSource.pool.maxIdleTimeExcess"; - static final String PROPERTY_DB_VALIDATION_QUERY = "VitroConnection.DataSource.validationQuery"; - static final String PROPERTY_DB_SDB_LAYOUT = "VitroConnection.DataSource.sdb.layout"; - - static final String DEFAULT_TYPE = "MySQL"; - static final String DEFAULT_DRIVER_CLASS = "com.mysql.jdbc.Driver"; - static final String DEFAULT_LAYOUT = "layout2/hash"; - static final String DEFAULT_VALIDATION_QUERY = "SELECT 1"; - - static final int DEFAULT_MAXACTIVE = 40; // ms - static final int MINIMUM_MAXACTIVE = 20; // ms - static final int DEFAULT_MAXIDLE = 10; // ms - - static final int DEFAULT_MAX_IDLE_TIME = 1800; // seconds - static final int DEFAULT_MAX_IDLE_TIME_EXCESS = 300; // seconds - - static final boolean DEFAULT_TESTONBORROW = true; - static final boolean DEFAULT_TESTONRETURN = true; - - private ServletContext ctx; - private BasicDataSource ds; - private RDFServiceFactory rdfServiceFactory; - private RDFService rdfService; - private Dataset dataset; - private ModelMaker modelMaker; - - @Override - public void startup(Application application, ComponentStartupStatus ss) { - try { - this.ctx = application.getServletContext(); - - configureSDBContext(); - - new SDBConnectionSmokeTests(ctx, ss).checkDatabaseConnection(); - - this.ds = new SDBDataSource(ctx).getDataSource(); - this.rdfServiceFactory = createRdfServiceFactory(); - this.rdfService = rdfServiceFactory.getRDFService(); - this.dataset = new RDFServiceDataset(this.rdfService); - this.modelMaker = createModelMaker(); - ss.info("Initialized the content data structures for SDB"); - } catch (SQLException e) { - throw new RuntimeException( - "Failed to set up the content data structures for SDB", e); - } - } - - private void configureSDBContext() { - SDB.getContext().set(SDB.unionDefaultGraph, true); - } - - private RDFServiceFactory createRdfServiceFactory() throws SQLException { - StoreDesc storeDesc = makeStoreDesc(); - Store store = connectStore(ds, storeDesc); - - if (!isSetUp(store)) { - JenaDataSourceSetupBase.thisIsFirstStartup(); - setupSDB(store); - } - - return new LoggingRDFServiceFactory(new RDFServiceFactorySDB(ds, - storeDesc)); - } - - /** - * Tests whether an SDB store has been formatted and populated for use. - */ - private boolean isSetUp(Store store) throws SQLException { - if (!(StoreUtils.isFormatted(store))) { - return false; - } - - // even if the store exists, it may be empty - try { - return (SDBFactory.connectNamedModel(store, - ModelNames.TBOX_ASSERTIONS)).size() > 0; - } catch (Exception e) { - return false; - } - } - - private StoreDesc makeStoreDesc() { - ConfigurationProperties props = ConfigurationProperties.getBean(ctx); - String layoutStr = props.getProperty(PROPERTY_DB_SDB_LAYOUT, - DEFAULT_LAYOUT); - String dbtypeStr = props.getProperty(PROPERTY_DB_TYPE, DEFAULT_TYPE); - return new StoreDesc(LayoutType.fetch(layoutStr), - DatabaseType.fetch(dbtypeStr)); - } - - private Store connectStore(DataSource bds, StoreDesc storeDesc) - throws SQLException { - SDBConnection conn = new SDBConnection(bds.getConnection()); - return SDBFactory.connectStore(conn, storeDesc); - } - - private void setupSDB(Store store) { - log.info("Initializing SDB store"); - store.getTableFormatter().create(); - store.getTableFormatter().truncate(); - } - - private ModelMaker createModelMaker() { - return addContentDecorators(new ModelMakerWithPersistentEmptyModels( - new MemoryMappingModelMaker(new RDFServiceModelMaker( - this.rdfService), SMALL_CONTENT_MODELS))); - } - - @Override - public RDFServiceFactory getRDFServiceFactory() { - return this.rdfServiceFactory; - } - - @Override - public RDFService getRDFService() { - return this.rdfService; - } - - @Override - public Dataset getDataset() { - return this.dataset; - } - - @Override - public ModelMaker getModelMaker() { - return this.modelMaker; - } - - /** - * Use models from the short-term RDFService, since there is less contention - * for the database connections that way. The exceptions are the - * memory-mapped models. By keeping them, we also keep their sub-models. - * - * Set up the Union models again also, so they will reference the short-term - * models. - */ - @Override - public OntModelCache getShortTermOntModels(RDFService shortTermRdfService, - OntModelCache longTermOntModelCache) { - ModelMakerOntModelCache shortCache = new ModelMakerOntModelCache( - addContentDecorators(new ModelMakerWithPersistentEmptyModels( - new RDFServiceModelMaker(shortTermRdfService)))); - - MaskingOntModelCache combinedCache = new MaskingOntModelCache( - shortCache, longTermOntModelCache, - Arrays.asList(MEMORY_MAPPED_CONTENT_MODELS)); - - return new UnionModelsOntModelsCache(combinedCache, CONTENT_UNIONS); - } - - @Override - public String toString() { - return "ContentTripleSourceSDB[" + ToString.hashHex(this) + "]"; - } - - @Override - public void shutdown(Application application) { - if (this.modelMaker != null) { - this.modelMaker.close(); - } - if (this.dataset != null) { - this.dataset.close(); - } - if (this.rdfService != null) { - this.rdfService.close(); - } - if (ds != null) { - String driverClassName = ds.getDriverClassName(); - try { - ds.close(); - } catch (SQLException e) { - }finally { - attemptToDeregisterJdbcDriver(driverClassName); - cleanupAbandonedConnectionThread(driverClassName); - } - } - } - - private void attemptToDeregisterJdbcDriver(String driverClassName) { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - - for (Enumeration drivers = DriverManager.getDrivers(); drivers - .hasMoreElements();) { - Driver driver = drivers.nextElement(); - if (driver.getClass().getClassLoader() == cl) { - // This driver was registered by the webapp's ClassLoader, so - // deregister it: - try { - DriverManager.deregisterDriver(driver); - } catch (SQLException ex) { - log.error("Error deregistering JDBC driver {" + driver - + "}", ex); - } - } else { - // driver was not registered by the webapp's ClassLoader and may - // be in use elsewhere - } - } - } - - /** - * The MySQL driver leaves a thread running after it is deregistered. - * Versions after 5.1.23 provide AbandonedConnectionCleanupThread.shutdown() - * to stop this thread. - * - * Using reflection to invoke this method means that we don't have a - * hard-coded dependency to MySQL. - */ - private void cleanupAbandonedConnectionThread(String driverClassName) { - if (!driverClassName.contains("mysql")) { - return; - } - try { - Class.forName("com.mysql.jdbc.AbandonedConnectionCleanupThread") - .getMethod("shutdown").invoke(null); - } catch (Exception e) { - log.info("Failed to shutdown MySQL connection cleanup thread: " + e); - } - } -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBConnectionSmokeTests.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBConnectionSmokeTests.java deleted file mode 100644 index d3b35576df..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBConnectionSmokeTests.java +++ /dev/null @@ -1,187 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb; - -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_DRIVER_CLASS; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_DRIVER_CLASS_NAME; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_PASSWORD; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_TYPE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_URL; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_USERNAME; - -import java.io.UnsupportedEncodingException; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Properties; - -import javax.servlet.ServletContext; - -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; -import edu.cornell.mannlib.vitro.webapp.modules.ComponentStartupStatus; - -/** - * Smoke tests for the database connection that SDB will use. - * - * Confirm that the URL, Username and Password have been specified for the - * Database connection. - * - * Confirm that we can load the database driver. - * - * Confirm that we can connect to the database using those properties. - * - * Try to confirm that the database connection is configured to use UTF-8 - * encoding. Don't know how well this works. - */ -public class SDBConnectionSmokeTests { - private final ConfigurationProperties props; - private final ComponentStartupStatus ss; - - public SDBConnectionSmokeTests(ServletContext ctx, ComponentStartupStatus ss) { - this.props = ConfigurationProperties.getBean(ctx); - this.ss = ss; - } - - public void checkDatabaseConnection() { - String url = props.getProperty(PROPERTY_DB_URL); - if (url == null || url.isEmpty()) { - ss.fatal("runtime.properties does not contain a value for '" - + PROPERTY_DB_URL + "'"); - return; - } - - // Get the full URL, with options. - url = SDBDataSource.getJdbcUrl(props); - - String username = props.getProperty(PROPERTY_DB_USERNAME); - if (username == null || username.isEmpty()) { - ss.fatal("runtime.properties does not contain a value for '" - + PROPERTY_DB_USERNAME + "'"); - return; - } - String password = props.getProperty(PROPERTY_DB_PASSWORD); - if (password == null || password.isEmpty()) { - ss.fatal("runtime.properties does not contain a value for '" - + PROPERTY_DB_PASSWORD + "'"); - return; - } - - String driverClassName = props - .getProperty(PROPERTY_DB_DRIVER_CLASS_NAME); - if (driverClassName == null) { - try { - Class.forName(DEFAULT_DRIVER_CLASS).newInstance(); - } catch (Exception e) { - ss.fatal("The default Database Driver failed to load. " - + "The driver class is '" + DEFAULT_DRIVER_CLASS + "'", - e); - return; - } - } else { - try { - Class.forName(driverClassName).newInstance(); - } catch (Exception e) { - ss.fatal("The Database Driver failed to load. " - + "The driver class was set by " - + PROPERTY_DB_DRIVER_CLASS_NAME + " to be '" - + driverClassName + "'", e); - return; - } - } - - Properties connectionProps = new Properties(); - connectionProps.put("user", username); - connectionProps.put("password", password); - - try (Connection conn = DriverManager - .getConnection(url, connectionProps)) { - // We have an SQL connection - see if we have any XSD Strings in the database - String skip = props.getProperty("skip.Jena3StringTest", "false"); - if (!Boolean.parseBoolean(skip)) { - try { - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT COUNT(1) AS total FROM Nodes WHERE datatype='http://www.w3.org/2001/XMLSchema#string'"); - if (rs != null && rs.next()) { - long total = rs.getLong("total"); - if (total > 0) { - ss.fatal("XSD Strings exist in Nodes table. Requires upgrade for Jena 3"); - } - } - } catch (SQLException e) { - // Ignore SQL Exception here, as it likely represents a triple store that's not initialised yet. - } - } - } catch (SQLException e) { - ss.fatal("Can't connect to the database: " + PROPERTY_DB_URL + "='" - + url + "', " + PROPERTY_DB_USERNAME + "='" + username - + "'", e); - return; - } - - String dbType = props.getProperty(PROPERTY_DB_TYPE, "MySQL"); - checkForPropertHandlingOfUnicodeCharacters(url, connectionProps, dbType); - } - - private void checkForPropertHandlingOfUnicodeCharacters(String url, - Properties connectionProps, String dbType) { - String testString = "ABC\u00CE\u0123"; - - try (Connection conn = DriverManager - .getConnection(url, connectionProps); - Statement stmt = conn.createStatement()) { - - // Create the temporary table. - stmt.executeUpdate("CREATE TEMPORARY TABLE smoke_test (contents varchar(100))"); - - // Write the test string, encoding in UTF-8 on the way in. - try (PreparedStatement pstmt = conn - .prepareStatement("INSERT INTO smoke_test values ( ? )")) { - pstmt.setBytes(1, testString.getBytes("UTF-8")); - pstmt.executeUpdate(); - } catch (UnsupportedEncodingException e1) { - e1.printStackTrace(); - } - - // Read it back as a String. Does the database decode it properly? - ResultSet rs = stmt.executeQuery("SELECT * FROM smoke_test"); - if (!rs.next()) { - throw new SQLException( - "Query of temporary table returned 0 rows."); - } - String storedValue = rs.getString(1); - if (!testString.equals(storedValue)) { - String message = "The database does not store Unicode " - + "characters correctly. The test inserted \"" - + showUnicode(testString) - + "\", but the query returned \"" - + showUnicode(storedValue) - + "\". Is the character encoding correctly " - + "set on the database?"; - if ("MySQL".equals(dbType)) { - // For MySQL, we know that this is a configuration problem. - ss.fatal(message); - } else { - // For other databases, it might not be. - ss.warning(message); - } - } - } catch (SQLException e) { - ss.fatal("Failed to check handling of Unicode characters", e); - } - } - - /** - * Display the hex codes for a String. - */ - private String showUnicode(String testString) { - StringBuilder u = new StringBuilder(); - for (char c : testString.toCharArray()) { - u.append(String.format("\\u%04x", c & 0x0000FFFF)); - } - return u.toString(); - } - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java deleted file mode 100644 index 9f80da08d7..0000000000 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/triplesource/impl/sdb/SDBDataSource.java +++ /dev/null @@ -1,178 +0,0 @@ -/* $This file is distributed under the terms of the license in LICENSE$ */ - -package edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb; - -import javax.servlet.ServletContext; - -import org.apache.commons.lang3.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import org.apache.commons.dbcp2.BasicDataSource; - -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; - -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_DRIVER_CLASS; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_MAXACTIVE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_MAXIDLE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_MAX_IDLE_TIME; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_MAX_IDLE_TIME_EXCESS; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_TESTONBORROW; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_TESTONRETURN; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_TYPE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.DEFAULT_VALIDATION_QUERY; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.MINIMUM_MAXACTIVE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_DRIVER_CLASS_NAME; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_MAX_ACTIVE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_MAX_IDLE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_MAX_IDLE_TIME; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_MAX_IDLE_TIME_EXCESS; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_PASSWORD; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_TYPE; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_URL; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_USERNAME; -import static edu.cornell.mannlib.vitro.webapp.triplesource.impl.sdb.ContentTripleSourceSDB.PROPERTY_DB_VALIDATION_QUERY; - -/** - * Create a DataSource on the SDB database. - */ -public class SDBDataSource { - private static final Log log = LogFactory.getLog(SDBDataSource.class); - - private final ConfigurationProperties configProps; - - - public SDBDataSource(ServletContext ctx) { - this.configProps = ConfigurationProperties.getBean(ctx); - } - - public BasicDataSource getDataSource() { - BasicDataSource cpds = new BasicDataSource(); - cpds.setDriverClassName(getDbDriverClassName()); - cpds.setUrl(getJdbcUrl(configProps)); - cpds.setUsername(configProps.getProperty(PROPERTY_DB_USERNAME)); - cpds.setPassword(configProps.getProperty(PROPERTY_DB_PASSWORD)); - cpds.setMaxTotal(getMaxActive()); - cpds.setMaxIdle(getMaxIdle()); - cpds.setMinEvictableIdleTimeMillis(getMaxIdleTime()); - cpds.setTestOnBorrow(DEFAULT_TESTONBORROW); - cpds.setTestOnReturn(DEFAULT_TESTONRETURN); - cpds.setValidationQuery(getValidationQuery()); - return cpds; -// try { -// cpds.setMaxIdleTimeExcessConnections(getMaxIdleTimeExcess()); -// cpds.setAcquireIncrement(5); -// cpds.setNumHelperThreads(6); -// } catch (PropertyVetoException pve) { -// throw new RuntimeException(pve); -// } - } - - private String getDbDriverClassName() { - return configProps.getProperty(PROPERTY_DB_DRIVER_CLASS_NAME, - DEFAULT_DRIVER_CLASS); - } - - private String getValidationQuery() { - return configProps.getProperty(PROPERTY_DB_VALIDATION_QUERY, - DEFAULT_VALIDATION_QUERY); - } - - private int getMaxActive() { - String maxActiveStr = configProps.getProperty(PROPERTY_DB_MAX_ACTIVE); - if (StringUtils.isEmpty(maxActiveStr)) { - return DEFAULT_MAXACTIVE; - } - - int maxActive = DEFAULT_MAXACTIVE; - try { - maxActive = Integer.parseInt(maxActiveStr); - } catch (NumberFormatException nfe) { - log.error("Unable to parse connection pool maxActive setting " - + maxActiveStr + " as an integer"); - return DEFAULT_MAXACTIVE; - } - - if (maxActive >= MINIMUM_MAXACTIVE) { - return maxActive; - } - - log.warn("Specified value for " + PROPERTY_DB_MAX_ACTIVE - + " is too low. Using minimum value of " + MINIMUM_MAXACTIVE); - return MINIMUM_MAXACTIVE; - } - - private int getMaxIdle() { - int maxIdleInt = Math.max(getMaxActive() / 4, DEFAULT_MAXIDLE); - return getPropertyAsInt(PROPERTY_DB_MAX_IDLE, maxIdleInt); - } - - private int getMaxIdleTime() { - return getPropertyAsInt(PROPERTY_DB_MAX_IDLE_TIME, DEFAULT_MAX_IDLE_TIME); - } - - private int getMaxIdleTimeExcess() { - return getPropertyAsInt(PROPERTY_DB_MAX_IDLE_TIME_EXCESS, DEFAULT_MAX_IDLE_TIME_EXCESS); - } - - private int getPropertyAsInt(String prop, int defaultValue) { - String propStr = configProps.getProperty(prop); - - if (StringUtils.isEmpty(propStr)) { - return defaultValue; - } - - try { - return Integer.parseInt(propStr); - } catch (NumberFormatException nfe) { - log.error("Unable to parse connection pool maxIdle setting " - + propStr + " as an integer"); - return defaultValue; - } - } - - /** - * Get the JDBC URL, perhaps with special MySQL options. - * - * This must be static and package-accessible so SDBConnectionSmokeTests can - * use the same options. - */ - static String getJdbcUrl(ConfigurationProperties props) { - String url = props.getProperty(PROPERTY_DB_URL); - - // Ensure that MySQL handles unicode properly, else all kinds of - // horrible nastiness ensues. Also, set some other handy options. - if (DEFAULT_TYPE.equals(getDbType(props))) { - if (!url.contains("?")) { - url += "?useUnicode=yes&characterEncoding=utf8&nullNamePatternMatchesAll=true&cachePrepStmts=true&useServerPrepStmts=true&serverTimezone=UTC"; - } else { - String urlLwr = url.toLowerCase(); - if (!urlLwr.contains("useunicode")) { - url += "&useUnicode=yes"; - } - if (!urlLwr.contains("characterencoding")) { - url += "&characterEncoding=utf8"; - } - if (!urlLwr.contains("nullnamepatternmatchesall")) { - url += "&nullNamePatternMatchesAll=true"; - } - if (!urlLwr.contains("cacheprepstmts")) { - url += "&cachePrepStmts=true"; - } - if (!urlLwr.contains("useserverprepstmts")) { - url += "&useServerPrepStmts=true"; - } - if (!urlLwr.contains("servertimezone")) { - url += "&serverTimezone=UTC"; - } - } - } - return url; - } - - private static String getDbType(ConfigurationProperties props) { - return props.getProperty(PROPERTY_DB_TYPE, DEFAULT_TYPE); - } - - -} diff --git a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/ListConfigUtils.java b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/ListConfigUtils.java index e4ed16e93d..124d1bdf0c 100644 --- a/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/ListConfigUtils.java +++ b/api/src/main/java/edu/cornell/mannlib/vitro/webapp/web/templatemodels/customlistview/ListConfigUtils.java @@ -4,8 +4,6 @@ import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; -import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.sdb.RDFServiceSDB; import org.apache.commons.lang3.StringUtils; public final class ListConfigUtils { diff --git a/home/src/main/resources/config/example.applicationSetup.n3 b/home/src/main/resources/config/example.applicationSetup.n3 index 0df7bdb6e4..d880a3590d 100644 --- a/home/src/main/resources/config/example.applicationSetup.n3 +++ b/home/src/main/resources/config/example.applicationSetup.n3 @@ -85,14 +85,10 @@ # The TDB-based implementation is the default option. It reads its parameters # from the runtime.properties file, for backward compatibility. # -# Other implementations are based on an SDB instance, a "standard" SPARQL -# endpoint, or a Virtuoso endpoint, with parameters as shown. +# Other implementations are based on a "standard" SPARQL endpoint or a +# Virtuoso endpoint, with parameters as shown. # -#:sdbContentTripleSource -# a vitroWebapp:triplesource.impl.sdb.ContentTripleSourceSDB , -# vitroWebapp:modules.tripleSource.ContentTripleSource . - :tdbContentTripleSource a vitroWebapp:triplesource.impl.tdb.ContentTripleSourceTDB , vitroWebapp:modules.tripleSource.ContentTripleSource ; diff --git a/home/src/main/resources/config/example.runtime.properties b/home/src/main/resources/config/example.runtime.properties index 989cf19e3f..229b33ab8f 100644 --- a/home/src/main/resources/config/example.runtime.properties +++ b/home/src/main/resources/config/example.runtime.properties @@ -48,8 +48,8 @@ email.smtpHost = email.replyTo = # -# NOTE: VitroConnection.DataSource.* properties are only used in conjuction with -# an SDB triple store. +# NOTE: VitroConnection.DataSource.* properties are only used by OpenSocial for +# SQL database interaction. # # The basic parameters for a database connection. Change the end of the # URL to reflect your database name (if it is not "vitrodb"). Change the username diff --git a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl index 0a8c972a8a..d8e22c81b1 100644 --- a/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/de_DE/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1402,14 +1402,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Starte SDB-Setup"@de-DE ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index af03833315..21f62d7496 100644 --- a/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1405,14 +1405,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Run SDB Setup"@en-CA ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl index 372588e1a9..2000871432 100644 --- a/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/en_US/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1405,14 +1405,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Run SDB Setup"@en-US ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl index df34897a47..0767119791 100644 --- a/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/es/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1401,14 +1401,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Ejecutar la instalación SDB"@es ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl index 233a2ee326..8cc78a4f83 100644 --- a/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/fr_CA/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1401,14 +1401,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Exécuter la configuration SDB"@fr-CA ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl index 0cab595f9f..c4a3156a39 100644 --- a/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/pt_BR/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1401,14 +1401,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Executar Configuração do SDB"@pt-BR ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl index 75fc2e81de..64af510a71 100644 --- a/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/ru_RU/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1401,14 +1401,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Запустить установку SDB"@ru-RU ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl index 506fb9669c..69fff58ec8 100644 --- a/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl +++ b/home/src/main/resources/rdf/i18n/sr_Latn_RS/interface-i18n/firsttime/vitro_UiLabel.ttl @@ -1401,14 +1401,6 @@ prop-data:fake_external_auth.Vitro prop:hasKey "fake_external_auth" ; prop:hasPackage "Vitro-languages" . -prop-data:run_sdb_setup.Vitro - rdf:type owl:NamedIndividual ; - rdf:type prop:PropertyKey ; - rdfs:label "Pokrenite SDB setup"@sr-Latn-RS ; - prop:hasApp "Vitro" ; - prop:hasKey "run_sdb_setup" ; - prop:hasPackage "Vitro-languages" . - prop-data:property_management.Vitro rdf:type owl:NamedIndividual ; rdf:type prop:PropertyKey ; diff --git a/installer/webapp/src/main/webResources/WEB-INF/classes/log4j.properties b/installer/webapp/src/main/webResources/WEB-INF/classes/log4j.properties index acfd46f59e..7e84c3df9f 100644 --- a/installer/webapp/src/main/webResources/WEB-INF/classes/log4j.properties +++ b/installer/webapp/src/main/webResources/WEB-INF/classes/log4j.properties @@ -42,8 +42,6 @@ log4j.logger.org.semanticweb.owlapi.rdf.rdfxml.parser=WARN log4j.logger.org.springframework=WARN # suppress odd warnings from libraries -log4j.logger.org.apache.jena.sdb.layout2.LoaderTuplesNodes=FATAL -log4j.logger.org.apache.jena.sdb.sql.SDBConnection=ERROR log4j.logger.org.openjena.riot=FATAL log4j.logger.org.apache.jena.riot=FATAL log4j.logger.org.directwebremoting=FATAL diff --git a/webapp/src/main/webapp/templates/freemarker/body/sdbSetup.ftl b/webapp/src/main/webapp/templates/freemarker/body/sdbSetup.ftl deleted file mode 100644 index 01f351850b..0000000000 --- a/webapp/src/main/webapp/templates/freemarker/body/sdbSetup.ftl +++ /dev/null @@ -1,12 +0,0 @@ -<#-- $This file is distributed under the terms of the license in LICENSE$ --> - -<#if link??> -
-

${sdbstatus}

- - -
- -<#if message??> -

${message}

-