This commit is contained in:
sjm222 2010-12-27 00:48:09 +00:00
parent 5e3f106f72
commit 85db1c3ba0
5 changed files with 231 additions and 63 deletions

View file

@ -39,9 +39,7 @@ public class ABoxUpdater {
private OntModel newTBoxAnnotationsModel; private OntModel newTBoxAnnotationsModel;
private OntologyChangeLogger logger; private OntologyChangeLogger logger;
private OntologyChangeRecord record; private OntologyChangeRecord record;
private OntClass OWL_THING = (ModelFactory private OntClass OWL_THING = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createClass(OWL.Thing.getURI());
.createOntologyModel(OntModelSpec.OWL_MEM))
.createClass(OWL.Thing.getURI());
/** /**
* *
@ -311,7 +309,7 @@ public class ABoxUpdater {
namedClassList.add(ontClass); namedClassList.add(ontClass);
} }
} }
OntClass parent = (namedClassList.isEmpty()) OntClass parent = (!namedClassList.isEmpty())
? namedClassList.get(0) ? namedClassList.get(0)
: OWL_THING; : OWL_THING;
@ -323,10 +321,9 @@ public class ABoxUpdater {
} }
//log summary of changes //log summary of changes
//logger.log("Class " + deletedClass.getURI() + " has been deleted. Any references to it in the knowledge base will be changed to " + logger.log("Class " + deletedClass.getURI() + " has been deleted. Any references to it in the knowledge base will be changed to " + replacementClass.getURI());
// replacementClass.getURI());
AtomicOntologyChange chg = new AtomicOntologyChange(deletedClass.getURI(), replacementClass.getURI(), AtomicChangeType.RENAME); AtomicOntologyChange chg = new AtomicOntologyChange(deletedClass.getURI(), replacementClass.getURI(), AtomicChangeType.RENAME, change.getNotes());
renameClass(chg); renameClass(chg);
} }
@ -349,18 +346,59 @@ public class ABoxUpdater {
} }
private void addProperty(AtomicOntologyChange propObj) throws IOException{ private void addProperty(AtomicOntologyChange propObj) throws IOException{
OntProperty tempProperty = newTboxModel.getOntProperty OntProperty addedProperty = newTboxModel.getOntProperty (propObj.getDestinationURI());
(propObj.getDestinationURI());
if (tempProperty == null) { if (addedProperty == null) {
logger.logError("Unable to find property " + logger.logError("Unable to find property " + propObj.getDestinationURI() + " in new TBox");
propObj.getDestinationURI() +
" in newTBoxModel");
return; return;
} }
OntProperty superProperty = tempProperty.getSuperProperty();
// if the newly added property has an inverse in the new TBox, then for all existing
// ABox statements involving that inverse (if the inverse is new also there won't be
// any) add the corresponding statement with the new property.
//
// Shouldn't a reasoner be doing this?
OntProperty inverseOfAddedProperty = addedProperty.getInverseOf();
if (inverseOfAddedProperty != null) {
Model additions = ModelFactory.createDefaultModel();
aboxModel.enterCriticalSection(Lock.WRITE);
try {
StmtIterator iter = aboxModel.listStatements((Resource) null, inverseOfAddedProperty, (RDFNode) null);
while (iter.hasNext()) {
Statement stmt = iter.next();
Statement newStmt = ResourceFactory.createStatement(stmt.getObject().asResource(), addedProperty, stmt.getSubject());
additions.add(newStmt);
}
aboxModel.add(additions);
record.recordAdditions(additions);
if (additions.size() > 0) {
logger.log(additions.size() + " statement" +
((additions.size() > 1) ? "s" : "") +
" with predicate " + addedProperty.getURI() + " " +
((additions.size() > 1) ? "were" : "was")
+ " added (as an inverse to existing " + inverseOfAddedProperty.getURI() +
" assertions");
}
} finally {
aboxModel.leaveCriticalSection();
}
}
/* OntProperty superProperty = addedProperty.getSuperProperty();
if (superProperty == null) { if (superProperty == null) {
return; return;
} }
int count = aboxModel.listStatements( int count = aboxModel.listStatements(
(Resource) null, superProperty, (RDFNode) null).toSet().size(); (Resource) null, superProperty, (RDFNode) null).toSet().size();
if (count > 0) { if (count > 0) {
@ -369,7 +407,7 @@ public class ABoxUpdater {
"a new subproperty " + propObj.getDestinationURI() + "a new subproperty " + propObj.getDestinationURI() +
" in the new ontology version. "); " in the new ontology version. ");
logger.log("Please review uses of this property to see if " + propObj.getDestinationURI() + " is a more appropriate choice."); logger.log("Please review uses of this property to see if " + propObj.getDestinationURI() + " is a more appropriate choice.");
} }*/
} }
private void deleteProperty(AtomicOntologyChange propObj) throws IOException{ private void deleteProperty(AtomicOntologyChange propObj) throws IOException{
@ -413,7 +451,7 @@ public class ABoxUpdater {
propObj.getSourceURI() + " " + (plural ? "were" : "was") + " removed. "); propObj.getSourceURI() + " " + (plural ? "were" : "was") + " removed. ");
} }
} else { } else {
AtomicOntologyChange chg = new AtomicOntologyChange(deletedProperty.getURI(), replacementProperty.getURI(), AtomicChangeType.RENAME); AtomicOntologyChange chg = new AtomicOntologyChange(deletedProperty.getURI(), replacementProperty.getURI(), AtomicChangeType.RENAME, propObj.getNotes());
renameProperty(chg); renameProperty(chg);
} }
@ -435,8 +473,7 @@ public class ABoxUpdater {
} }
Model renamePropAddModel = ModelFactory.createDefaultModel(); Model renamePropAddModel = ModelFactory.createDefaultModel();
Model renamePropRetractModel = Model renamePropRetractModel = ModelFactory.createDefaultModel();
ModelFactory.createDefaultModel();
aboxModel.enterCriticalSection(Lock.WRITE); aboxModel.enterCriticalSection(Lock.WRITE);
try { try {

View file

@ -13,6 +13,7 @@ public class AtomicOntologyChange {
private String sourceURI; private String sourceURI;
private String destinationURI; private String destinationURI;
private AtomicChangeType atomicChangeType; private AtomicChangeType atomicChangeType;
private String notes;
public AtomicOntologyChange() { public AtomicOntologyChange() {
@ -20,11 +21,13 @@ public class AtomicOntologyChange {
public AtomicOntologyChange(String sourceURI, public AtomicOntologyChange(String sourceURI,
String destinationURI, String destinationURI,
AtomicChangeType atomicChangeType) { AtomicChangeType atomicChangeType,
String notes) {
this.sourceURI = sourceURI; this.sourceURI = sourceURI;
this.destinationURI = destinationURI; this.destinationURI = destinationURI;
this.atomicChangeType = atomicChangeType; this.atomicChangeType = atomicChangeType;
this.notes = notes;
} }
@ -63,9 +66,17 @@ public class AtomicOntologyChange {
public void setAtomicChangeType(AtomicChangeType atomicChangeType) { public void setAtomicChangeType(AtomicChangeType atomicChangeType) {
this.atomicChangeType = atomicChangeType; this.atomicChangeType = atomicChangeType;
} }
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public enum AtomicChangeType { public enum AtomicChangeType {
ADD, DELETE, RENAME ADD, DELETE, RENAME
} }
} }

View file

@ -2,9 +2,26 @@
package edu.cornell.mannlib.vitro.webapp.ontology.update; package edu.cornell.mannlib.vitro.webapp.ontology.update;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import com.hp.hpl.jena.datatypes.xsd.XSDDateTime;
import com.hp.hpl.jena.ontology.DatatypeProperty;
import com.hp.hpl.jena.ontology.ObjectProperty;
import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.ontology.OntModelSpec;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory; 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.rdf.model.Statement;
import com.hp.hpl.jena.rdf.model.StmtIterator;
import com.hp.hpl.jena.shared.Lock; import com.hp.hpl.jena.shared.Lock;
/** /**
@ -17,7 +34,19 @@ public class DateTimeMigration {
private OntModel aboxModel; private OntModel aboxModel;
private OntologyChangeLogger logger; private OntologyChangeLogger logger;
private OntologyChangeRecord record; private OntologyChangeRecord record;
private static final String dateTimeURI = "http://vivoweb.org/ontology/core#dateTime";
private static final String dateTimePrecisionURI = "http://vivoweb.org/ontology/core#dateTimePrecision";
private static final String yPrecisionURI = "http://vivoweb.org/ontology/core#yearPrecision";
private static final String ymPrecisionURI = "http://vivoweb.org/ontology/core#yearMonthPrecision";
private static final String ymdPrecisionURI = "http://vivoweb.org/ontology/core#yearMonthDayPrecision";
private static final String ymdtPrecisionURI = "http://vivoweb.org/ontology/core#yearMonthDayTimePrecision";
private DatatypeProperty dateTimeProp = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createDatatypeProperty(dateTimeURI);
private ObjectProperty dateTimePrecisionProp = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createObjectProperty(dateTimePrecisionURI);
/** /**
* Constructor * Constructor
* *
@ -40,24 +69,110 @@ public class DateTimeMigration {
* and property definitions in the transition from version 1.1 to 1.2. * and property definitions in the transition from version 1.1 to 1.2.
* *
*/ */
public void updateABox() { public void updateABox() throws IOException {
// note: not handling timezones - they are not expected to be in the 1.1.1 data
DateFormat yearFormat = new SimpleDateFormat("yyyy");
DateFormat yearMonthFormat = new SimpleDateFormat("yyyy-mm");
DateFormat yearMonthDayFormat = new SimpleDateFormat("yyyy-mm-dd");
aboxModel.enterCriticalSection(Lock.WRITE);
try {
Model additions = ModelFactory.createDefaultModel();
Model retractions = ModelFactory.createDefaultModel();
StmtIterator iter = aboxModel.listStatements((Resource) null, dateTimeProp, (RDFNode) null);
while (iter.hasNext()) {
Statement newStmt = null;
Date date = null;
Statement stmt = iter.next();
String precision = getPrecision(stmt);
if (precision == null) {
logger.log("WARNING: no precision found for individual " + stmt.getSubject().getURI() );
} else if (yPrecisionURI.equals(precision)) {
try {
date = yearFormat.parse(stmt.getObject().asLiteral().getLexicalForm());
} catch (ParseException pe) {
logger.log("Parse Exception for year literal: " + stmt.getObject().asLiteral().getLexicalForm() + ". skipping statement.");
}
newStmt = ResourceFactory.createStatement(stmt.getSubject(), stmt.getPredicate(), getDateTimeLiteral(date) );
} else if (ymPrecisionURI.equals(precision)) {
try {
date = yearMonthFormat.parse(stmt.getObject().asLiteral().getLexicalForm());
} catch (ParseException pe) {
logger.log("Parse Exception for year literal: " + stmt.getObject().asLiteral().getLexicalForm() + ". skipping statement.");
}
newStmt = ResourceFactory.createStatement(stmt.getSubject(), stmt.getPredicate(), getDateTimeLiteral(date) );
} else if (ymdPrecisionURI.equals(precision)) {
try {
date = yearMonthDayFormat.parse(stmt.getObject().asLiteral().getLexicalForm());
} catch (ParseException pe) {
logger.log("Parse Exception for year literal: " + stmt.getObject().asLiteral().getLexicalForm() + ". skipping statement.");
}
newStmt = ResourceFactory.createStatement(stmt.getSubject(), stmt.getPredicate(), getDateTimeLiteral(date) );
} else if (ymdtPrecisionURI.equals(precision)) {
logger.log("WARNING: unhandled precision found for individual " + stmt.getSubject().getURI() + ": " + precision );
} else {
logger.log("WARNING: unrecognized precision found for individual " + stmt.getSubject().getURI() + ": " + precision );
}
if (newStmt != null ) {
additions.add(newStmt);
retractions.add(stmt);
}
}
aboxModel.remove(retractions);
record.recordRetractions(retractions);
aboxModel.add(additions);
record.recordAdditions(additions);
} finally {
aboxModel.leaveCriticalSection();
}
}
public String getPrecision(Statement stmt) {
String precision = null;
aboxModel.enterCriticalSection(Lock.WRITE); aboxModel.enterCriticalSection(Lock.WRITE);
try { try {
Model additions = ModelFactory.createDefaultModel();
Model retractions = ModelFactory.createDefaultModel();
StmtIterator iter = aboxModel.listStatements(stmt.getSubject(), dateTimePrecisionProp, (RDFNode) null);
aboxModel.remove(retractions); while (iter.hasNext()) {
record.recordRetractions(retractions); Statement statement = iter.next();
aboxModel.add(additions); precision = ((Resource)statement.getObject()).getURI();
record.recordAdditions(additions); }
return precision;
} finally { } finally {
aboxModel.leaveCriticalSection(); aboxModel.leaveCriticalSection();
} }
} }
public static Literal getDateTimeLiteral(Date date) {
// Note this loses time zone info, don't know how get parser to extract that
//Calendar cal = Calendar.getInstance( TimeZone.getTimeZone("GMT") );
Calendar cal = Calendar.getInstance();
cal.setTime(date);
XSDDateTime dt = new XSDDateTime(cal);
return ResourceFactory.createTypedLiteral(dt);
}
} }

View file

@ -2,18 +2,17 @@
package edu.cornell.mannlib.vitro.webapp.ontology.update; package edu.cornell.mannlib.vitro.webapp.ontology.update;
import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange; import java.io.File;
import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange.AtomicChangeType; import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import org.skife.csv.CSVReader; import org.skife.csv.CSVReader;
import org.skife.csv.SimpleReader; import org.skife.csv.SimpleReader;
import java.io.FileInputStream; import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange.AtomicChangeType;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.StringTokenizer;
import java.util.ArrayList;
/** /**
* Performs parsing on Prompt output and provides change object list. * Performs parsing on Prompt output and provides change object list.
@ -61,12 +60,19 @@ public class OntologyChangeParser {
} else { } else {
changeObj = new AtomicOntologyChange(); changeObj = new AtomicOntologyChange();
if (cols[0] != null && cols[0].length() > 0) { if (cols[0] != null && cols[0].length() > 0) {
changeObj.setSourceURI(cols[0]); changeObj.setSourceURI(cols[0]);
} }
if (cols[1] != null && cols[1].length() > 0) { if (cols[1] != null && cols[1].length() > 0) {
changeObj.setDestinationURI(cols[1]); changeObj.setDestinationURI(cols[1]);
} }
if (cols[4] != null && cols[4].length() > 0) {
changeObj.setNotes(cols[4]);
}
if ("Yes".equals(cols[2])) { if ("Yes".equals(cols[2])) {
changeObj.setAtomicChangeType(AtomicChangeType.RENAME); changeObj.setAtomicChangeType(AtomicChangeType.RENAME);
} else if ("Delete".equals(cols[3])) { } else if ("Delete".equals(cols[3])) {
@ -77,6 +83,8 @@ public class OntologyChangeParser {
logger.logError("Invalid rename or change type data: '" + logger.logError("Invalid rename or change type data: '" +
cols[2] + " " + cols[3] + "'"); cols[2] + " " + cols[3] + "'");
} }
changeObjects.add(changeObj); changeObjects.add(changeObj);
} }

View file

@ -65,7 +65,6 @@ public class OntologyUpdater {
if (!logger.errorsWritten()) { if (!logger.errorsWritten()) {
// add assertions to the knowledge base showing that the // add assertions to the knowledge base showing that the
// update was successful, so we don't need to run it again. // update was successful, so we don't need to run it again.
// TODO improve error handling in future version.
assertSuccess(); assertSuccess();
} }
@ -80,19 +79,19 @@ public class OntologyUpdater {
private void performUpdate() throws IOException { private void performUpdate() throws IOException {
DateTimeMigration dtMigration = new DateTimeMigration(settings.getOntModelSelector().getABoxModel(), logger, record);
dtMigration.updateABox();
performSparqlConstructAdditions(settings.getSparqlConstructAdditionsDir(), settings.getOntModelSelector().getABoxModel()); performSparqlConstructAdditions(settings.getSparqlConstructAdditionsDir(), settings.getOntModelSelector().getABoxModel());
performSparqlConstructRetractions(settings.getSparqlConstructDeletionsDir(), settings.getOntModelSelector().getABoxModel()); performSparqlConstructRetractions(settings.getSparqlConstructDeletionsDir(), settings.getOntModelSelector().getABoxModel());
DateTimeMigration dtMigration = new DateTimeMigration(settings.getOntModelSelector().getABoxModel(), logger, record);
dtMigration.updateABox();
List<AtomicOntologyChange> rawChanges = getAtomicOntologyChanges(); List<AtomicOntologyChange> rawChanges = getAtomicOntologyChanges();
AtomicOntologyChangeLists changes = new AtomicOntologyChangeLists(rawChanges, AtomicOntologyChangeLists changes = new AtomicOntologyChangeLists(rawChanges,
settings.getNewTBoxModel(), settings.getNewTBoxModel(),
settings.getOldTBoxModel()); settings.getOldTBoxModel());
//process the TBox before the ABox //process the TBox before the ABox
updateTBoxAnnotations(); //TODO: uncomment updateTBoxAnnotations();
updateABox(changes); updateABox(changes);
@ -226,8 +225,7 @@ public class OntologyUpdater {
private List<AtomicOntologyChange> getAtomicOntologyChanges() private List<AtomicOntologyChange> getAtomicOntologyChanges()
throws IOException { throws IOException {
return (new OntologyChangeParser(logger)) return (new OntologyChangeParser(logger)).parseFile(settings.getDiffFile());
.parseFile(settings.getDiffFile());
} }
@ -339,18 +337,19 @@ public class OntologyUpdater {
if (changeObj.getSourceURI() != null){ if (changeObj.getSourceURI() != null){
if (oldTboxModel.getOntProperty(changeObj.getSourceURI()) != null){ if (oldTboxModel.getOntProperty(changeObj.getSourceURI()) != null){
atomicPropertyChanges.add(changeObj); atomicPropertyChanges.add(changeObj);
} } else if (oldTboxModel.getOntClass(changeObj.getSourceURI()) != null) {
else if (oldTboxModel.getOntClass(changeObj.getSourceURI()) != null) { atomicClassChanges.add(changeObj);
atomicClassChanges.add(changeObj); } else if ("Prop".equals(changeObj.getNotes())) {
} atomicPropertyChanges.add(changeObj);
else{ } else if ("Class".equals(changeObj.getNotes())) {
logger.logError("Source URI is neither a Property" + atomicClassChanges.add(changeObj);
" nor a Class. " + "Change Object skipped for sourceURI: " + changeObj.getSourceURI()); } else{
logger.log("WARNING: Source URI is neither a Property" +
" nor a Class. " + "Change Object skipped for sourceURI: " + changeObj.getSourceURI());
} }
} } else if(changeObj.getDestinationURI() != null){
else if(changeObj.getDestinationURI() != null){
if (newTboxModel.getOntProperty(changeObj.getDestinationURI()) != null) { if (newTboxModel.getOntProperty(changeObj.getDestinationURI()) != null) {
atomicPropertyChanges.add(changeObj); atomicPropertyChanges.add(changeObj);
@ -358,16 +357,14 @@ public class OntologyUpdater {
getDestinationURI()) != null) { getDestinationURI()) != null) {
atomicClassChanges.add(changeObj); atomicClassChanges.add(changeObj);
} else{ } else{
logger.logError("Destination URI is neither a Property" + logger.log("WARNING: Destination URI is neither a Property" +
" nor a Class. " + "Change Object skipped for destinationURI: " + changeObj.getDestinationURI()); " nor a Class. " + "Change Object skipped for destinationURI: " + changeObj.getDestinationURI());
} }
} } else{
else{ logger.log("WARNING: Source and Destination URI can't be null. " + "Change Object skipped" );
logger.logError("Source and Destination URI can't be null. "
+ "Change Object skipped" );
} }
} }
//logger.log("Property and Class change Object lists separated"); //logger.log("Property and Class change Object lists have been created");
} }
public List<AtomicOntologyChange> getAtomicClassChanges() { public List<AtomicOntologyChange> getAtomicClassChanges() {