VIVO-774 More functionality: implement deleteFauxProperty()

This commit is contained in:
Jim Blake 2014-10-31 18:17:38 -04:00
parent 564130329e
commit 190bf87979
9 changed files with 519 additions and 110 deletions

View file

@ -6,15 +6,27 @@ import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import java.util.Objects; import java.util.Objects;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.RoleRestrictedProperty;
/** /**
* Represents a specialization on an ObjectProperty, only meaningful for * Represents a specialization on an ObjectProperty, only meaningful for
* display. * display.
* *
* Must have a baseURI and a rangeURI. Other fields are optional. * BaseURI is required, may not be null, and may not be modified.
*
* It would be nice to place the same restrictions on rangeURI, but it may be
* null when the FauxProperty is being created, and it may be modified. The DAO
* will need to check rangeURI for validity before accepting an insert or
* modification.
*
* TODO Can we do this more cleanly? Can handle this as two classes FauxProperty
* and NewFauxProperty, and have each class enforce its own internal
* constraints? For example, the range must not be null, must represent a valid
* class, and must be equal to or a subclass of the range of the base property.
*/ */
public class FauxProperty extends BaseResourceBean implements ResourceBean { public class FauxProperty extends BaseResourceBean implements ResourceBean, RoleRestrictedProperty {
private final String rangeURI; private String rangeURI;
private final String domainURI; private String domainURI;
private String rangeLabel; private String rangeLabel;
private String domainLabel; private String domainLabel;
@ -28,15 +40,22 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean {
* @param baseURI * @param baseURI
* URI of the property. May not be null. * URI of the property. May not be null.
* @param rangeUri * @param rangeUri
* URI of the object class. May not be null. * URI of the object class. May be null.
*/ */
public FauxProperty(String domainURI, String baseURI, String rangeURI) { public FauxProperty(String domainURI, String baseURI, String rangeURI) {
super(Objects.requireNonNull(baseURI, "baseURI may not be null")); super(Objects.requireNonNull(baseURI, "baseURI may not be null"));
this.rangeURI = Objects.requireNonNull(rangeURI, this.rangeURI = rangeURI;
"rangeURI may not be null");
this.domainURI = domainURI; this.domainURI = domainURI;
} }
public FauxProperty() {
// This is required by OperationUtils.cloneBean()
}
public void setRangeURI(String rangeURI) {
this.rangeURI = rangeURI;
}
public String getRangeURI() { public String getRangeURI() {
return rangeURI; return rangeURI;
} }
@ -49,6 +68,10 @@ public class FauxProperty extends BaseResourceBean implements ResourceBean {
return (rangeLabel == null) ? localName(rangeURI) : rangeLabel; return (rangeLabel == null) ? localName(rangeURI) : rangeLabel;
} }
public void setDomainURI(String domainURI) {
this.domainURI = domainURI;
}
public String getDomainURI() { public String getDomainURI() {
return domainURI; return domainURI;
} }

View file

@ -2,16 +2,36 @@
package edu.cornell.mannlib.vitro.webapp.controller.edit; package edu.cornell.mannlib.vitro.webapp.controller.edit;
import java.util.Collections;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
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.controller.BaseEditController; import edu.cornell.mannlib.vedit.controller.BaseEditController;
import edu.cornell.mannlib.vedit.util.FormUtils;
import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission; import edu.cornell.mannlib.vitro.webapp.auth.permissions.SimplePermission;
import edu.cornell.mannlib.vitro.webapp.auth.policy.bean.PropertyRestrictionListener;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.modelaccess.ModelAccess;
/** /**
* TODO * TODO
*/ */
public class FauxPropertyRetryController extends BaseEditController { public class FauxPropertyRetryController extends BaseEditController {
private static final Log log = LogFactory
.getLog(FauxPropertyRetryController.class);
@Override @Override
public void doPost(HttpServletRequest req, HttpServletResponse response) { public void doPost(HttpServletRequest req, HttpServletResponse response) {
if (!isAuthorizedToDisplayPage(req, response, if (!isAuthorizedToDisplayPage(req, response,
@ -19,13 +39,98 @@ public class FauxPropertyRetryController extends BaseEditController {
return; return;
} }
VitroRequest request = new VitroRequest(req);
// create an EditProcessObject for this and put it in the session
EditProcessObject epo = super.createEpo(request);
ServletContext ctx = getServletContext();
FauxPropertyDao fpDao = ModelAccess.on(ctx).getWebappDaoFactory()
.getFauxPropertyDao();
epo.setDataAccessObject(fpDao);
FauxProperty fpForEditing = null;
if (epo.getUseRecycledBean()) {
fpForEditing = (FauxProperty) epo.getNewBean();
} else {
String create = request.getParameter("create");
String baseUri = request.getParameter("baseUri");
String rangeUri = request.getParameter("rangeUri");
String domainUri = request.getParameter("domainUri");
if (create != null) {
fpForEditing = new FauxProperty(null, baseUri, null);
epo.setAction("insert");
} else {
fpForEditing = fpDao.getFauxPropertyByUris(domainUri, baseUri,
rangeUri);
if (fpForEditing == null) {
throw new IllegalArgumentException(
"FauxProperty does not exist for <" + domainUri
+ "> ==> <" + baseUri + "> ==> <"
+ rangeUri + ">");
}
epo.setAction("update");
}
epo.setOriginalBean(fpForEditing);
}
// set any validators
// TODO NONE YET
// set up any listeners
epo.setChangeListenerList(Collections
.singletonList(new PropertyRestrictionListener(ctx)));
// where should the postinsert pageforwarder go?
// TODO // TODO
// make a postdelete pageforwarder that will send us to the control
// panel for the base property.
// TODO
FormObject foo = new FormObject();
foo.setErrorMap(epo.getErrMsgMap());
// We will need to set a lot of option lists and stuff.
// TODO
// Put attributes on the request so the JSP can populate the fields.
// request.setAttribute("transitive",propertyForEditing.getTransitive());
// request.setAttribute("objectIndividualSortPropertyURI",
// propertyForEditing.getObjectIndividualSortPropertyURI());
// TODO
// checkboxes are pretty annoying : we don't know if someone *unchecked*
// a box, so we have to default to false on updates.
// propertyForEditing.setSymmetric(false);
// TODO
epo.setFormObject(foo);
FormUtils.populateFormFromBean(fpForEditing, epo.getAction(), foo,
epo.getBadValueMap());
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
request.setAttribute("bodyJsp","/templates/edit/formBasic.jsp");
request.setAttribute("colspan","5");
request.setAttribute("formJsp","/templates/edit/specific/fauxProperty_retry.jsp");
request.setAttribute("scripts","/templates/edit/formBasic.js");
request.setAttribute("title","Faux Property Editing Form");
request.setAttribute("_action",epo.getAction());
setRequestAttributes(request,epo);
try {
rd.forward(request, response);
} catch (Exception e) {
log.error("Could not forward to view.");
log.error(e.getMessage());
log.error(e.getStackTrace());
}
} }
@Override @Override
public void doGet (HttpServletRequest request, HttpServletResponse response) { public void doGet(HttpServletRequest request, HttpServletResponse response) {
doPost(request, response); doPost(request, response);
} }
} }

View file

@ -42,4 +42,17 @@ public interface FauxPropertyDao {
FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, FauxProperty getFauxPropertyByUris(String domainUri, String baseUri,
String rangeUri); String rangeUri);
/**
* Delete this FauxProperty from the display model.
*
* Delete any ConfigContext that is based on the constraints in this
* FauxProperty, and any ObjectPropertyDisplayConfigs that depend on that
* ConfigContext.
*
* If no such ConfigContext is found, no error is raised.
*
* No check is made to see whether the ObjectPropertyDisplayConfig matches
* the settings on this FauxProperty.
*/
void deleteFauxProperty(FauxProperty fp);
} }

View file

@ -48,4 +48,14 @@ public class FauxPropertyDaoFiltering extends BaseFiltering implements FauxPrope
} }
/* (non-Javadoc)
* @see edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao#deleteFauxProperty(edu.cornell.mannlib.vitro.webapp.beans.FauxProperty)
*/
@Override
public void deleteFauxProperty(FauxProperty fp) {
// TODO Auto-generated method stub
throw new RuntimeException("FauxPropertyDao.deleteFauxProperty() not implemented.");
}
} }

View file

@ -4,16 +4,21 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty; import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty;
import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.bindValues;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.uriValue;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.query.QuerySolution;
import com.hp.hpl.jena.query.ResultSet; 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.Property;
import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.ResIterator; import com.hp.hpl.jena.rdf.model.ResIterator;
@ -23,6 +28,7 @@ import com.hp.hpl.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty; import edu.cornell.mannlib.vitro.webapp.beans.FauxProperty;
import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.FauxPropertyDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.rdfservice.adapters.AbstractOntModelDecorator; 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;
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser; import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.QueryParser;
@ -51,49 +57,12 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
private static final Property DISPLAY_NAME = createProperty(APPLICATION_CONTEXT_NS private static final Property DISPLAY_NAME = createProperty(APPLICATION_CONTEXT_NS
+ "displayName"); + "displayName");
private static final Property RDFS_LABEL = createProperty(VitroVocabulary.LABEL);
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Queries and parsers // Queries and parsers
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \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 : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedBy ?rangeUri . \n" //
+ "} \n"; //
private static final QueryParser<String> PARSER_LOCATE_CONFIG_CONTEXT = new QueryParser<String>() {
@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 // The instance
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -164,7 +133,7 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
QUALIFIED_BY_DOMAIN); QUALIFIED_BY_DOMAIN);
FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri); FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri);
populateInstance(fp, displayModel, context); populateInstance(fp, context);
return fp; return fp;
} }
} }
@ -172,61 +141,72 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
@Override @Override
public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri, public FauxProperty getFauxPropertyByUris(String domainUri, String baseUri,
String rangeUri) { String rangeUri) {
try (LockedOntModel displayModel = models.getDisplayModel().read()) { Set<ConfigContext> contexts = ConfigContext.findByQualifiers(models,
String queryString; domainUri, baseUri, rangeUri);
if (domainUri == null) { for (ConfigContext context : contexts) {
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); FauxProperty fp = new FauxProperty(domainUri, baseUri, rangeUri);
populateInstance(fp, displayModel, createResource(contextUri)); populateInstance(fp, createResource(context.getContextUri()));
return fp; return fp;
} }
log.debug("Can't find a FauxProperty for '" + domainUri + "', '"
+ baseUri + "', '" + rangeUri + "'");
return null;
}
@Override
public void deleteFauxProperty(FauxProperty fp) {
Set<ConfigContext> contexts = ConfigContext.findByQualifiers(models,
fp.getDomainURI(), fp.getURI(), fp.getRangeURI());
try (LockedOntModel displayModel = models.getDisplayModel().write()) {
for (ConfigContext context : contexts) {
Resource configResource = createResource(context.getConfigUri());
displayModel.removeAll(configResource, null, null);
displayModel.removeAll(null, null, configResource);
Resource contextResource = createResource(context.getContextUri());
displayModel.removeAll(contextResource, null, null);
displayModel.removeAll(null, null, contextResource);
}
}
} }
/** /**
* Add labels, annotations, and whatever else we can find on the * Add labels, annotations, and whatever else we can find on the
* ConfigContext. * ObjectPropertyDisplayConfig.
*/ */
private void populateInstance(FauxProperty fp, LockedOntModel model, private void populateInstance(FauxProperty fp, Resource context) {
Resource context) { // Range label and domain label.
String configUri = getUriValue(model, context, HAS_CONFIGURATION); try (LockedOntModel tboxModel = models.getTBoxModel().read()) {
if (configUri == null) { String rangeLabel = getStringValue(tboxModel,
return; createProperty(fp.getRangeURI()), RDFS_LABEL);
} if (rangeLabel != null) {
Resource config = createResource(configUri); fp.setRangeLabel(rangeLabel);
}
String displayName = getStringValue(model, config, DISPLAY_NAME); String domainLabel = getStringValue(tboxModel,
if (displayName != null) { createProperty(fp.getDomainURI()), RDFS_LABEL);
fp.setPickListName(displayName); if (domainLabel != null) {
fp.setDomainLabel(domainLabel);
}
}
// Display name.
try (LockedOntModel displayModel = models.getDisplayModel().read()) {
String configUri = getUriValue(displayModel, context,
HAS_CONFIGURATION);
if (configUri == null) {
return;
}
Resource config = createResource(configUri);
String displayName = getStringValue(displayModel, config,
DISPLAY_NAME);
if (displayName != null) {
fp.setPickListName(displayName);
}
} }
// TODO pull all sorts of things from the configuration. // 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 + ">");
} }
/** /**
@ -283,6 +263,135 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
return node.asLiteral().getString(); return node.asLiteral().getString();
} }
// ----------------------------------------------------------------------
// ConfigContext
// ----------------------------------------------------------------------
private static final String QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedByDomain ?domainUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \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 : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
private static class ParserLocateConfigContext extends
QueryParser<Set<ConfigContext>> {
private final String domainUri;
private final String baseUri;
private final String rangeUri;
public ParserLocateConfigContext(String domainUri, String baseUri,
String rangeUri) {
this.domainUri = domainUri;
this.baseUri = baseUri;
this.rangeUri = rangeUri;
}
@Override
protected Set<ConfigContext> defaultValue() {
return Collections.emptySet();
}
@Override
protected Set<ConfigContext> parseResults(String queryStr,
ResultSet results) {
Set<ConfigContext> set = new HashSet<>();
while (results.hasNext()) {
QuerySolution row = results.next();
String contextUri = ifResourcePresent(row, "context", null);
String configUri = ifResourcePresent(row, "config", null);
if (contextUri != null && configUri != null) {
set.add(new ConfigContext(contextUri, configUri, domainUri,
baseUri, rangeUri));
}
}
return set;
}
}
private static class ConfigContext {
public static Set<ConfigContext> findByQualifiers(
LockingOntModelSelector models, String domainUri,
String baseUri, String rangeUri) {
try (LockedOntModel displayModel = models.getDisplayModel().read()) {
String queryString;
if (domainUri == null) {
queryString = bindValues(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_NO_DOMAIN,
uriValue("baseUri", baseUri),
uriValue("rangeUri", rangeUri));
} else {
queryString = bindValues(
QUERY_LOCATE_CONFIG_CONTEXT_WITH_DOMAIN,
uriValue("baseUri", baseUri),
uriValue("rangeUri", rangeUri),
uriValue("domainUri", domainUri));
}
ParserLocateConfigContext parser = new ParserLocateConfigContext(
domainUri, baseUri, rangeUri);
return new SparqlQueryRunner(displayModel).executeSelect(
parser, queryString);
}
}
private final String contextUri;
private final String configUri;
private final String domainUri;
private final String baseUri;
private final String rangeUri;
public ConfigContext(String contextUri, String configUri,
String domainUri, String baseUri, String rangeUri) {
this.contextUri = contextUri;
this.configUri = configUri;
this.domainUri = domainUri;
this.baseUri = baseUri;
this.rangeUri = rangeUri;
}
public String getContextUri() {
return contextUri;
}
public String getConfigUri() {
return configUri;
}
public String getDomainUri() {
return domainUri;
}
public String getBaseUri() {
return baseUri;
}
public String getRangeUri() {
return rangeUri;
}
}
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
// Helper classes. Are they worth it, just to use try-with-resources? // Helper classes. Are they worth it, just to use try-with-resources?
// ---------------------------------------------------------------------- // ----------------------------------------------------------------------
@ -297,6 +406,10 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
public LockableOntModel getDisplayModel() { public LockableOntModel getDisplayModel() {
return new LockableOntModel(oms.getDisplayModel()); return new LockableOntModel(oms.getDisplayModel());
} }
public LockableOntModel getTBoxModel() {
return new LockableOntModel(oms.getTBoxModel());
}
} }
private static class LockableOntModel { private static class LockableOntModel {
@ -310,6 +423,11 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
ontModel.enterCriticalSection(Lock.READ); ontModel.enterCriticalSection(Lock.READ);
return new LockedOntModel(ontModel); return new LockedOntModel(ontModel);
} }
public LockedOntModel write() {
ontModel.enterCriticalSection(Lock.WRITE);
return new LockedOntModel(ontModel);
}
} }
private static class LockedOntModel extends AbstractOntModelDecorator private static class LockedOntModel extends AbstractOntModelDecorator
@ -328,4 +446,5 @@ public class FauxPropertyDaoJena implements FauxPropertyDao {
super.leaveCriticalSection(); super.leaveCriticalSection();
} }
} }
} }

View file

@ -137,4 +137,35 @@ public class SparqlQueryRunner {
} }
public static String bindValues(String rawString, VariableValue... values) {
String queryString = rawString;
for (VariableValue value: values) {
queryString = value.bind(queryString);
}
return queryString;
}
public static UriValue uriValue(String name, String uri) {
return new UriValue(name, uri);
}
public interface VariableValue {
String bind(String rawString);
}
private static class UriValue implements VariableValue {
private final String name;
private final String uri;
public UriValue(String name, String uri) {
this.name = name;
this.uri = uri;
}
@Override
public String bind(String rawString) {
return rawString.replaceAll("\\?" + name + "\\b", "<" + uri + ">");
}
}
} }

View file

@ -0,0 +1,92 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.utils;
import static org.junit.Assert.*;
import static edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryRunner.*;
import org.junit.Test;
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
/**
* For now, just test the methods that manipulate the query string.
*/
public class SparqlQueryRunnerTest extends AbstractTestClass {
@Test
public void bindValuesNameNotFound() {
String raw = "No such name here";
String expected = raw;
assertEquals(expected, bindValues(raw, uriValue("bogus", "BOGUS")));
}
@Test
public void bindOneUri() {
String raw = "Replace both ?this and ?this also.";
String expected = "Replace both <URI> and <URI> also.";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
@Test
public void bindTwoUris() {
String raw = "Replace both ?this and ?that also.";
String expected = "Replace both <URI> and <ANOTHER> also.";
assertEquals(
expected,
bindValues(raw, uriValue("this", "URI"),
uriValue("that", "ANOTHER")));
}
@Test
public void honorWordBoundary() {
String raw = "Replace ?this but not ?thistle.";
String expected = "Replace <URI> but not ?thistle.";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
@Test
public void honorStringLimit() {
String raw = "?this";
String expected = "<URI>";
assertEquals(expected, bindValues(raw, uriValue("this", "URI")));
}
private static final String REAL_WORLD_RAW = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor ?baseUri ; \n" //
+ " :qualifiedByDomain ?domainUri ; \n" //
+ " :qualifiedBy ?rangeUri ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
private static final String REAL_WORLD_EXPECTED = "" //
+ "PREFIX : <http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationConfiguration#> \n" //
+ "\n" //
+ "SELECT DISTINCT ?context ?config \n" //
+ "WHERE { \n" //
+ " ?context a :ConfigContext ; \n" //
+ " :configContextFor <http://vivoweb.org/ontology/core#relates> ; \n" //
+ " :qualifiedByDomain <http://vivoweb.org/ontology/core#Contract> ; \n" //
+ " :qualifiedBy <http://vivoweb.org/ontology/core#ResearcherRole> ; \n" //
+ " :hasConfiguration ?config . \n" //
+ "} \n"; //
@Test
public void realWorldExample() {
assertEquals(
REAL_WORLD_EXPECTED,
bindValues(
REAL_WORLD_RAW,
uriValue("baseUri",
"http://vivoweb.org/ontology/core#relates"),
uriValue("domainUri",
"http://vivoweb.org/ontology/core#Contract"),
uriValue("rangeUri",
"http://vivoweb.org/ontology/core#ResearcherRole")));
}
}

View file

@ -0,0 +1,6 @@
<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
<%@ taglib prefix="form" uri="http://vitro.mannlib.cornell.edu/edit/tags" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<h1>Like, TOTALLY BOGUS.</h1>

View file

@ -98,18 +98,25 @@
<c:if test="${!empty fauxproperties}"> <c:if test="${!empty fauxproperties}">
<c:forEach var="fauxproperty" items="${fauxproperties}"> <c:forEach var="fauxproperty" items="${fauxproperties}">
<ul style="list-style-type:none;"> <ul style="list-style-type:none;">
<c:url var="fauxpropertyURL" value="fauxpropertyEdit">
<c:param name="property" value="${property.URI}"/>
<c:param name="domain" value="${fauxproperty.domainURI}" />
<c:param name="range" value="${fauxproperty.rangeURI}" />
</c:url>
<li> <li>
<a href="${fauxpropertyURL}">${fauxproperty.pickListName}</a>
<c:choose> <c:choose>
<c:when test="${empty fauxproperty.domainLabel}"> <c:when test="${empty fauxproperty.domainLabel}">
<c:url var="fauxpropertyURL" value="editForm">
<c:param name="controller" value="FauxProperty"/>
<c:param name="baseUri" value="${property.URI}"/>
<c:param name="rangeUri" value="${fauxproperty.rangeURI}" />
</c:url>
<a href="${fauxpropertyURL}">${fauxproperty.pickListName}</a>
no domain, no domain,
</c:when> </c:when>
<c:otherwise> <c:otherwise>
<c:url var="fauxpropertyURL" value="editForm">
<c:param name="controller" value="FauxProperty"/>
<c:param name="baseUri" value="${property.URI}"/>
<c:param name="domainUri" value="${fauxproperty.domainURI}" />
<c:param name="rangeUri" value="${fauxproperty.rangeURI}" />
</c:url>
<a href="${fauxpropertyURL}">${fauxproperty.pickListName}</a>
domain: ${fauxproperty.domainLabel}, domain: ${fauxproperty.domainLabel},
</c:otherwise> </c:otherwise>
</c:choose> </c:choose>
@ -120,14 +127,17 @@
</c:if> </c:if>
</td> </td>
<td> <td>
<form action="editForm" method="get"> <form action="editForm" method="get">
<input type="hidden" name="basepropertyURI" value="${property.URI}"/> <input type="hidden" name="create" value="create"/>
<input type="hidden" name="controller" value="FauxProperty"/> <input type="hidden" name="baseUri" value="${property.URI}"/>
<input type="submit" class="form-button" value="Create New Faux Property"/> <input type="hidden" name="controller" value="FauxProperty"/>
</form> <input type="submit" class="form-button" value="Create New Faux Property"/>
</form>
</td> </td>
</tr> </tr>
<tr><td colspan="3"><hr/></td></tr> <tr><td colspan="3"><hr/></td></tr>
<!-- _____________________________________________ superproperties __________________________________________ --> <!-- _____________________________________________ superproperties __________________________________________ -->
<tr valign="bottom" align="center"> <tr valign="bottom" align="center">