NIHVIVO-2660 Filter out data property statements that don't have a literal object. Some associated refactoring.
This commit is contained in:
parent
a7a576340f
commit
010ffda62c
7 changed files with 166 additions and 132 deletions
|
@ -58,31 +58,6 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
|||
|
||||
protected static final Log log = LogFactory.getLog(DataPropertyDaoJena.class.getName());
|
||||
|
||||
/* This may be the intent behind JenaBaseDao.NONUSER_NAMESPACES, but that
|
||||
* value does not contain all of these namespaces.
|
||||
*/
|
||||
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
|
||||
// Don't need to exclude these, because they are not owl:DatatypeProperty
|
||||
//"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
||||
//"http://www.w3.org/2000/01/rdf-schema#",
|
||||
"http://www.w3.org/2002/07/owl#",
|
||||
"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#",
|
||||
"http://vitro.mannlib.cornell.edu/ns/vitro/public#"
|
||||
);
|
||||
|
||||
/*
|
||||
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
|
||||
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
|
||||
*/
|
||||
protected static final String PROPERTY_FILTERS;
|
||||
static {
|
||||
List<String> namespaceFilters = new ArrayList<String>();
|
||||
for (String namespace : EXCLUDED_NAMESPACES) {
|
||||
namespaceFilters.add("( afn:namespace(?property) != \"" + namespace + "\" )");
|
||||
}
|
||||
PROPERTY_FILTERS = StringUtils.join(namespaceFilters, " && ");
|
||||
}
|
||||
|
||||
private class DataPropertyRanker implements Comparator {
|
||||
public int compare (Object o1, Object o2) {
|
||||
DataProperty dp1 = (DataProperty) o1;
|
||||
|
@ -735,34 +710,63 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
|||
return rootProperties;
|
||||
}
|
||||
|
||||
/*
|
||||
* SPARQL-based methods for getting the individual's data properties.
|
||||
* Ideally this implementation should replace the existing way of getting
|
||||
* the data property list, but the consequences of this may be far-reaching,
|
||||
* so we are implementing a new method now and will merge the old approach
|
||||
* into the new one in a future release.
|
||||
*/
|
||||
|
||||
/* This may be the intent behind JenaBaseDao.NONUSER_NAMESPACES, but that
|
||||
* value does not contain all of these namespaces.
|
||||
*/
|
||||
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
|
||||
// Don't need to exclude these, because they are not owl:DatatypeProperty
|
||||
//"http://www.w3.org/1999/02/22-rdf-syntax-ns#",
|
||||
//"http://www.w3.org/2000/01/rdf-schema#",
|
||||
"http://www.w3.org/2002/07/owl#",
|
||||
"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#",
|
||||
"http://vitro.mannlib.cornell.edu/ns/vitro/public#"
|
||||
);
|
||||
|
||||
/*
|
||||
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
|
||||
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
|
||||
*/
|
||||
protected static final String PROPERTY_FILTERS;
|
||||
static {
|
||||
List<String> namespaceFilters = new ArrayList<String>();
|
||||
for (String namespace : EXCLUDED_NAMESPACES) {
|
||||
namespaceFilters.add("( afn:namespace(?property) != \"" + namespace + "\" )");
|
||||
}
|
||||
PROPERTY_FILTERS = StringUtils.join(namespaceFilters, " && ");
|
||||
}
|
||||
|
||||
protected static final String DATA_PROPERTY_QUERY_STRING =
|
||||
PREFIXES + "\n" +
|
||||
"SELECT DISTINCT ?property WHERE { \n" +
|
||||
" ?subject ?property ?object . \n" +
|
||||
" ?property a owl:DatatypeProperty . \n" +
|
||||
" FILTER ( \n" +
|
||||
" isLiteral(?object) && \n" +
|
||||
PROPERTY_FILTERS + "\n" +
|
||||
" ) \n" +
|
||||
"}";
|
||||
|
||||
@Override
|
||||
public List<DataProperty> getDataPropertyList(Individual subject) {
|
||||
return getDataPropertyList(subject.getURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
/*
|
||||
* SPARQL-based method for getting the individual's data properties.
|
||||
* Ideally this implementation should replace the existing way of getting
|
||||
* the data property list, but the consequences of this may be far-reaching,
|
||||
* so we are implementing a new method now and will merge the old approach
|
||||
* into the new one in a future release.
|
||||
*/
|
||||
public List<DataProperty> getDataPropertyList(String subjectUri) {
|
||||
|
||||
// Due to a Jena bug, prebinding on ?subject combined with the isLiteral()
|
||||
// filter causes the query to fail. Using string concatenation to insert the
|
||||
// subject uri instead.
|
||||
String queryString =
|
||||
prefixes + "\n" +
|
||||
"SELECT DISTINCT ?property WHERE { \n" +
|
||||
" <" + subjectUri + "> ?property ?object . \n" +
|
||||
" ?property a owl:DatatypeProperty . \n" +
|
||||
" FILTER ( \n" +
|
||||
" isLiteral(?object) && \n" +
|
||||
PROPERTY_FILTERS + "\n" +
|
||||
" ) \n" +
|
||||
"}";
|
||||
// filter causes the query to fail. Insert the subjectUri manually instead.
|
||||
// QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||
// initialBindings.add("subject", ResourceFactory.createResource(subjectUri));
|
||||
String queryString = subUriForQueryVar(DATA_PROPERTY_QUERY_STRING, "subject", subjectUri);
|
||||
|
||||
Query query = null;
|
||||
try {
|
||||
|
|
|
@ -4,10 +4,11 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.hp.hpl.jena.datatypes.TypeMapper;
|
||||
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntResource;
|
||||
import com.hp.hpl.jena.query.Dataset;
|
||||
|
@ -16,7 +17,6 @@ import com.hp.hpl.jena.query.QueryExecution;
|
|||
import com.hp.hpl.jena.query.QueryExecutionFactory;
|
||||
import com.hp.hpl.jena.query.QueryFactory;
|
||||
import com.hp.hpl.jena.query.QuerySolution;
|
||||
import com.hp.hpl.jena.query.QuerySolutionMap;
|
||||
import com.hp.hpl.jena.query.ResultSet;
|
||||
import com.hp.hpl.jena.rdf.model.AnonId;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
|
@ -42,21 +42,6 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro
|
|||
|
||||
private DatasetWrapperFactory dwf;
|
||||
|
||||
protected static final String DATA_PROPERTY_VALUE_QUERY_STRING =
|
||||
"SELECT ?value WHERE { \n" +
|
||||
" ?subject ?property ?value . \n" +
|
||||
"}";
|
||||
|
||||
static protected Query dataPropertyValueQuery;
|
||||
static {
|
||||
try {
|
||||
dataPropertyValueQuery = QueryFactory.create(DATA_PROPERTY_VALUE_QUERY_STRING);
|
||||
} catch(Throwable th){
|
||||
log.error("could not create SPARQL query for DATA_PROPERTY_VALUE_QUERY_STRING " + th.getMessage());
|
||||
log.error(DATA_PROPERTY_VALUE_QUERY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
public DataPropertyStatementDaoJena(DatasetWrapperFactory dwf,
|
||||
WebappDaoFactoryJena wadf) {
|
||||
super(wadf);
|
||||
|
@ -311,6 +296,23 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro
|
|||
* SPARQL-based methods for getting the individual's values for a single data property.
|
||||
*/
|
||||
|
||||
protected static final String DATA_PROPERTY_VALUE_QUERY_STRING =
|
||||
"SELECT ?value WHERE { \n" +
|
||||
" ?subject ?property ?value . \n" +
|
||||
// ignore statements with uri values
|
||||
" FILTER ( isLiteral(?value) ) " +
|
||||
"} ";
|
||||
|
||||
protected static Query dataPropertyValueQuery;
|
||||
static {
|
||||
try {
|
||||
dataPropertyValueQuery = QueryFactory.create(DATA_PROPERTY_VALUE_QUERY_STRING);
|
||||
} catch(Throwable th) {
|
||||
log.error("could not create SPARQL query for DATA_PROPERTY_VALUE_QUERY_STRING " + th.getMessage());
|
||||
log.error(DATA_PROPERTY_VALUE_QUERY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Literal> getDataPropertyValuesForIndividualByProperty(Individual subject, DataProperty property) {
|
||||
return getDataPropertyValuesForIndividualByProperty(subject.getURI(), property.getURI());
|
||||
|
@ -320,10 +322,16 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro
|
|||
public List<Literal> getDataPropertyValuesForIndividualByProperty(String subjectUri, String propertyUri) {
|
||||
log.debug("Data property value query string:\n" + DATA_PROPERTY_VALUE_QUERY_STRING);
|
||||
log.debug("Data property value:\n" + dataPropertyValueQuery);
|
||||
|
||||
QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||
initialBindings.add("subject", ResourceFactory.createResource(subjectUri));
|
||||
initialBindings.add("property", ResourceFactory.createResource(propertyUri));
|
||||
|
||||
// Due to a Jena bug, prebinding on ?subject combined with the isLiteral()
|
||||
// filter causes the query to fail. Insert the subjectUri manually instead.
|
||||
// QuerySolutionMap initialBindings = new QuerySolutionMap();
|
||||
// initialBindings.add("subject", ResourceFactory.createResource(subjectUri));
|
||||
// initialBindings.add("property", ResourceFactory.createResource(propertyUri));
|
||||
Map<String, String> bindings = new HashMap<String, String>();
|
||||
bindings.put("subject", subjectUri);
|
||||
bindings.put("property", propertyUri);
|
||||
String queryString = subUrisForQueryVars(DATA_PROPERTY_VALUE_QUERY_STRING, bindings);
|
||||
|
||||
// Run the SPARQL query to get the properties
|
||||
List<Literal> values = new ArrayList<Literal>();
|
||||
|
@ -332,7 +340,7 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro
|
|||
dataset.getLock().enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
QueryExecution qexec = QueryExecutionFactory.create(
|
||||
dataPropertyValueQuery, dataset, initialBindings);
|
||||
queryString, dataset);
|
||||
ResultSet results = qexec.execSelect();
|
||||
|
||||
while (results.hasNext()) {
|
||||
|
|
|
@ -1071,5 +1071,21 @@ public class JenaBaseDao extends JenaBaseDaoCon {
|
|||
return temp;
|
||||
}
|
||||
|
||||
/** Manually replace query variables with uris when prebinding causes the query to fail, probably
|
||||
* due to a Jena bug.
|
||||
*/
|
||||
protected static String subUrisForQueryVars(String queryString, Map<String, String> varsToUris) {
|
||||
|
||||
for (String var : varsToUris.keySet()) {
|
||||
queryString = subUriForQueryVar(queryString, var, varsToUris.get(var));
|
||||
}
|
||||
return queryString;
|
||||
}
|
||||
|
||||
/** Manually replace a query variable with a uri when prebinding causes the query to fail, probably
|
||||
* due to a Jena bug.
|
||||
*/
|
||||
protected static String subUriForQueryVar(String queryString, String varName, String uri) {
|
||||
return queryString.replaceAll("\\?" + varName + "\\b", "<" + uri + ">");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,44 +52,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
|||
public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectPropertyDao {
|
||||
private static final Log log = LogFactory.getLog(ObjectPropertyDaoJena.class.getName());
|
||||
|
||||
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
|
||||
"http://www.w3.org/2002/07/owl#"
|
||||
);
|
||||
/*
|
||||
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
|
||||
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
|
||||
*/
|
||||
protected static final String PROPERTY_FILTERS;
|
||||
static {
|
||||
List<String> namespaceFilters = new ArrayList<String>();
|
||||
for (String namespace : EXCLUDED_NAMESPACES) {
|
||||
namespaceFilters.add("( afn:namespace(?property) != \"" + namespace + "\" )");
|
||||
}
|
||||
// A hack to include the vitro:primaryLink and vitro:additionalLink properties in the list
|
||||
namespaceFilters.add("( ?property = vitro:primaryLink ||" +
|
||||
"?property = vitro:additionalLink ||" +
|
||||
"afn:namespace(?property) != \"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#\" )");
|
||||
PROPERTY_FILTERS = StringUtils.join(namespaceFilters, " && ");
|
||||
}
|
||||
|
||||
protected static final String LIST_VIEW_CONFIG_FILE_QUERY_STRING =
|
||||
"PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#>" +
|
||||
"SELECT ?property ?filename WHERE { \n" +
|
||||
" ?property display:listViewConfigFile ?filename . \n" +
|
||||
"}";
|
||||
|
||||
protected static Query listViewConfigFileQuery = null;
|
||||
static {
|
||||
try {
|
||||
listViewConfigFileQuery = QueryFactory.create(LIST_VIEW_CONFIG_FILE_QUERY_STRING);
|
||||
} catch(Throwable th){
|
||||
log.error("could not create SPARQL query for LIST_VIEW_CONFIG_FILE_QUERY_STRING " + th.getMessage());
|
||||
log.error(LIST_VIEW_CONFIG_FILE_QUERY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
Map<ObjectProperty, String> customListViewConfigFileMap = null;
|
||||
|
||||
public ObjectPropertyDaoJena(DatasetWrapperFactory dwf,
|
||||
WebappDaoFactoryJena wadf) {
|
||||
super(dwf, wadf);
|
||||
|
@ -847,34 +809,57 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
|
|||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* SPARQL-based methods for getting the individual's object properties.
|
||||
* Ideally this implementation should replace the existing way of getting
|
||||
* the object property list, but the consequences of this may be far-reaching,
|
||||
* so we are implementing a new method now and will merge the old approach
|
||||
* into the new one in a future release.
|
||||
*/
|
||||
|
||||
protected static final List<String> EXCLUDED_NAMESPACES = Arrays.asList(
|
||||
"http://www.w3.org/2002/07/owl#"
|
||||
);
|
||||
/*
|
||||
* This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces.
|
||||
* It will be implemented in a better way in v1.3 (Editing and Display Configuration).
|
||||
*/
|
||||
protected static final String PROPERTY_FILTERS;
|
||||
static {
|
||||
List<String> namespaceFilters = new ArrayList<String>();
|
||||
for (String namespace : EXCLUDED_NAMESPACES) {
|
||||
namespaceFilters.add("( afn:namespace(?property) != \"" + namespace + "\" )");
|
||||
}
|
||||
// A hack to include the vitro:primaryLink and vitro:additionalLink properties in the list
|
||||
namespaceFilters.add("( ?property = vitro:primaryLink ||" +
|
||||
"?property = vitro:additionalLink ||" +
|
||||
"afn:namespace(?property) != \"http://vitro.mannlib.cornell.edu/ns/vitro/0.7#\" )");
|
||||
PROPERTY_FILTERS = StringUtils.join(namespaceFilters, " && ");
|
||||
}
|
||||
|
||||
protected static final String OBJECT_PROPERTY_QUERY_STRING =
|
||||
PREFIXES + "\n" +
|
||||
"SELECT DISTINCT ?property WHERE { \n" +
|
||||
" ?subject ?property ?object . \n" +
|
||||
" ?property a owl:ObjectProperty . \n" +
|
||||
" FILTER ( \n" +
|
||||
" isURI(?object) && \n" +
|
||||
PROPERTY_FILTERS + "\n" +
|
||||
" ) \n" +
|
||||
"}";
|
||||
|
||||
@Override
|
||||
public List<ObjectProperty> getObjectPropertyList(Individual subject) {
|
||||
return getObjectPropertyList(subject.getURI());
|
||||
}
|
||||
|
||||
@Override
|
||||
/*
|
||||
* SPARQL-based method for getting the individual's object properties.
|
||||
* Ideally this implementation should replace the existing way of getting
|
||||
* the object property list, but the consequences of this may be far-reaching,
|
||||
* so we are implementing a new method now and will merge the old approach
|
||||
* into the new one in a future release.
|
||||
*/
|
||||
public List<ObjectProperty> getObjectPropertyList(String subjectUri) {
|
||||
|
||||
// Due to a Jena bug, prebinding on ?subject combined with the isURI()
|
||||
// filter causes the query to fail. Using string concatenation to insert the
|
||||
// subject uri instead.
|
||||
String queryString =
|
||||
prefixes + "\n" +
|
||||
"SELECT DISTINCT ?property WHERE { \n" +
|
||||
" <" + subjectUri + "> ?property ?object . \n" +
|
||||
" ?property a owl:ObjectProperty . \n" +
|
||||
" FILTER ( \n" +
|
||||
" isURI(?object) && \n" +
|
||||
PROPERTY_FILTERS + "\n" +
|
||||
" ) \n" +
|
||||
"}";
|
||||
String queryString = subUriForQueryVar(OBJECT_PROPERTY_QUERY_STRING, "subject", subjectUri);
|
||||
|
||||
Query query = null;
|
||||
try {
|
||||
|
@ -900,6 +885,24 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp
|
|||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
protected static final String LIST_VIEW_CONFIG_FILE_QUERY_STRING =
|
||||
"PREFIX display: <http://vitro.mannlib.cornell.edu/ontologies/display/1.1#>" +
|
||||
"SELECT ?property ?filename WHERE { \n" +
|
||||
" ?property display:listViewConfigFile ?filename . \n" +
|
||||
"}";
|
||||
|
||||
protected static Query listViewConfigFileQuery = null;
|
||||
static {
|
||||
try {
|
||||
listViewConfigFileQuery = QueryFactory.create(LIST_VIEW_CONFIG_FILE_QUERY_STRING);
|
||||
} catch(Throwable th){
|
||||
log.error("could not create SPARQL query for LIST_VIEW_CONFIG_FILE_QUERY_STRING " + th.getMessage());
|
||||
log.error(LIST_VIEW_CONFIG_FILE_QUERY_STRING);
|
||||
}
|
||||
}
|
||||
|
||||
Map<ObjectProperty, String> customListViewConfigFileMap = null;
|
||||
|
||||
@Override
|
||||
public String getCustomListViewConfigFileName(ObjectProperty op) {
|
||||
|
|
|
@ -251,6 +251,14 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SPARQL-based method for getting values related to a single object property.
|
||||
* We cannot return a List<ObjectPropertyStatement> here, the way the corresponding method of
|
||||
* DataPropertyStatementDaoJena returns a List<DataPropertyStatement>. We need to accomodate
|
||||
* custom queries that could request any data in addition to just the object of the statement.
|
||||
* However, we do need to get the object of the statement so that we have it to create editing links.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public List<Map<String, String>> getObjectPropertyStatementsForIndividualByProperty(
|
||||
String subjectUri,
|
||||
|
@ -263,13 +271,6 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
}
|
||||
|
||||
@Override
|
||||
/*
|
||||
* SPARQL-based method for getting values related to a single object property.
|
||||
* We cannot return a List<ObjectPropertyStatement> here, the way the corresponding method of
|
||||
* DataPropertyStatementDaoJena returns a List<DataPropertyStatement>. We need to accomodate
|
||||
* custom queries that could request any data in addition to just the object of the statement.
|
||||
* However, we do need to get the object of the statement so that we have it to create editing links.
|
||||
*/
|
||||
public List<Map<String, String>> getObjectPropertyStatementsForIndividualByProperty(
|
||||
String subjectUri,
|
||||
String propertyUri,
|
||||
|
@ -315,7 +316,7 @@ public class ObjectPropertyStatementDaoJena extends JenaBaseDao implements Objec
|
|||
while (results.hasNext()) {
|
||||
QuerySolution soln = results.nextSolution();
|
||||
RDFNode node = soln.get(objectKey);
|
||||
if (node.isResource()) {
|
||||
if (node.isURIResource()) {
|
||||
list.add(QueryUtils.querySolutionToStringValueMap(soln));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,12 +53,14 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao {
|
|||
put("vitroPublic", VitroVocabulary.VITRO_PUBLIC);
|
||||
}};
|
||||
|
||||
protected static String prefixes = "";
|
||||
protected static final String PREFIXES;
|
||||
static {
|
||||
String prefixes = "";
|
||||
for (String key : NAMESPACES.keySet()) {
|
||||
prefixes += "PREFIX " + key + ": <" + NAMESPACES.get(key) + ">\n";
|
||||
}
|
||||
log.debug("Query prefixes: " + prefixes);
|
||||
PREFIXES = prefixes;
|
||||
log.debug("Query prefixes: " + PREFIXES);
|
||||
}
|
||||
|
||||
protected DatasetWrapperFactory dwf;
|
||||
|
|
|
@ -109,7 +109,7 @@ public class GroupedPropertyList extends BaseTemplateModel {
|
|||
|
||||
}
|
||||
|
||||
// It's possible that a collated object property retrieved in the call to getPopulatedObjectPropertyList()
|
||||
// It's possible that an object property retrieved in the call to getPopulatedObjectPropertyList()
|
||||
// is now empty of statements, because if not editing, some statements without a linked individual
|
||||
// are not retrieved by the query. (See <linked-individual-required> elements in queries.)
|
||||
// Remove these properties, and also remove any groups with no remaining properties.
|
||||
|
|
Loading…
Add table
Reference in a new issue