VIVO-925 When creating class or properties, permit URIs that are already in use...
...as long as they aren't already declared as things, classes or properties
This commit is contained in:
parent
837d2afdad
commit
5c1944f508
8 changed files with 129 additions and 90 deletions
|
@ -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:
|
||||
|
|
|
@ -88,8 +88,9 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory {
|
|||
return innerWebappDaoFactory.checkURI(uriStr);
|
||||
}
|
||||
|
||||
public String checkURI(String uriStr, boolean checkUniqueness) {
|
||||
return innerWebappDaoFactory.checkURI(uriStr, checkUniqueness);
|
||||
@Override
|
||||
public String checkURIForEditableEntity(String uriStr) {
|
||||
return innerWebappDaoFactory.checkURIForEditableEntity(uriStr);
|
||||
}
|
||||
|
||||
public boolean hasExistingURI(String uriStr) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
@ -176,31 +178,52 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
|
||||
@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) {
|
||||
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;
|
||||
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;
|
||||
|
||||
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
|
||||
|
@ -209,6 +232,11 @@ public class WebappDaoFactoryJena implements WebappDaoFactory {
|
|||
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);
|
||||
|
|
|
@ -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;
|
||||
if (anyStatements(ontModel, createResource(uriStr), null, null)) {
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
if (anyStatements(ontModel, null, createProperty(uriStr), null)) {
|
||||
return true;
|
||||
}
|
||||
if (anyStatements(ontModel, null, null, createResource(uriStr))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} finally {
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
return existingURI;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -71,7 +71,8 @@ public class WebappDaoFactoryStub implements WebappDaoFactory {
|
|||
this.objectPropertyDao = objectPropertyDao;
|
||||
}
|
||||
|
||||
public void setObjectPropertyStatementDao(ObjectPropertyStatementDao objectPropertyStatementDao) {
|
||||
public void setObjectPropertyStatementDao(
|
||||
ObjectPropertyStatementDao objectPropertyStatementDao) {
|
||||
this.objectPropertyStatementDao = objectPropertyStatementDao;
|
||||
}
|
||||
|
||||
|
@ -161,9 +162,9 @@ 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
|
||||
|
|
Loading…
Add table
Reference in a new issue