From 02ac3944e0373354560ff2cae6068bcb17c40cda Mon Sep 17 00:00:00 2001 From: Jim Blake Date: Thu, 30 Oct 2014 15:52:23 -0400 Subject: [PATCH] VIVO-774 show list of faux properties on the Property Editing page. --- .../vitro/webapp/beans/FauxProperty.java | 73 ++++ .../edit/PropertyEditController.java | 19 +- .../vitro/webapp/dao/FauxPropertyDao.java | 37 +- .../filtering/FauxPropertyDaoFiltering.java | 251 +++---------- .../webapp/dao/jena/FauxPropertyDaoJena.java | 332 +++++++++++++++++- .../webapp/dao/jena/WebappDaoFactoryJena.java | 6 +- .../vitro/webapp/utils/SparqlQueryRunner.java | 10 + .../templates/edit/specific/props_edit.jsp | 37 ++ 8 files changed, 530 insertions(+), 235 deletions(-) create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/beans/FauxProperty.java diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/FauxProperty.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/FauxProperty.java new file mode 100644 index 000000000..08a440c47 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/FauxProperty.java @@ -0,0 +1,73 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.beans; + +import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; + +import java.util.Objects; + +/** + * Represents a specialization on an ObjectProperty, only meaningful for + * display. + * + * Must have a baseURI and a rangeURI. Other fields are optional. + */ +public class FauxProperty extends BaseResourceBean implements ResourceBean { + private final String rangeURI; + private final String domainURI; + + private String rangeLabel; + private String domainLabel; + + /** + * Arguments are in this order to mimic the relationship: subject ==> + * property ==> object + * + * @param domainURI + * URI of the subject class. May be null. + * @param baseURI + * URI of the property. May not be null. + * @param rangeUri + * URI of the object class. May not be null. + */ + public FauxProperty(String domainURI, String baseURI, String rangeURI) { + super(Objects.requireNonNull(baseURI, "baseURI may not be null")); + this.rangeURI = Objects.requireNonNull(rangeURI, + "rangeURI may not be null"); + this.domainURI = domainURI; + } + + public String getRangeURI() { + return rangeURI; + } + + public void setRangeLabel(String rangeLabel) { + this.rangeLabel = rangeLabel; + } + + public String getRangeLabel() { + return (rangeLabel == null) ? localName(rangeURI) : rangeLabel; + } + + public String getDomainURI() { + return domainURI; + } + + public void setDomainLabel(String domainLabel) { + this.domainLabel = domainLabel; + } + + public String getDomainLabel() { + return (domainLabel == null) ? (domainURI == null ? "null" + : localName(domainURI)) : domainLabel; + } + + private String localName(String uriString) { + try { + return createResource(uriString).getLocalName(); + } catch (Exception e) { + return uriString; + } + } + +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyEditController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyEditController.java index 8741f65d1..460bbd229 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyEditController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/edit/PropertyEditController.java @@ -17,8 +17,10 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.EditProcessObject; import edu.cornell.mannlib.vedit.beans.FormObject; +import edu.cornell.mannlib.vedit.beans.Option; import edu.cornell.mannlib.vedit.controller.BaseEditController; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; +import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.Ontology; import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup; @@ -33,7 +35,8 @@ public class PropertyEditController extends BaseEditController { private static final Log log = LogFactory.getLog(PropertyEditController.class.getName()); - public void doPost (HttpServletRequest request, HttpServletResponse response) { + @Override + public void doPost (HttpServletRequest request, HttpServletResponse response) { if (!isAuthorizedToDisplayPage(request, response, SimplePermission.EDIT_ONTOLOGY.ACTION)) { return; @@ -189,11 +192,9 @@ public class PropertyEditController extends BaseEditController { request.setAttribute("suppressquery","true"); - boolean FORCE_NEW = true; - EditProcessObject epo = super.createEpo(request, FORCE_NEW); FormObject foo = new FormObject(); - HashMap OptionMap = new HashMap(); + HashMap> OptionMap = new HashMap<>(); foo.setOptionLists(OptionMap); epo.setFormObject(foo); @@ -210,11 +211,18 @@ public class PropertyEditController extends BaseEditController { sortForPickList(subProps, vreq); request.setAttribute("subproperties", subProps); + // equivalent properties and faux properties + List eqProps = getObjectPropertiesForURIList( opDao.getEquivalentPropertyURIs(p.getURI()), opDao); sortForPickList(eqProps, vreq); request.setAttribute("equivalentProperties", eqProps); + List fauxProps = vreq.getUnfilteredAssertionsWebappDaoFactory().getFauxPropertyDao(). + getFauxPropertiesForBaseUri(p.getURI()); + sortForPickList(fauxProps, vreq); + request.setAttribute("fauxproperties", fauxProps); + RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP); request.setAttribute("epoKey",epo.getKey()); request.setAttribute("propertyWebapp", p); @@ -232,7 +240,8 @@ public class PropertyEditController extends BaseEditController { } - public void doGet (HttpServletRequest request, HttpServletResponse response) { + @Override + public void doGet (HttpServletRequest request, HttpServletResponse response) { doPost(request,response); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/FauxPropertyDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/FauxPropertyDao.java index 68b1a0afd..8edfefa9b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/FauxPropertyDao.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/FauxPropertyDao.java @@ -2,9 +2,44 @@ package edu.cornell.mannlib.vitro.webapp.dao; +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; + /** - * TODO + * Utility methods for fetching, storing and manipulating FauxProperty objects. */ public interface FauxPropertyDao { + /** + * Get all of the FauxProperties that are based on this URI. + * + * @return May return an empty list. Never returns null. + */ + List getFauxPropertiesForBaseUri(String uri); + + /** + * If the display model contains a ConfigContext with this URI, get the + * FauxProperty that it describes. + * + * @return May return null. + */ + FauxProperty getFauxPropertyFromConfigContextUri(String contextUri); + + /** + * If the display model contains a ConfigContext based on these URIs, get + * the FauxProperty that it describes. May return null. + * + * @param domainUri + * May be null, but then this will only match a ConfigContext + * that has no qualifiedByDomain property. + * @param baseUri + * Object of configContextFor property. May not be null. + * @param rangeUri + * Object of qualifiedBy property. May not be null. + * @return May return null. + */ + FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, + String rangeUri); + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java index ec9c9299b..8d34d7d2b 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/FauxPropertyDaoFiltering.java @@ -2,217 +2,50 @@ package edu.cornell.mannlib.vitro.webapp.dao.filtering; +import java.util.List; + +import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters; -class FauxPropertyDaoFiltering extends BaseFiltering implements FauxPropertyDao{ - final FauxPropertyDao innerFauxPropertyDao; - final VitroFilters filters; +/** + * TODO Find out if this is really necessary. If so, what is filtered? + */ +public class FauxPropertyDaoFiltering extends BaseFiltering implements FauxPropertyDao { + final FauxPropertyDao innerFauxPropertyDao; + final VitroFilters filters; + + public FauxPropertyDaoFiltering(FauxPropertyDao fauxPropertyDao, + VitroFilters filters) { + super(); + this.innerFauxPropertyDao = fauxPropertyDao; + this.filters = filters; + } + + /* filtered methods */ + + @Override + public List getFauxPropertiesForBaseUri(String uri) { + // TODO Auto-generated method stub + throw new RuntimeException( + "FauxPropertyDao.getFauxPropertiesForBaseUri() not implemented."); + } + + @Override + public FauxProperty getFauxPropertyFromConfigContextUri(String contextUri) { + // TODO Auto-generated method stub + throw new RuntimeException( + "FauxPropertyDaoFiltering.getFauxPropertyFromConfigContextUri() not implemented."); + + } + + @Override + public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, + String rangeUri) { + // TODO Auto-generated method stub + throw new RuntimeException( + "FauxPropertyDaoFiltering.getFauxPropertyByUris() not implemented."); + + } - public FauxPropertyDaoFiltering(FauxPropertyDao fauxPropertyDao, - VitroFilters filters) { - super(); - this.innerFauxPropertyDao = fauxPropertyDao; - this.filters = filters; - } - -// /* filtered methods */ -// public List getAllObjectProperties() { -// return filterAndWrap(innerFauxPropertyDao.getAllObjectProperties(), filters); -// } -// -// public List getObjectPropertiesForFauxPropertyStatements(List fauxPropertyStatements) { -// //assume that the objPropStmts are already filtered -// List list = -// innerFauxPropertyDao -// .getObjectPropertiesForFauxPropertyStatements(fauxPropertyStatements); -// return filterAndWrap(list, filters); -// } -// -// -// public FauxProperty getFauxPropertyByURI(String fauxPropertyURI) { -// FauxProperty newOprop=innerFauxPropertyDao.getFauxPropertyByURI(fauxPropertyURI); -// return (newOprop == null) ? null : new FauxPropertyFiltering(newOprop, filters); -// } -// -// public FauxProperty getFauxPropertyByURIs(String fauxPropertyURI, String domainURI, String rangeURI) { -// FauxProperty newOprop=innerFauxPropertyDao.getFauxPropertyByURIs(fauxPropertyURI, domainURI, rangeURI); -// return (newOprop == null) ? null : new FauxPropertyFiltering(newOprop, filters); -// } -// -// public FauxProperty getFauxPropertyByURIs(String fauxPropertyURI, String domainURI, String rangeURI, FauxProperty base) { -// FauxProperty newOprop=innerFauxPropertyDao.getFauxPropertyByURIs(fauxPropertyURI, domainURI, rangeURI, base); -// return (newOprop == null) ? null : new FauxPropertyFiltering(newOprop, filters); -// } -// -// public List getStatementsUsingFauxProperty(FauxProperty op) { -// return FauxPropertyStatementDaoFiltering.filterAndWrapList(innerFauxPropertyDao.getStatementsUsingFauxProperty(op),filters); -// } -// -// public List getRootObjectProperties() { -// return filterAndWrap(innerFauxPropertyDao.getRootObjectProperties(),filters); -// } -// -// -// /* other methods */ -// public void deleteFauxProperty(String fauxPropertyURI) { -// innerFauxPropertyDao.deleteFauxProperty(fauxPropertyURI); -// } -// -// -// public void deleteFauxProperty(FauxProperty fauxProperty) { -// innerFauxPropertyDao.deleteFauxProperty(fauxProperty); -// } -// -// -// public void fillObjectPropertiesForIndividual(Individual individual) { -// innerFauxPropertyDao.fillObjectPropertiesForIndividual(individual); -// } -// -// public int insertFauxProperty(FauxProperty fauxProperty) throws InsertException { -// return innerFauxPropertyDao.insertFauxProperty(fauxProperty); -// } -// -// public void updateFauxProperty(FauxProperty fauxProperty) { -// innerFauxPropertyDao.updateFauxProperty(fauxProperty); -// } -// -// public void addSuperproperty(FauxProperty property, FauxProperty superproperty) { -// innerFauxPropertyDao.addSuperproperty(property, superproperty); -// } -// -// public void addSuperproperty(String propertyURI, String superpropertyURI) { -// innerFauxPropertyDao.addSuperproperty(propertyURI, superpropertyURI); -// } -// -// public void removeSuperproperty(FauxProperty property, FauxProperty superproperty) { -// innerFauxPropertyDao.removeSuperproperty(property, superproperty); -// } -// -// public void removeSuperproperty(String propertyURI, String superpropertyURI) { -// innerFauxPropertyDao.removeSuperproperty(propertyURI, superpropertyURI); -// } -// -// public void addSubproperty(FauxProperty property, FauxProperty subproperty) { -// innerFauxPropertyDao.addSubproperty(property, subproperty); -// } -// -// public void addSubproperty(String propertyURI, String subpropertyURI) { -// innerFauxPropertyDao.addSubproperty(propertyURI, subpropertyURI); -// } -// -// public void removeSubproperty(FauxProperty property, FauxProperty subproperty) { -// innerFauxPropertyDao.removeSubproperty(property, subproperty); -// } -// -// public void removeSubproperty(String propertyURI, String subpropertyURI) { -// innerFauxPropertyDao.removeSubproperty(propertyURI, subpropertyURI); -// } -// -// public List getSubPropertyURIs(String propertyURI) { -// return innerFauxPropertyDao.getSubPropertyURIs(propertyURI); -// } -// -// public List getAllSubPropertyURIs(String propertyURI) { -// return innerFauxPropertyDao.getAllSubPropertyURIs(propertyURI); -// } -// -// public List getSuperPropertyURIs(String propertyURI, boolean direct) { -// return innerFauxPropertyDao.getSuperPropertyURIs(propertyURI, direct); -// } -// -// public List getAllSuperPropertyURIs(String propertyURI) { -// return innerFauxPropertyDao.getAllSuperPropertyURIs(propertyURI); -// } -// -// public static List filterAndWrap(List list, VitroFilters filters){ -// if( list == null ) return null; -// if( list.size() ==0 ) return list; -// -// List filtered = new LinkedList(); -// Filter.filter(list, -// new AndUnary(notNull,filters.getFauxPropertyFilter()), -// filtered); -// -// List wrapped = new LinkedList(); -// for( FauxProperty prop : filtered){ -// if( prop != null){ -// wrapped.add( new FauxPropertyFiltering(prop, filters)); -// } -// } -// return wrapped; -// } -// -// private static final UnaryFunctor notNull = -// new UnaryFunctor(){ -// @Override -// public Boolean fn(FauxProperty arg) { -// return arg != null; -// } -// }; -// -// public void addSubproperty(Property property, Property subproperty) { -// innerFauxPropertyDao.addSubproperty(property, subproperty); -// } -// -// public void addSuperproperty(Property property, Property superproperty) { -// innerFauxPropertyDao.addSuperproperty(property, superproperty); -// } -// -// public void removeSubproperty(Property property, Property subproperty) { -// innerFauxPropertyDao.removeSubproperty(property, subproperty); -// } -// -// public void removeSuperproperty(Property property, Property superproperty) { -// innerFauxPropertyDao.removeSuperproperty(property, superproperty); -// } -// -// public void addEquivalentProperty(String propertyURI, -// String equivalentPropertyURI) { -// innerFauxPropertyDao.addEquivalentProperty(propertyURI, equivalentPropertyURI); -// } -// -// public void addEquivalentProperty(Property property, -// Property equivalentProperty) { -// innerFauxPropertyDao.addEquivalentProperty(property, equivalentProperty); -// } -// -// public List getEquivalentPropertyURIs(String propertyURI) { -// return innerFauxPropertyDao.getEquivalentPropertyURIs(propertyURI); -// } -// -// public void removeEquivalentProperty(String propertyURI, -// String equivalentPropertyURI) { -// innerFauxPropertyDao.removeEquivalentProperty(propertyURI, equivalentPropertyURI); -// } -// -// public void removeEquivalentProperty(Property property, -// Property equivalentProperty) { -// innerFauxPropertyDao.removeEquivalentProperty(property, equivalentProperty); -// } -// -// public boolean skipEditForm(String predicateURI) { -// return innerFauxPropertyDao.skipEditForm(predicateURI); -// } -// -// public List getClassesWithRestrictionOnProperty(String propertyURI) { -// return innerFauxPropertyDao.getClassesWithRestrictionOnProperty(propertyURI); -// } -// -// @Override -// // This may need to be filtered at some point. -// public List getFauxPropertyList(Individual subject) { -// return innerFauxPropertyDao.getFauxPropertyList(subject); -// } -// -// @Override -// // This may need to be filtered at some point. -// public List getFauxPropertyList(String subjectUri) { -// return innerFauxPropertyDao.getFauxPropertyList(subjectUri); -// } -// -// @Override -// public String getCustomListViewConfigFileName(FauxProperty fauxProperty) { -// return innerFauxPropertyDao.getCustomListViewConfigFileName(fauxProperty); -// } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java index 3bfcddfe0..3201d9b4f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/FauxPropertyDaoJena.java @@ -2,32 +2,330 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; -import java.util.Map; +import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty; +import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; -import org.apache.jena.atlas.lib.Pair; +import java.util.ArrayList; +import java.util.List; -import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import com.hp.hpl.jena.ontology.OntModel; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.query.Syntax; +import com.hp.hpl.jena.rdf.model.Property; +import com.hp.hpl.jena.rdf.model.RDFNode; +import com.hp.hpl.jena.rdf.model.ResIterator; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.vocabulary.RDF; + +import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao; -import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService; +import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractOntModelDecorator; +import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner; +import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser; /** * TODO */ public class FauxPropertyDaoJena implements FauxPropertyDao { + private static final Log log = LogFactory.getLog(FauxPropertyDaoJena.class); - /** - * @param rdfService - * @param dwf - * @param customListViewConfigFileMap - * @param webappDaoFactoryJena - */ - public FauxPropertyDaoJena( - RDFService rdfService, - DatasetWrapperFactory dwf, - Map>, String> customListViewConfigFileMap, - WebappDaoFactoryJena webappDaoFactoryJena) { - // TODO Auto-generated constructor stub - throw new RuntimeException("FauxPropertyDaoJena Constructor not implemented."); + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + private static final String APPLICATION_CONTEXT_NS = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#"; + private static final Resource CONFIG_CONTEXT = createResource(APPLICATION_CONTEXT_NS + + "ConfigContext"); + private static final Property HAS_CONFIGURATION = createProperty(APPLICATION_CONTEXT_NS + + "hasConfiguration"); + private static final Property CONFIG_CONTEXT_FOR = createProperty(APPLICATION_CONTEXT_NS + + "configContextFor"); + private static final Property QUALIFIED_BY_RANGE = createProperty(APPLICATION_CONTEXT_NS + + "qualifiedBy"); + private static final Property QUALIFIED_BY_DOMAIN = createProperty(APPLICATION_CONTEXT_NS + + "qualifiedByDomain"); + + private static final Property DISPLAY_NAME = createProperty(APPLICATION_CONTEXT_NS + + "displayName"); + + // ---------------------------------------------------------------------- + // Queries and parsers + // ---------------------------------------------------------------------- + + private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN = "" // + + "PREFIX : \n" // + + "\n" // + + "SELECT DISTINCT ?context \n" // + + "WHERE { \n" // + + " ?context a :ConfigContext ; \n" // + + " :configContextFor ?baseUri ; \n" // + + " :qualifiedByDomain ?domainUri ; \n" // + + " :qualifiedBy ?rangeUri . \n" // + + "} \n"; // + + // TODO Add a filter that will reject solutions that include qualifiedByDomain + private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN = "" // + + "PREFIX : \n" // + + "\n" // + + "SELECT DISTINCT ?context \n" // + + "WHERE { \n" // + + " ?context a :ConfigContext ; \n" // + + " :configContextFor ?baseUri ; \n" // + + " :qualifiedBy ?rangeUri . \n" // + + "} \n"; // + + private static final QueryParser PARSER_LOCATE_CONFIG_CONTEXT = new QueryParser() { + @Override + protected String defaultValue() { + return null; + } + + @Override + protected String parseResults(String queryStr, ResultSet results) { + if (results.hasNext()) { + return ifResourcePresent(results.next(), "context", null); + } else { + return null; + } + } + }; + + // ---------------------------------------------------------------------- + // The instance + // ---------------------------------------------------------------------- + + private final LockingOntModelSelector models; + + public FauxPropertyDaoJena(WebappDaoFactoryJena wadf) { + this.models = new LockingOntModelSelector(wadf.getOntModelSelector()); } + @Override + public List getFauxPropertiesForBaseUri(String uri) { + List list = new ArrayList<>(); + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + if (uri != null) { + ResIterator contextResources = displayModel + .listSubjectsWithProperty(CONFIG_CONTEXT_FOR, + createResource(uri)); + for (Resource context : contextResources.toList()) { + if (!context.isURIResource()) { + continue; + } + + FauxProperty fp = getFauxPropertyFromConfigContextUri(context + .getURI()); + if (fp == null) { + continue; + } + + list.add(fp); + } + } + } + return list; + } + + @Override + public FauxProperty getFauxPropertyFromConfigContextUri(String contextUri) { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + if (contextUri == null) { + return null; + } + + Resource context = createResource(contextUri); + if (!displayModel.contains(context, RDF.type, CONFIG_CONTEXT)) { + log.debug("'" + contextUri + "' is not a CONFIG_CONTEXT"); + return null; + } + + String baseUri = getUriValue(displayModel, context, + CONFIG_CONTEXT_FOR); + if (baseUri == null) { + log.debug("'" + contextUri + "' has no value for '" + + CONFIG_CONTEXT_FOR + "'"); + return null; + } + + String rangeUri = getUriValue(displayModel, context, + QUALIFIED_BY_RANGE); + if (rangeUri == null) { + log.debug("'" + contextUri + "' has no value for '" + + QUALIFIED_BY_RANGE + "'"); + return null; + } + + // domainURI is optional. + String domainUri = getUriValue(displayModel, context, + QUALIFIED_BY_DOMAIN); + + FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri); + populateInstance(fp, displayModel, context); + return fp; + } + } + + @Override + public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, + String rangeUri) { + try (LockedOntModel displayModel = models.getDisplayModel().read()) { + String queryString; + if (domainUri == null) { + queryString = substituteUri( + substituteUri( + QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN, + baseUri, "baseUri"), rangeUri, "rangeUri"); + } else { + queryString = substituteUri( + substituteUri( + substituteUri( + QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN, + baseUri, "baseUri"), rangeUri, + "rangeUri"), domainUri, "domainUri"); + } + + String contextUri = new SparqlQueryRunner(displayModel) + .executeSelect(PARSER_LOCATE_CONFIG_CONTEXT, queryString); + + if (contextUri == null) { + log.debug("Can't find a ContextConfig for '" + domainUri + + "', '" + baseUri + "', '" + rangeUri + "'"); + return null; + } + + FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri); + populateInstance(fp, displayModel, createResource(contextUri)); + return fp; + } + } + + /** + * Add labels, annotations, and whatever else we can find on the + * ConfigContext. + */ + private void populateInstance(FauxProperty fp, LockedOntModel model, + Resource context) { + String configUri = getUriValue(model, context, HAS_CONFIGURATION); + if (configUri == null) { + return; + } + Resource config = createResource(configUri); + + String displayName = getStringValue(model, config, DISPLAY_NAME); + if (displayName != null) { + fp.setPickListName(displayName); + } + + // TODO pull all sorts of things from the configuration. + // TODO pull labels for the domain and range classes. + } + + private String substituteUri(String queryString, String variableName, + String uri) { + return queryString.replace("?" + variableName, "<" + uri + ">"); + } + + /** + * Returns a single URI that is the object of this subject and property. + * Returns null if no valid statement is found. + */ + private String getUriValue(LockedOntModel displayModel, Resource subject, + Property property) { + List nodeList = displayModel.listObjectsOfProperty(subject, + property).toList(); + if (nodeList.isEmpty()) { + log.warn("'" + subject.getURI() + "' has no value for '" + + property.getURI() + "'."); + return null; + } + + RDFNode node = nodeList.get(0); + if (nodeList.size() > 1) { + log.warn("'" + subject.getURI() + "' has " + nodeList.size() + + " values for ''. Using '" + node + "'"); + } + if (!node.isURIResource()) { + log.warn("Value of '" + subject.getURI() + property.getURI() + + "' '' is not a URI resource."); + return null; + } + return node.asResource().getURI(); + } + + /** + * Returns a single String value that is the object of this subject and + * property. Returns null if no valid statement is found. + */ + private String getStringValue(LockedOntModel displayModel, + Resource subject, Property property) { + List nodeList = displayModel.listObjectsOfProperty(subject, + property).toList(); + if (nodeList.isEmpty()) { + log.warn("'" + subject.getURI() + "' has no value for '" + + property.getURI() + "'."); + return null; + } + + RDFNode node = nodeList.get(0); + if (nodeList.size() > 1) { + log.warn("'" + subject.getURI() + "' has " + nodeList.size() + + " values for ''. Using '" + node + "'"); + } + if (!node.isLiteral()) { + log.warn("Value of '" + subject.getURI() + property.getURI() + + "' '' is not a Literal."); + return null; + } + return node.asLiteral().getString(); + } + + // ---------------------------------------------------------------------- + // Helper classes. Are they worth it, just to use try-with-resources? + // ---------------------------------------------------------------------- + + private static class LockingOntModelSelector { + private final OntModelSelector oms; + + public LockingOntModelSelector(OntModelSelector oms) { + this.oms = oms; + } + + public LockableOntModel getDisplayModel() { + return new LockableOntModel(oms.getDisplayModel()); + } + } + + private static class LockableOntModel { + private final OntModel ontModel; + + public LockableOntModel(OntModel ontModel) { + this.ontModel = ontModel; + } + + public LockedOntModel read() { + ontModel.enterCriticalSection(Lock.READ); + return new LockedOntModel(ontModel); + } + } + + private static class LockedOntModel extends AbstractOntModelDecorator + implements AutoCloseable { + + protected LockedOntModel(OntModel m) { + super(m); + } + + /** + * Just unlocks the model. Doesn't actually close it, because we may + * want to use it again. + */ + @Override + public void close() { + super.leaveCriticalSection(); + } + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java index cc3e12677..e96192b30 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java @@ -379,9 +379,9 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { private FauxPropertyDao fauxPropertyDao = null; @Override public FauxPropertyDao getFauxPropertyDao() { - if( fauxPropertyDao == null ) - fauxPropertyDao = new FauxPropertyDaoJena( - rdfService, dwf, config.customListViewConfigFileMap, this); + if( fauxPropertyDao == null ) { + fauxPropertyDao = new FauxPropertyDaoJena(this); + } return fauxPropertyDao; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/SparqlQueryRunner.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/SparqlQueryRunner.java index 87f9fd4ce..6ffb697ca 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/SparqlQueryRunner.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/SparqlQueryRunner.java @@ -15,6 +15,7 @@ import com.hp.hpl.jena.query.Syntax; import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.RDFNode; /** * Execute SPARQL queries against a model. @@ -95,6 +96,15 @@ public class SparqlQueryRunner { protected abstract T defaultValue(); + protected String ifResourcePresent(QuerySolution solution, + String variableName, String defaultValue) { + RDFNode node = solution.get(variableName); + if (node == null || !node.isURIResource()) { + return defaultValue; + } + return node.asResource().getURI(); + } + protected String ifLiteralPresent(QuerySolution solution, String variableName, String defaultValue) { Literal literal = solution.getLiteral(variableName); diff --git a/webapp/web/templates/edit/specific/props_edit.jsp b/webapp/web/templates/edit/specific/props_edit.jsp index c4c130621..cad21169b 100644 --- a/webapp/web/templates/edit/specific/props_edit.jsp +++ b/webapp/web/templates/edit/specific/props_edit.jsp @@ -91,6 +91,43 @@ +
+ + + + + +
    + + + + + +
  • + ${fauxproperty.pickListName} + + + no domain, + + + domain: ${fauxproperty.domainLabel}, + + + range: ${fauxproperty.rangeLabel} +
  • +
+
+
+ + +
+ + + +
+ + +