diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java index 37ad01170..fa76dc1ad 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java @@ -21,12 +21,13 @@ public interface WebappDaoFactory { public String checkURI(String uriStr); /** - * Checks a URI String for two things: well-formedness and, optionally, - * uniqueness in the model. Ill-formed strings or those matching URIs - * already in use will cause an error message to be returned. + * Checks a URI String to see whether it is suitable for use on a new editable entity. + * It must be well-formed, and it must not be declared in the model as a Thing, Class, + * ObjectProperty or DataProperty. Ill-formed strings or those so declared will + * cause an error message to be returned. * @return error message String if invalid; otherwise null */ - public String checkURI(String uriStr, boolean checkUniqueness); + public String checkURIForEditableEntity(String uriStr); /** * Check if a given URI string exists in the system: diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java index a6d87fd0f..144711afa 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java @@ -88,11 +88,12 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory { return innerWebappDaoFactory.checkURI(uriStr); } - public String checkURI(String uriStr, boolean checkUniqueness) { - return innerWebappDaoFactory.checkURI(uriStr, checkUniqueness); - } - - public boolean hasExistingURI(String uriStr) { + @Override + public String checkURIForEditableEntity(String uriStr) { + return innerWebappDaoFactory.checkURIForEditableEntity(uriStr); + } + + public boolean hasExistingURI(String uriStr) { return innerWebappDaoFactory.hasExistingURI(uriStr); } 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 5afeca4d8..f566e992c 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 @@ -487,7 +487,7 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements ontModel.enterCriticalSection(Lock.WRITE); try { getOntModel().getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true)); - String errMsgStr = getWebappDaoFactory().checkURI(dtp.getURI()); + String errMsgStr = getWebappDaoFactory().checkURIForEditableEntity(dtp.getURI()); if (errMsgStr != null) { throw new InsertException(errMsgStr); } 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 f85ed8406..1d5abfd64 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 @@ -534,7 +534,7 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp ontModel.enterCriticalSection(Lock.WRITE); try { getOntModel().getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true)); - String errMsgStr = getWebappDaoFactory().checkURI(prop.getURI()); + String errMsgStr = getWebappDaoFactory().checkURIForEditableEntity(prop.getURI()); if (errMsgStr != null) { throw new InsertException(errMsgStr); } @@ -542,7 +542,7 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp com.hp.hpl.jena.ontology.ObjectProperty inv = null; if (hasInverse(prop)) { log.debug("non-null inverse URI: " +prop.getURIInverse()); - errMsgStr = getWebappDaoFactory().checkURI(prop.getURIInverse()); + errMsgStr = getWebappDaoFactory().checkURIForEditableEntity(prop.getURIInverse()); if (errMsgStr != null) { throw new InsertException("Unusable URI for inverse property: "+errMsgStr); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java index 85e708987..d136a95f7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/VClassDaoJena.java @@ -934,7 +934,7 @@ public class VClassDaoJena extends JenaBaseDao implements VClassDao { ontModel.enterCriticalSection(Lock.WRITE); getOntModel().getBaseModel().notifyEvent(new EditEvent(getWebappDaoFactory().getUserURI(),true)); try { - String errMsgStr = getWebappDaoFactory().checkURI(cls.getURI()); + String errMsgStr = getWebappDaoFactory().checkURIForEditableEntity(cls.getURI()); if (errMsgStr != null) { throw new InsertException(errMsgStr); } 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 c40fca4f3..826c5f36a 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 @@ -23,6 +23,8 @@ 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; +import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.util.iterator.ClosableIterator; @@ -174,41 +176,67 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { return this.properties; } - @Override + @Override public String checkURI(String uriStr) { - return checkURI(uriStr, true); - } + String errorMessage = checkURIForValidity(uriStr); + if (errorMessage != null) { + return errorMessage; + } + + if (this.hasExistingURI(uriStr)) { + return "URI is already in use. Please enter another URI. "; + } + + return null; + } @Override - public String checkURI(String uriStr, boolean checkUniqueness) { - uriStr = (uriStr == null) ? " " : uriStr; - String errorMsg = ""; - String duplicateMsg = "URI is already in use. " + - "Please enter another URI. "; - IRIFactory factory = IRIFactory.jenaImplementation(); - IRI iri = factory.create( uriStr ); - if (iri.hasViolation(false) ) { - errorMsg += (iri.violations(false).next()) - .getShortMessage() + " "; - } else if (checkUniqueness) { - boolean existingURI = this.hasExistingURI(uriStr); - if(existingURI) { - errorMsg+="Not a valid URI. Please enter another URI. "; - errorMsg+=duplicateMsg; - } - } - return (errorMsg.length()>0) ? errorMsg : null; - } - - - - //Check if URI already in use or not either as resource OR as property + public String checkURIForEditableEntity(String uriStr) { + String errorMessage = checkURIForValidity(uriStr); + if (errorMessage != null) { + return errorMessage; + } + + if(hasEditableEntity(uriStr)) { + return "URI is already in use. Please enter another URI. "; + } + + return null; + } + + private String checkURIForValidity(String uriStr) { + uriStr = (uriStr == null) ? " " : uriStr; + + IRI iri = IRIFactory.jenaImplementation().create(uriStr); + if (iri.hasViolation(false)) { + return (iri.violations(false).next()).getShortMessage() + " "; + } + + try { + Resource res = ResourceFactory.createResource(uriStr); + if (res.getLocalName().matches("\\d+")) { + return "Localname must contain at least one non-numeric " + + "character. Please enter another URI. "; + } + } catch (Exception e) { + return "Not a valid URI. Please enter another URI. "; + } + + return null; + } + + //Check if URI already in use or not either as resource OR as property @Override public boolean hasExistingURI(String uriStr) { OntModel ontModel = ontModelSelector.getFullModel(); return URIUtils.hasExistingURI(uriStr, ontModel); } + private boolean hasEditableEntity(String uriStr) { + OntModel ontModel = ontModelSelector.getFullModel(); + return URIUtils.hasEditableEntity(uriStr, ontModel); + } + @Override public WebappDaoFactory getUserAwareDaoFactory(String userURI) { return new WebappDaoFactoryJena(this, userURI); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/URIUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/URIUtils.java index 9628c661a..4c890a64e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/URIUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/URIUtils.java @@ -2,59 +2,67 @@ package edu.cornell.mannlib.vitro.webapp.utils.jena; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import static com.hp.hpl.jena.rdf.model.ResourceFactory.createProperty; +import static com.hp.hpl.jena.rdf.model.ResourceFactory.createResource; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; -import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.shared.Lock; +import com.hp.hpl.jena.vocabulary.OWL; +import com.hp.hpl.jena.vocabulary.RDF; public class URIUtils { - - private static final Log log = LogFactory.getLog(URIUtils.class.getName()); - - public static boolean hasExistingURI(String uriStr, OntModel ontModel) { - boolean existingURI = false; - ontModel.enterCriticalSection(Lock.READ); - try { - boolean validPropertyURI = true; - String localName = uriStr.substring(uriStr.lastIndexOf("/") + 1); - //if local name is only numbers, this is not a valid uri for a property - if(localName.matches("\\d+")) { - validPropertyURI = false; - } - Resource newURIAsRes = ResourceFactory.createResource(uriStr); - - StmtIterator closeIt = ontModel.listStatements( - newURIAsRes, null, (RDFNode)null); - if (closeIt.hasNext()) { - existingURI = true; - - } - //if not in the subject position, check in object position - if (!existingURI) { - closeIt = ontModel.listStatements(null, null, newURIAsRes); - if (closeIt.hasNext()) { - existingURI= true; - } - } - //Check for property - if (validPropertyURI && !existingURI) { - Property newURIAsProp = ResourceFactory.createProperty(uriStr); - closeIt = ontModel.listStatements( - null, newURIAsProp, (RDFNode)null); - if (closeIt.hasNext()) { - existingURI = true; - } - } - } finally { - ontModel.leaveCriticalSection(); + public static boolean hasExistingURI(String uriStr, OntModel ontModel) { + ontModel.enterCriticalSection(Lock.READ); + try { + if (anyStatements(ontModel, createResource(uriStr), null, null)) { + return true; } - - return existingURI; - } + if (anyStatements(ontModel, null, createProperty(uriStr), null)) { + return true; + } + if (anyStatements(ontModel, null, null, createResource(uriStr))) { + return true; + } + return false; + } finally { + ontModel.leaveCriticalSection(); + } + } + + public static boolean hasEditableEntity(String uriStr, OntModel ontModel) { + ontModel.enterCriticalSection(Lock.READ); + try { + Resource res = createResource(uriStr); + if (anyStatements(ontModel, res, RDF.type, OWL.Thing)) { + return true; + } + if (anyStatements(ontModel, res, RDF.type, OWL.Class)) { + return true; + } + if (anyStatements(ontModel, res, RDF.type, OWL.DatatypeProperty)) { + return true; + } + if (anyStatements(ontModel, res, RDF.type, OWL.ObjectProperty)) { + return true; + } + return false; + } finally { + ontModel.leaveCriticalSection(); + } + } + + private static boolean anyStatements(OntModel m, Resource s, Property p, + RDFNode o) { + StmtIterator stmts = m.listStatements(s, p, o); + try { + return stmts.hasNext(); + } finally { + stmts.close(); + } + } + } diff --git a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryStub.java b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryStub.java index a5ecbac35..6f6653bfb 100644 --- a/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryStub.java +++ b/webapp/test/stubs/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactoryStub.java @@ -71,10 +71,11 @@ public class WebappDaoFactoryStub implements WebappDaoFactory { this.objectPropertyDao = objectPropertyDao; } - public void setObjectPropertyStatementDao(ObjectPropertyStatementDao objectPropertyStatementDao) { + public void setObjectPropertyStatementDao( + ObjectPropertyStatementDao objectPropertyStatementDao) { this.objectPropertyStatementDao = objectPropertyStatementDao; } - + public void setFauxPropertyDao(FauxPropertyDao fauxPropertyDao) { this.fauxPropertyDao = fauxPropertyDao; } @@ -86,7 +87,7 @@ public class WebappDaoFactoryStub implements WebappDaoFactory { public void setUserAccountsDao(UserAccountsDao userAccountsDao) { this.userAccountsDao = userAccountsDao; } - + public void setVClassDao(VClassDao vClassDao) { this.vClassDao = vClassDao; } @@ -161,11 +162,11 @@ public class WebappDaoFactoryStub implements WebappDaoFactory { } @Override - public String checkURI(String uriStr, boolean checkUniqueness) { + public String checkURIForEditableEntity(String uriStr) { throw new RuntimeException( - "WebappDaoFactory.checkURI() not implemented."); + "WebappDaoFactory.checkURIForNewEditableEntity() not implemented."); } - + @Override public boolean hasExistingURI(String uriStr) { throw new RuntimeException(