diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java index b1d6a6962..a21e386be 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java @@ -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 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 namespaceFilters = new ArrayList(); - 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 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 namespaceFilters = new ArrayList(); + 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 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 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 { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java index b71d9f21d..bb318c002 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyStatementDaoJena.java @@ -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 getDataPropertyValuesForIndividualByProperty(Individual subject, DataProperty property) { return getDataPropertyValuesForIndividualByProperty(subject.getURI(), property.getURI()); @@ -320,10 +322,16 @@ public class DataPropertyStatementDaoJena extends JenaBaseDao implements DataPro public List 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 bindings = new HashMap(); + 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 values = new ArrayList(); @@ -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()) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java index fbff51849..750283a82 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/JenaBaseDao.java @@ -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 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 + ">"); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java index 72b721915..762be2cc2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java @@ -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 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 namespaceFilters = new ArrayList(); - 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: " + - "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 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 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 namespaceFilters = new ArrayList(); + 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 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 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: " + + "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 customListViewConfigFileMap = null; @Override public String getCustomListViewConfigFileName(ObjectProperty op) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java index d59a3e1e4..5436edd1b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyStatementDaoJena.java @@ -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 here, the way the corresponding method of + * DataPropertyStatementDaoJena returns a List. 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> 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 here, the way the corresponding method of - * DataPropertyStatementDaoJena returns a List. 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> 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)); } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java index 3bf6b20e7..07c16ae21 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java @@ -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; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java index b3328bcac..e7658096c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java @@ -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 elements in queries.) // Remove these properties, and also remove any groups with no remaining properties.