This commit is contained in:
parent
5e3f106f72
commit
85db1c3ba0
5 changed files with 231 additions and 63 deletions
|
@ -39,9 +39,7 @@ public class ABoxUpdater {
|
|||
private OntModel newTBoxAnnotationsModel;
|
||||
private OntologyChangeLogger logger;
|
||||
private OntologyChangeRecord record;
|
||||
private OntClass OWL_THING = (ModelFactory
|
||||
.createOntologyModel(OntModelSpec.OWL_MEM))
|
||||
.createClass(OWL.Thing.getURI());
|
||||
private OntClass OWL_THING = (ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM)).createClass(OWL.Thing.getURI());
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -311,7 +309,7 @@ public class ABoxUpdater {
|
|||
namedClassList.add(ontClass);
|
||||
}
|
||||
}
|
||||
OntClass parent = (namedClassList.isEmpty())
|
||||
OntClass parent = (!namedClassList.isEmpty())
|
||||
? namedClassList.get(0)
|
||||
: OWL_THING;
|
||||
|
||||
|
@ -323,10 +321,9 @@ public class ABoxUpdater {
|
|||
}
|
||||
|
||||
//log summary of changes
|
||||
//logger.log("Class " + deletedClass.getURI() + " has been deleted. Any references to it in the knowledge base will be changed to " +
|
||||
// replacementClass.getURI());
|
||||
logger.log("Class " + deletedClass.getURI() + " has been deleted. Any references to it in the knowledge base will be changed to " + 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);
|
||||
}
|
||||
|
||||
|
@ -349,18 +346,59 @@ public class ABoxUpdater {
|
|||
}
|
||||
|
||||
private void addProperty(AtomicOntologyChange propObj) throws IOException{
|
||||
OntProperty tempProperty = newTboxModel.getOntProperty
|
||||
(propObj.getDestinationURI());
|
||||
if (tempProperty == null) {
|
||||
logger.logError("Unable to find property " +
|
||||
propObj.getDestinationURI() +
|
||||
" in newTBoxModel");
|
||||
OntProperty addedProperty = newTboxModel.getOntProperty (propObj.getDestinationURI());
|
||||
|
||||
if (addedProperty == null) {
|
||||
logger.logError("Unable to find property " + propObj.getDestinationURI() + " in new TBox");
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
int count = aboxModel.listStatements(
|
||||
(Resource) null, superProperty, (RDFNode) null).toSet().size();
|
||||
if (count > 0) {
|
||||
|
@ -369,7 +407,7 @@ public class ABoxUpdater {
|
|||
"a new subproperty " + propObj.getDestinationURI() +
|
||||
" in the new ontology version. ");
|
||||
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{
|
||||
|
@ -413,7 +451,7 @@ public class ABoxUpdater {
|
|||
propObj.getSourceURI() + " " + (plural ? "were" : "was") + " removed. ");
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
|
||||
|
@ -435,8 +473,7 @@ public class ABoxUpdater {
|
|||
}
|
||||
|
||||
Model renamePropAddModel = ModelFactory.createDefaultModel();
|
||||
Model renamePropRetractModel =
|
||||
ModelFactory.createDefaultModel();
|
||||
Model renamePropRetractModel = ModelFactory.createDefaultModel();
|
||||
|
||||
aboxModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
|
|
|
@ -13,6 +13,7 @@ public class AtomicOntologyChange {
|
|||
private String sourceURI;
|
||||
private String destinationURI;
|
||||
private AtomicChangeType atomicChangeType;
|
||||
private String notes;
|
||||
|
||||
public AtomicOntologyChange() {
|
||||
|
||||
|
@ -20,11 +21,13 @@ public class AtomicOntologyChange {
|
|||
|
||||
public AtomicOntologyChange(String sourceURI,
|
||||
String destinationURI,
|
||||
AtomicChangeType atomicChangeType) {
|
||||
AtomicChangeType atomicChangeType,
|
||||
String notes) {
|
||||
|
||||
this.sourceURI = sourceURI;
|
||||
this.destinationURI = destinationURI;
|
||||
this.atomicChangeType = atomicChangeType;
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,9 +66,17 @@ public class AtomicOntologyChange {
|
|||
public void setAtomicChangeType(AtomicChangeType atomicChangeType) {
|
||||
this.atomicChangeType = atomicChangeType;
|
||||
}
|
||||
|
||||
|
||||
public String getNotes() {
|
||||
return notes;
|
||||
}
|
||||
|
||||
public void setNotes(String notes) {
|
||||
this.notes = notes;
|
||||
}
|
||||
|
||||
public enum AtomicChangeType {
|
||||
ADD, DELETE, RENAME
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,26 @@
|
|||
|
||||
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.OntModelSpec;
|
||||
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.rdf.model.Statement;
|
||||
import com.hp.hpl.jena.rdf.model.StmtIterator;
|
||||
import com.hp.hpl.jena.shared.Lock;
|
||||
|
||||
/**
|
||||
|
@ -17,7 +34,19 @@ public class DateTimeMigration {
|
|||
private OntModel aboxModel;
|
||||
private OntologyChangeLogger logger;
|
||||
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
|
||||
*
|
||||
|
@ -40,24 +69,110 @@ public class DateTimeMigration {
|
|||
* 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);
|
||||
|
||||
try {
|
||||
|
||||
Model additions = ModelFactory.createDefaultModel();
|
||||
Model retractions = ModelFactory.createDefaultModel();
|
||||
|
||||
|
||||
|
||||
aboxModel.remove(retractions);
|
||||
record.recordRetractions(retractions);
|
||||
aboxModel.add(additions);
|
||||
record.recordAdditions(additions);
|
||||
StmtIterator iter = aboxModel.listStatements(stmt.getSubject(), dateTimePrecisionProp, (RDFNode) null);
|
||||
|
||||
while (iter.hasNext()) {
|
||||
Statement statement = iter.next();
|
||||
precision = ((Resource)statement.getObject()).getURI();
|
||||
}
|
||||
|
||||
return precision;
|
||||
|
||||
} finally {
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
|
@ -2,18 +2,17 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.ontology.update;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange;
|
||||
import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange.AtomicChangeType;
|
||||
import java.io.File;
|
||||
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.SimpleReader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.ArrayList;
|
||||
import edu.cornell.mannlib.vitro.webapp.ontology.update.AtomicOntologyChange.AtomicChangeType;
|
||||
|
||||
/**
|
||||
* Performs parsing on Prompt output and provides change object list.
|
||||
|
@ -61,12 +60,19 @@ public class OntologyChangeParser {
|
|||
} else {
|
||||
|
||||
changeObj = new AtomicOntologyChange();
|
||||
|
||||
if (cols[0] != null && cols[0].length() > 0) {
|
||||
changeObj.setSourceURI(cols[0]);
|
||||
}
|
||||
|
||||
if (cols[1] != null && cols[1].length() > 0) {
|
||||
changeObj.setDestinationURI(cols[1]);
|
||||
}
|
||||
|
||||
if (cols[4] != null && cols[4].length() > 0) {
|
||||
changeObj.setNotes(cols[4]);
|
||||
}
|
||||
|
||||
if ("Yes".equals(cols[2])) {
|
||||
changeObj.setAtomicChangeType(AtomicChangeType.RENAME);
|
||||
} else if ("Delete".equals(cols[3])) {
|
||||
|
@ -77,6 +83,8 @@ public class OntologyChangeParser {
|
|||
logger.logError("Invalid rename or change type data: '" +
|
||||
cols[2] + " " + cols[3] + "'");
|
||||
}
|
||||
|
||||
|
||||
changeObjects.add(changeObj);
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ public class OntologyUpdater {
|
|||
if (!logger.errorsWritten()) {
|
||||
// add assertions to the knowledge base showing that the
|
||||
// update was successful, so we don't need to run it again.
|
||||
// TODO improve error handling in future version.
|
||||
assertSuccess();
|
||||
}
|
||||
|
||||
|
@ -80,19 +79,19 @@ public class OntologyUpdater {
|
|||
|
||||
private void performUpdate() throws IOException {
|
||||
|
||||
DateTimeMigration dtMigration = new DateTimeMigration(settings.getOntModelSelector().getABoxModel(), logger, record);
|
||||
dtMigration.updateABox();
|
||||
|
||||
performSparqlConstructAdditions(settings.getSparqlConstructAdditionsDir(), settings.getOntModelSelector().getABoxModel());
|
||||
performSparqlConstructRetractions(settings.getSparqlConstructDeletionsDir(), settings.getOntModelSelector().getABoxModel());
|
||||
|
||||
|
||||
DateTimeMigration dtMigration = new DateTimeMigration(settings.getOntModelSelector().getABoxModel(), logger, record);
|
||||
dtMigration.updateABox();
|
||||
|
||||
List<AtomicOntologyChange> rawChanges = getAtomicOntologyChanges();
|
||||
|
||||
AtomicOntologyChangeLists changes = new AtomicOntologyChangeLists(rawChanges,
|
||||
settings.getNewTBoxModel(),
|
||||
settings.getOldTBoxModel());
|
||||
//process the TBox before the ABox
|
||||
updateTBoxAnnotations();
|
||||
//TODO: uncomment updateTBoxAnnotations();
|
||||
|
||||
updateABox(changes);
|
||||
|
||||
|
@ -226,8 +225,7 @@ public class OntologyUpdater {
|
|||
|
||||
private List<AtomicOntologyChange> getAtomicOntologyChanges()
|
||||
throws IOException {
|
||||
return (new OntologyChangeParser(logger))
|
||||
.parseFile(settings.getDiffFile());
|
||||
return (new OntologyChangeParser(logger)).parseFile(settings.getDiffFile());
|
||||
}
|
||||
|
||||
|
||||
|
@ -339,18 +337,19 @@ public class OntologyUpdater {
|
|||
if (changeObj.getSourceURI() != null){
|
||||
|
||||
if (oldTboxModel.getOntProperty(changeObj.getSourceURI()) != null){
|
||||
atomicPropertyChanges.add(changeObj);
|
||||
}
|
||||
else if (oldTboxModel.getOntClass(changeObj.getSourceURI()) != null) {
|
||||
atomicClassChanges.add(changeObj);
|
||||
}
|
||||
else{
|
||||
logger.logError("Source URI is neither a Property" +
|
||||
" nor a Class. " + "Change Object skipped for sourceURI: " + changeObj.getSourceURI());
|
||||
atomicPropertyChanges.add(changeObj);
|
||||
} else if (oldTboxModel.getOntClass(changeObj.getSourceURI()) != null) {
|
||||
atomicClassChanges.add(changeObj);
|
||||
} else if ("Prop".equals(changeObj.getNotes())) {
|
||||
atomicPropertyChanges.add(changeObj);
|
||||
} else if ("Class".equals(changeObj.getNotes())) {
|
||||
atomicClassChanges.add(changeObj);
|
||||
} 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) {
|
||||
atomicPropertyChanges.add(changeObj);
|
||||
|
@ -358,16 +357,14 @@ public class OntologyUpdater {
|
|||
getDestinationURI()) != null) {
|
||||
atomicClassChanges.add(changeObj);
|
||||
} 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());
|
||||
}
|
||||
}
|
||||
else{
|
||||
logger.logError("Source and Destination URI can't be null. "
|
||||
+ "Change Object skipped" );
|
||||
} else{
|
||||
logger.log("WARNING: 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() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue