NIHVIVO-215
This commit is contained in:
parent
ae7b5b9835
commit
174ca4dbcb
2 changed files with 170 additions and 48 deletions
|
@ -10,14 +10,12 @@ import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
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.AllValuesFromRestriction;
|
import com.hp.hpl.jena.ontology.AllValuesFromRestriction;
|
||||||
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||||
import com.hp.hpl.jena.ontology.OntClass;
|
|
||||||
import com.hp.hpl.jena.ontology.OntModel;
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
import com.hp.hpl.jena.ontology.OntProperty;
|
import com.hp.hpl.jena.ontology.OntProperty;
|
||||||
import com.hp.hpl.jena.ontology.OntResource;
|
import com.hp.hpl.jena.ontology.OntResource;
|
||||||
|
@ -575,26 +573,12 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
||||||
ontModel.enterCriticalSection(Lock.WRITE);
|
ontModel.enterCriticalSection(Lock.WRITE);
|
||||||
try {
|
try {
|
||||||
com.hp.hpl.jena.ontology.DatatypeProperty jDataprop = ontModel.getDatatypeProperty(dtp.getURI());
|
com.hp.hpl.jena.ontology.DatatypeProperty jDataprop = ontModel.getDatatypeProperty(dtp.getURI());
|
||||||
if (dtp.getPublicName() == null || dtp.getPublicName().length() == 0) {
|
|
||||||
jDataprop.removeAll(RDFS.label);
|
updateRDFSLabel(jDataprop, dtp.getPublicName());
|
||||||
} else {
|
|
||||||
jDataprop.setLabel(dtp.getPublicName(), (String) getDefaultLanguage());
|
updatePropertyResourceURIValue(jDataprop, RDFS.domain,dtp.getDomainClassURI(),ontModel);
|
||||||
}
|
updatePropertyResourceURIValue(jDataprop, RDFS.range,dtp.getRangeDatatypeURI(),ontModel);
|
||||||
Resource domainRes = null;
|
|
||||||
if ( (dtp.getDomainClassURI() != null) && (dtp.getDomainClassURI().length()>0) ) {
|
|
||||||
domainRes = ontModel.getResource(dtp.getDomainClassURI());
|
|
||||||
}
|
|
||||||
jDataprop.removeAll(RDFS.domain);
|
|
||||||
if (domainRes != null) {
|
|
||||||
jDataprop.setDomain(domainRes);
|
|
||||||
}
|
|
||||||
if (dtp.getRangeDatatypeURI() != null && !dtp.getRangeDatatypeURI().equals("")) {
|
|
||||||
Resource rangeResource = ontModel.getResource(dtp.getRangeDatatypeURI());
|
|
||||||
if (rangeResource != null)
|
|
||||||
jDataprop.setRange(rangeResource);
|
|
||||||
} else {
|
|
||||||
jDataprop.removeAll(RDFS.range);
|
|
||||||
}
|
|
||||||
if (dtp.getFunctional()) {
|
if (dtp.getFunctional()) {
|
||||||
if (!ontModel.contains(jDataprop,RDF.type,OWL.FunctionalProperty)) {
|
if (!ontModel.contains(jDataprop,RDF.type,OWL.FunctionalProperty)) {
|
||||||
ontModel.add(jDataprop,RDF.type,OWL.FunctionalProperty);
|
ontModel.add(jDataprop,RDF.type,OWL.FunctionalProperty);
|
||||||
|
@ -604,37 +588,25 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements
|
||||||
ontModel.remove(jDataprop,RDF.type,OWL.FunctionalProperty);
|
ontModel.remove(jDataprop,RDF.type,OWL.FunctionalProperty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updatePropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel);
|
updatePropertyStringValue(jDataprop, EXAMPLE, dtp.getExample(), ontModel);
|
||||||
updatePropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel);
|
updatePropertyStringValue(jDataprop, DESCRIPTION_ANNOT, dtp.getDescription(), ontModel);
|
||||||
updatePropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel);
|
updatePropertyStringValue(jDataprop, PUBLIC_DESCRIPTION_ANNOT, dtp.getPublicDescription(), ontModel);
|
||||||
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
|
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_RANK_ANNOT, dtp.getDisplayTier(), ontModel);
|
||||||
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);
|
updatePropertyNonNegativeIntValue(jDataprop, DISPLAY_LIMIT, dtp.getDisplayLimit(), ontModel);
|
||||||
//updatePropertyStringValue(jDataprop, HIDDEN_ANNOT, dtp.getHidden(), ontModel);
|
|
||||||
jDataprop.removeAll(HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT);
|
if (dtp.getHiddenFromDisplayBelowRoleLevel() != null) {
|
||||||
if (HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT != null && dtp.getHiddenFromDisplayBelowRoleLevel() != null) { // only need to add if present
|
updatePropertyResourceURIValue(jDataprop,HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT,dtp.getHiddenFromDisplayBelowRoleLevel().getURI(),ontModel);
|
||||||
jDataprop.addProperty(HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT, ResourceFactory.createResource(dtp.getHiddenFromDisplayBelowRoleLevel().getURI()));
|
}
|
||||||
}
|
|
||||||
jDataprop.removeAll(PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT);
|
if (dtp.getProhibitedFromUpdateBelowRoleLevel() != null) {
|
||||||
if (PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT != null && dtp.getProhibitedFromUpdateBelowRoleLevel() != null) { // only need to add if present
|
updatePropertyResourceURIValue(jDataprop,PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT,dtp.getProhibitedFromUpdateBelowRoleLevel().getURI(),ontModel);
|
||||||
jDataprop.addProperty(PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT, ResourceFactory.createResource(dtp.getProhibitedFromUpdateBelowRoleLevel().getURI()));
|
}
|
||||||
}
|
|
||||||
/*
|
if (dtp.getGroupURI() != null) {
|
||||||
updatePropertyBooleanValue(jDataprop, PROPERTY_SELFEDITPROHIBITEDANNOT, dtp.isSelfEditProhibited(), ontModel, JenaBaseDao.KEEP_ONLY_IF_TRUE);
|
updatePropertyResourceURIValue(jDataprop,PROPERTY_INPROPERTYGROUPANNOT,dtp.getGroupURI(),ontModel);
|
||||||
updatePropertyBooleanValue(jDataprop, PROPERTY_CURATOREDITPROHIBITEDANNOT, dtp.isCuratorEditProhibited(), ontModel, JenaBaseDao.KEEP_ONLY_IF_TRUE);
|
}
|
||||||
*/
|
|
||||||
try {
|
|
||||||
jDataprop.removeAll(PROPERTY_INPROPERTYGROUPANNOT);
|
|
||||||
if (dtp.getGroupURI() != null && dtp.getGroupURI().length()>0) {
|
|
||||||
String badURIErrorStr = checkURI(dtp.getGroupURI());
|
|
||||||
if (badURIErrorStr == null) {
|
|
||||||
jDataprop.addProperty(PROPERTY_INPROPERTYGROUPANNOT, ontModel.getResource(dtp.getGroupURI()));
|
|
||||||
} else {
|
|
||||||
log.error(badURIErrorStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("error linking data property "+dtp.getURI()+" to property group");
|
|
||||||
}
|
|
||||||
updatePropertyStringValue(jDataprop,PROPERTY_CUSTOMENTRYFORMANNOT,dtp.getCustomEntryForm(),ontModel);
|
updatePropertyStringValue(jDataprop,PROPERTY_CUSTOMENTRYFORMANNOT,dtp.getCustomEntryForm(),ontModel);
|
||||||
} finally {
|
} finally {
|
||||||
ontModel.leaveCriticalSection();
|
ontModel.leaveCriticalSection();
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.dao.jena;
|
||||||
|
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import com.hp.hpl.jena.ontology.DatatypeProperty;
|
||||||
|
import com.hp.hpl.jena.ontology.OntModel;
|
||||||
|
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||||
|
import com.hp.hpl.jena.rdf.model.Model;
|
||||||
|
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||||
|
import com.hp.hpl.jena.vocabulary.OWL;
|
||||||
|
import com.hp.hpl.jena.vocabulary.RDF;
|
||||||
|
import com.hp.hpl.jena.vocabulary.RDFS;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.beans.DataProperty;
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DataPropertyDaoJenaTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// Test that the DataPropertyDaoJena::updateDataProperty method will only update the jena model for
|
||||||
|
// those properties in DataProperty that have a different value from what is already in the
|
||||||
|
// jena model for that property.
|
||||||
|
//
|
||||||
|
// Specifically, updateDataProperty method should not remove a statement from the model and
|
||||||
|
// then add the same statement back in. The reason for this is that in vitro the "immutable" properties
|
||||||
|
// are stored in a sub-model and the user-editable properties are stored in a super-model and
|
||||||
|
// all updates are performed against the super-model, so removing and then re-adding
|
||||||
|
// the same statement may result in a change of state (if the statement was in the sub-model
|
||||||
|
// it will migrate to the super-model) because of the way jena handles additions and
|
||||||
|
// deletions with respect to super and sub models. This migration of statements may cause
|
||||||
|
// undesirable behavior in the vitro application.
|
||||||
|
|
||||||
|
public void minimalUpdates(){
|
||||||
|
|
||||||
|
// 1. create two models and attach one as a sub-model of the other
|
||||||
|
// 2. populate the sub-model with one statement for each of the 13 properties represented in DataProperty
|
||||||
|
// 3. save the state of both the sub-model and the super-model
|
||||||
|
// 4. populate a DataProperty object with the data in the (combined) model and call the updateDataProperty
|
||||||
|
// (having made no changes to the DataProperty object)
|
||||||
|
// 5. verify that both the sub-model and the super-model are unchanged
|
||||||
|
|
||||||
|
String propertyURI = "http://vivoweb.org/ontology/core#addressCity";
|
||||||
|
|
||||||
|
OntModel superModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // this simulates the user-editable ontology in vivo
|
||||||
|
OntModel subModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM); // this simulates the core ontology in vivo
|
||||||
|
superModel.addSubModel(subModel);
|
||||||
|
|
||||||
|
String rdfsLabel = "this is the rdfs label";
|
||||||
|
String lang = "en-US";
|
||||||
|
|
||||||
|
// populate sub-model
|
||||||
|
DatatypeProperty property1 = subModel.createDatatypeProperty(propertyURI);
|
||||||
|
|
||||||
|
property1.setLabel(rdfsLabel,lang);
|
||||||
|
property1.setPropertyValue(RDFS.domain, subModel.createResource("http://thisIsTheDomainClassURI"));
|
||||||
|
property1.setPropertyValue(RDFS.range, subModel.createResource("http://thisIsTheRangeClassURI"));
|
||||||
|
property1.addProperty(RDF.type, OWL.FunctionalProperty);
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.EXAMPLE_ANNOT), subModel.createTypedLiteral("this is the example"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.DESCRIPTION_ANNOT), subModel.createTypedLiteral("this is the description"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.PUBLIC_DESCRIPTION_ANNOT), subModel.createTypedLiteral("this is the public description"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.DISPLAY_RANK_ANNOT), subModel.createTypedLiteral(21));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.DISPLAY_LIMIT), subModel.createTypedLiteral(5));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.HIDDEN_FROM_DISPLAY_BELOW_ROLE_LEVEL_ANNOT), subModel.createResource("http://vitro.mannlib.cornell.edu/ns/vitro/role#curator"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.PROHIBITED_FROM_UPDATE_BELOW_ROLE_LEVEL_ANNOT), subModel.createResource("http://vitro.mannlib.cornell.edu/ns/vitro/role#selfEditor"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.PROPERTY_INPROPERTYGROUPANNOT), subModel.createResource("http://thisIsTheInPropertyGroupURI"));
|
||||||
|
property1.setPropertyValue(subModel.createProperty(VitroVocabulary.PROPERTY_CUSTOMENTRYFORMANNOT), subModel.createResource("http://thisIsTheCustomFormEntryURI"));
|
||||||
|
|
||||||
|
// Save copies of sub-model and super-model
|
||||||
|
|
||||||
|
// uncommment the next two lines to debug failures
|
||||||
|
//System.out.println("**Before updating data property:");
|
||||||
|
//printModels(superModel, subModel);
|
||||||
|
|
||||||
|
superModel.removeSubModel(subModel);
|
||||||
|
|
||||||
|
OntModel origSubModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||||
|
origSubModel.add(subModel);
|
||||||
|
OntModel origSuperModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM);
|
||||||
|
origSuperModel.add(superModel);
|
||||||
|
|
||||||
|
superModel.addSubModel(subModel);
|
||||||
|
|
||||||
|
// Populate the DataProperty with the data in the sub-model and then update the combined model
|
||||||
|
// (from the unchanged object).
|
||||||
|
WebappDaoFactoryJena wdfj = new WebappDaoFactoryJena(superModel);
|
||||||
|
DataPropertyDaoJena dpdj = (DataPropertyDaoJena) wdfj.getDataPropertyDao();
|
||||||
|
DataProperty dataProperty = dpdj.getDataPropertyByURI(propertyURI); // the DataProperty will be populated
|
||||||
|
// with the information already in
|
||||||
|
// the jena model.
|
||||||
|
|
||||||
|
|
||||||
|
Assert.assertEquals(dataProperty.getPublicName(), property1.getLabel(lang));
|
||||||
|
|
||||||
|
dpdj.updateDataProperty(dataProperty); // we haven't changed any values here, so
|
||||||
|
// the models should be unchanged.
|
||||||
|
|
||||||
|
// Verify that the sub-model and super-model are both unchanged
|
||||||
|
|
||||||
|
// uncommment the next two lines to debug failures
|
||||||
|
//System.out.println("\n**After updating data property:");
|
||||||
|
//printModels(superModel,subModel);
|
||||||
|
|
||||||
|
superModel.removeSubModel(subModel);
|
||||||
|
|
||||||
|
//modtime affects the diff but we don't care about that difference
|
||||||
|
wipeOutModTime(origSubModel);
|
||||||
|
wipeOutModTime(origSuperModel);
|
||||||
|
wipeOutModTime(subModel);
|
||||||
|
wipeOutModTime(superModel);
|
||||||
|
|
||||||
|
Assert.assertTrue(subModel.isIsomorphicWith(origSubModel));
|
||||||
|
Assert.assertTrue(superModel.isIsomorphicWith(origSuperModel));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void printModels(OntModel superModel, OntModel subModel) {
|
||||||
|
|
||||||
|
// Detach the submodel for printing to get an accurate
|
||||||
|
// account of what is in each.
|
||||||
|
|
||||||
|
superModel.removeSubModel(subModel);
|
||||||
|
|
||||||
|
System.out.println("\nThe sub-model has " + subModel.size() + " statements:");
|
||||||
|
System.out.println("---------------------------------------------------");
|
||||||
|
subModel.writeAll(System.out,"N3",null);
|
||||||
|
|
||||||
|
System.out.println("\nThe super-model has " + superModel.size() + " statements:");
|
||||||
|
System.out.println("---------------------------------------------------");
|
||||||
|
superModel.write(System.out,"N3",null);
|
||||||
|
|
||||||
|
superModel.addSubModel(subModel);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void wipeOutModTime(Model model){
|
||||||
|
model.removeAll(null, model.createProperty(VitroVocabulary.MODTIME), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue