Merge pull request #292 from brianjlowe/issue/VIVO-3713
VIVO-3713 Avoid excessive use of resources when ABox firsttime data are changed
This commit is contained in:
commit
fb4594ed3e
4 changed files with 286 additions and 164 deletions
|
@ -98,7 +98,7 @@ public class ConfigurationModelsSetup implements ServletContextListener {
|
|||
OntModel baseModelFirsttime = VitroModelFactory.createOntologyModel();
|
||||
RDFFilesLoader.loadFirstTimeFiles(ctx, modelPath, baseModelFirsttime, true);
|
||||
|
||||
if (baseModelFirsttime.isIsomorphicWith(baseModelFirsttimeBackup)) {
|
||||
if (RDFFilesLoader.areIsomporphic(baseModelFirsttime, baseModelFirsttimeBackup)) {
|
||||
log.debug("They are the same, so do nothing: '" + modelPath + "'");
|
||||
} else {
|
||||
log.debug("They differ:" + modelPath + ", compare values in configuration models with user's triplestore");
|
||||
|
@ -132,9 +132,8 @@ public class ConfigurationModelsSetup implements ServletContextListener {
|
|||
|
||||
// remove special cases for display, problem with blank nodes
|
||||
if (modelIdString.equals("display")) {
|
||||
|
||||
removeBlankTriples(difOldNew);
|
||||
removeBlankTriples(difNewOld);
|
||||
RDFFilesLoader.removeBlankTriples(difOldNew);
|
||||
RDFFilesLoader.removeBlankTriples(difNewOld);
|
||||
}
|
||||
|
||||
if (difOldNew.isEmpty() && difNewOld.isEmpty()) {
|
||||
|
@ -149,7 +148,7 @@ public class ConfigurationModelsSetup implements ServletContextListener {
|
|||
log.debug("Difference for " + modelIdString + " (old -> new), these triples should be removed: " + out);
|
||||
|
||||
// Check if the UI-changes Overlap with the changes made in the fristtime-files
|
||||
checkUiChangesOverlapWithFileChanges(baseModel, userModel, difOldNew);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(baseModel, userModel, difOldNew);
|
||||
|
||||
// before we remove the triples, we need to compare values in back up firsttime with user's triplestore
|
||||
// if the triples which should be removed are still in user´s triplestore, remove them
|
||||
|
@ -167,7 +166,7 @@ public class ConfigurationModelsSetup implements ServletContextListener {
|
|||
log.debug("Difference for " + modelIdString + " (new -> old), these triples should be added: " + out2);
|
||||
|
||||
// Check if the UI-changes Overlap with the changes made in the fristtime-files
|
||||
checkUiChangesOverlapWithFileChanges(baseModel, userModel, difNewOld);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(baseModel, userModel, difNewOld);
|
||||
|
||||
// before we add the triples, we need to compare values in back up firsttime with user's triplestore
|
||||
// if the triples which should be added are not already in user´s triplestore, add them
|
||||
|
@ -186,85 +185,6 @@ public class ConfigurationModelsSetup implements ServletContextListener {
|
|||
return updatedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the UI-changes Overlap with the changes made in the fristtime-files, if they overlap these changes are not applied to the user-model (UI)
|
||||
*
|
||||
* @param baseModel firsttime backup model
|
||||
* @param userModel current state in the system (user/UI-model)
|
||||
* @param changesModel the changes between firsttime-files and firttime-backup
|
||||
*/
|
||||
private void checkUiChangesOverlapWithFileChanges(Model baseModel, Model userModel, Model changesModel) {
|
||||
log.debug("Beginn check if subtractions from Backup-firsttime model to current state of firsttime-files were changed in user-model (via UI)");
|
||||
Model changesUserModel = userModel.difference(baseModel);
|
||||
List<Statement> changedInUIandFileStatements = new ArrayList<Statement>();
|
||||
|
||||
if(!changesUserModel.isEmpty())
|
||||
{
|
||||
removeBlankTriples(changesUserModel);
|
||||
|
||||
StringWriter out3 = new StringWriter();
|
||||
changesUserModel.write(out3, "TTL");
|
||||
log.debug("There were changes in the user-model via UI which have also changed in the firsttime files, the following triples will not be updated");
|
||||
|
||||
// iterate all statements and check if the ones which should be removed were not changed via the UI
|
||||
StmtIterator iter = changesUserModel.listStatements();
|
||||
while (iter.hasNext()) {
|
||||
Statement stmt = iter.nextStatement(); // get next statement
|
||||
Resource subject = stmt.getSubject(); // get the subject
|
||||
Property predicate = stmt.getPredicate(); // get the predicate
|
||||
RDFNode object = stmt.getObject(); // get the object
|
||||
|
||||
StmtIterator iter2 = changesModel.listStatements();
|
||||
|
||||
while (iter2.hasNext()) {
|
||||
Statement stmt2 = iter2.nextStatement(); // get next statement
|
||||
Resource subject2 = stmt2.getSubject(); // get the subject
|
||||
Property predicate2 = stmt2.getPredicate(); // get the predicate
|
||||
RDFNode object2 = stmt2.getObject(); // get the object
|
||||
|
||||
// if subject and predicate are equal but the object differs and the language tag is the same, do not update these triples
|
||||
// this case indicates an change in the UI, which should not be overwriten from the firsttime files
|
||||
if(subject.equals(subject2) && predicate.equals(predicate2) && !object.equals(object2) ) {
|
||||
// if object is an literal, check the language tag
|
||||
if (object.isLiteral() && object2.isLiteral()) {
|
||||
// if the langauge tag is the same, remove this triple from the update list
|
||||
if(object.asLiteral().getLanguage().equals(object2.asLiteral().getLanguage())) {
|
||||
log.debug("This two triples changed UI and files: \n UI: " + stmt + " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
} else {
|
||||
log.debug("This two triples changed UI and files: \n UI: " + stmt + " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove triples which were changed in the user model (UI) from the list
|
||||
changesModel.remove(changedInUIandFileStatements);
|
||||
} else {
|
||||
log.debug("There were no changes in the user-model via UI compared to the backup-firsttime-model");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all triples where subject or object is blank (Anon)
|
||||
*/
|
||||
private void removeBlankTriples(Model model) {
|
||||
StmtIterator iter = model.listStatements();
|
||||
List<Statement> removeStatement = new ArrayList<Statement>();
|
||||
while (iter.hasNext()) {
|
||||
Statement stmt = iter.nextStatement(); // get next statement
|
||||
Resource subject = stmt.getSubject(); // get the subject
|
||||
RDFNode object = stmt.getObject(); // get the object
|
||||
|
||||
if(subject.isAnon() || object.isAnon())
|
||||
{
|
||||
removeStatement.add(stmt);
|
||||
}
|
||||
}
|
||||
model.remove(removeStatement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
// Nothing to tear down.
|
||||
|
|
|
@ -3,22 +3,21 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.ABOX_ASSERTIONS;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.APPLICATION_METADATA;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.ABOX_ASSERTIONS_FIRSTTIME_BACKUP;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS_FIRSTTIME_BACKUP;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.APPLICATION_METADATA;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.APPLICATION_METADATA_FIRSTTIME_BACKUP;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS;
|
||||
import static edu.cornell.mannlib.vitro.webapp.modelaccess.ModelNames.TBOX_ASSERTIONS_FIRSTTIME_BACKUP;
|
||||
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.io.StringWriter;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.apache.jena.ontology.OntModel;
|
||||
import org.apache.jena.rdf.model.Model;
|
||||
import org.apache.jena.rdf.model.Property;
|
||||
|
@ -28,9 +27,6 @@ import org.apache.jena.shared.Lock;
|
|||
import org.apache.jena.util.ResourceUtils;
|
||||
import org.apache.jena.util.iterator.ClosableIterator;
|
||||
import org.apache.jena.vocabulary.RDF;
|
||||
import org.apache.jena.rdf.model.Statement;
|
||||
import org.apache.jena.rdf.model.StmtIterator;
|
||||
import org.apache.jena.rdf.model.RDFNode;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
|
||||
import edu.cornell.mannlib.vitro.webapp.modelaccess.ContextModelAccess;
|
||||
|
@ -129,23 +125,24 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
* URI of the Portal based on the default namespace.
|
||||
*/
|
||||
private void setPortalUriOnFirstTime(Model model, ServletContext ctx) {
|
||||
// Only a single portal is permitted in the initialization data
|
||||
Resource portalResource = null;
|
||||
// Only a single portal is permitted in the initialization data.
|
||||
// Treat all blank nodes with type Portal as describing the same
|
||||
// portal, and give them the same URI.
|
||||
List<Resource> toRename = new ArrayList<Resource>();
|
||||
ClosableIterator<Resource> portalResIt = model
|
||||
.listSubjectsWithProperty(RDF.type,
|
||||
model.getResource(VitroVocabulary.PORTAL));
|
||||
try {
|
||||
if (portalResIt.hasNext()) {
|
||||
while (portalResIt.hasNext()) {
|
||||
Resource portalRes = portalResIt.next();
|
||||
if (portalRes.isAnon()) {
|
||||
portalResource = portalRes;
|
||||
toRename.add(portalRes);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
portalResIt.close();
|
||||
}
|
||||
|
||||
if (portalResource != null) {
|
||||
for (Resource portalResource : toRename) {
|
||||
ResourceUtils.renameResource(portalResource, getDefaultNamespace(ctx) + "portal1");
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +246,7 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
setPortalUriOnFirstTime(firsttimeFilesModel, ctx);
|
||||
}
|
||||
|
||||
if ( firsttimeBackupModel.isIsomorphicWith(firsttimeFilesModel) ) {
|
||||
if ( RDFFilesLoader.areIsomporphic(firsttimeBackupModel, firsttimeFilesModel) ) {
|
||||
log.debug("They are the same, so do nothing: '" + modelPath + "'");
|
||||
} else {
|
||||
log.debug("They differ: '" + modelPath + "', compare values in configuration models with user's triplestore");
|
||||
|
@ -301,7 +298,7 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
log.debug("Difference for " + modelIdString + " (old -> new), these triples should be removed: " + out);
|
||||
|
||||
// Check if the UI-changes Overlap with the changes made in the fristtime-files
|
||||
checkUiChangesOverlapWithFileChanges(baseModel, userModel, difOldNew);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(baseModel, userModel, difOldNew);
|
||||
|
||||
// before we remove the triples, we need to compare values in back up firsttime with user's triplestore
|
||||
// if the triples which should be removed are still in user´s triplestore, remove them
|
||||
|
@ -320,7 +317,7 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
log.debug("Difference for " + modelIdString + " (new -> old), these triples should be added: " + out2);
|
||||
|
||||
// Check if the UI-changes Overlap with the changes made in the fristtime-files
|
||||
checkUiChangesOverlapWithFileChanges(baseModel, userModel, difNewOld);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(baseModel, userModel, difNewOld);
|
||||
|
||||
// before we add the triples, we need to compare values in back up firsttime with user's triplestore
|
||||
// if the triples which should be added are not already in user´s triplestore, add them
|
||||
|
@ -339,67 +336,6 @@ public class ContentModelSetup extends JenaDataSourceSetupBase
|
|||
return updatedFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the UI-changes Overlap with the changes made in the fristtime-files, if they overlap these changes are not applied to the user-model (UI)
|
||||
*
|
||||
* @param baseModel firsttime backup model
|
||||
* @param userModel current state in the system (user/UI-model)
|
||||
* @param changesModel the changes between firsttime-files and firttime-backup
|
||||
*/
|
||||
private void checkUiChangesOverlapWithFileChanges(Model baseModel, Model userModel, Model changesModel) {
|
||||
log.debug("Beginn check if subtractions from Backup-firsttime model to current state of firsttime-files were changed in user-model (via UI)");
|
||||
Model changesUserModel = userModel.difference(baseModel);
|
||||
List<Statement> changedInUIandFileStatements = new ArrayList<Statement>();
|
||||
|
||||
if(!changesUserModel.isEmpty())
|
||||
{
|
||||
|
||||
StringWriter out3 = new StringWriter();
|
||||
changesUserModel.write(out3, "TTL");
|
||||
log.debug("There were changes in the user-model via UI which have also changed in the firsttime files, the following triples will not be updated");
|
||||
|
||||
// iterate all statements and check if the ones which should be removed were not changed via the UI
|
||||
StmtIterator iter = changesUserModel.listStatements();
|
||||
while (iter.hasNext()) {
|
||||
Statement stmt = iter.nextStatement(); // get next statement
|
||||
Resource subject = stmt.getSubject(); // get the subject
|
||||
Property predicate = stmt.getPredicate(); // get the predicate
|
||||
RDFNode object = stmt.getObject(); // get the object
|
||||
|
||||
StmtIterator iter2 = changesModel.listStatements();
|
||||
|
||||
while (iter2.hasNext()) {
|
||||
Statement stmt2 = iter2.nextStatement(); // get next statement
|
||||
Resource subject2 = stmt2.getSubject(); // get the subject
|
||||
Property predicate2 = stmt2.getPredicate(); // get the predicate
|
||||
RDFNode object2 = stmt2.getObject(); // get the object
|
||||
|
||||
// if subject and predicate are equal but the object differs and the language tag is the same, do not update these triples
|
||||
// this case indicates an change in the UI, which should not be overwriten from the firsttime files
|
||||
if(subject.equals(subject2) && predicate.equals(predicate2) && !object.equals(object2) ) {
|
||||
// if object is an literal, check the language tag
|
||||
if (object.isLiteral() && object2.isLiteral()) {
|
||||
// if the langauge tag is the same, remove this triple from the update list
|
||||
if(object.asLiteral().getLanguage().equals(object2.asLiteral().getLanguage())) {
|
||||
log.debug("This two triples changed UI and files: \n UI: " + stmt + " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
} else {
|
||||
log.debug("This two triples changed UI and files: \n UI: " + stmt + " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove triples which were changed in the user model (UI) from the list
|
||||
changesModel.remove(changedInUIandFileStatements);
|
||||
} else {
|
||||
log.debug("There were no changes in the user-model via UI compared to the backup-firsttime-model");
|
||||
}
|
||||
}
|
||||
|
||||
/* ===================================================================== */
|
||||
|
||||
@Override
|
||||
public void contextDestroyed(ServletContextEvent sce) {
|
||||
// Nothing to do.
|
||||
|
|
|
@ -5,10 +5,12 @@ package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringWriter;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -23,6 +25,11 @@ import org.apache.jena.ontology.OntModel;
|
|||
import org.apache.jena.ontology.OntModelSpec;
|
||||
import org.apache.jena.rdf.model.Model;
|
||||
import org.apache.jena.rdf.model.ModelFactory;
|
||||
import org.apache.jena.rdf.model.Property;
|
||||
import org.apache.jena.rdf.model.RDFNode;
|
||||
import org.apache.jena.rdf.model.Resource;
|
||||
import org.apache.jena.rdf.model.Statement;
|
||||
import org.apache.jena.rdf.model.StmtIterator;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.application.ApplicationUtils;
|
||||
|
||||
|
@ -207,5 +214,130 @@ public class RDFFilesLoader {
|
|||
private RDFFilesLoader() {
|
||||
// Nothing to initialize.
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the user model (UI) changes conflict with the changes made to
|
||||
* the firsttime. If there is conflict, the user model UI value will be
|
||||
* left unchanged.
|
||||
*
|
||||
* @param baseModel firsttime backup model
|
||||
* @param userModel current state in the system (user/UI-model)
|
||||
* @param changesModel the changes between firsttime-files and firsttime-backup
|
||||
*/
|
||||
public static void removeChangesThatConflictWithUIEdits(Model baseModel,
|
||||
Model userModel, Model changesModel) {
|
||||
log.debug("Check if subtractions from backup-firsttime model to"
|
||||
+ " current state of firsttime-files were changed in user-model"
|
||||
+ " (via UI)");
|
||||
// We don't want to diff against the entire user model, which may be
|
||||
// huge. We only care about subject/predicate pairs that exist in the
|
||||
// changesModel. So extract these first from userModel into a
|
||||
// scopedUserModel that we can use for diffing.
|
||||
Model scopedUserModel = ModelFactory.createDefaultModel();
|
||||
StmtIterator scopeIt = changesModel.listStatements();
|
||||
while(scopeIt.hasNext()) {
|
||||
Statement scopingStmt = scopeIt.next();
|
||||
scopedUserModel.add(userModel.listStatements(
|
||||
scopingStmt.getSubject(), scopingStmt.getPredicate(), (RDFNode) null));
|
||||
}
|
||||
log.debug("Scoped user model has " + scopedUserModel.size());
|
||||
Model changesUserModel = scopedUserModel.difference(baseModel);
|
||||
log.debug("Diff of scoped user model against firsttime backup has "
|
||||
+ changesUserModel.size() + " triples");
|
||||
List<Statement> changedInUIandFileStatements = new ArrayList<Statement>();
|
||||
if(changesUserModel.isEmpty()) {
|
||||
log.debug("There were no changes in the user-model via UI"
|
||||
+ " compared to the backup-firsttime-model");
|
||||
return;
|
||||
}
|
||||
removeBlankTriples(changesUserModel);
|
||||
if(log.isDebugEnabled()) {
|
||||
StringWriter out3 = new StringWriter();
|
||||
changesUserModel.write(out3, "TTL");
|
||||
log.debug("changesUserModel:\n" + out3);
|
||||
}
|
||||
log.debug("There were changes in the user-model via UI which have"
|
||||
+ " also changed in the firsttime files. The following"
|
||||
+ " triples will not be updated.");
|
||||
// Iterate over all statements and check if the ones which should be
|
||||
// removed were not changed via the UI
|
||||
StmtIterator userChanges = changesUserModel.listStatements();
|
||||
while (userChanges.hasNext()) {
|
||||
Statement stmt = userChanges.nextStatement();
|
||||
Resource subject = stmt.getSubject();
|
||||
Property predicate = stmt.getPredicate();
|
||||
RDFNode object = stmt.getObject();
|
||||
StmtIterator firsttimeChanges = changesModel.listStatements(
|
||||
subject, predicate, (RDFNode) null);
|
||||
while (firsttimeChanges.hasNext()) {
|
||||
Statement stmt2 = firsttimeChanges.nextStatement();
|
||||
RDFNode object2 = stmt2.getObject();
|
||||
// If subject and predicate are equal but the object differs
|
||||
// and the language tag is the same, do not update these triples.
|
||||
// This case indicates an change in the UI, which should not
|
||||
// be overwritten from the firsttime files.
|
||||
if(!object.equals(object2) ) {
|
||||
// if object is an literal, check the language tag
|
||||
if (object.isLiteral() && object2.isLiteral()) {
|
||||
// if the language tag is the same, remove this
|
||||
// triple from the update list
|
||||
if(object.asLiteral().getLanguage().equals(
|
||||
object2.asLiteral().getLanguage())) {
|
||||
log.debug("This two triples changed UI and"
|
||||
+ " files: \n UI: " + stmt
|
||||
+ " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
} else {
|
||||
log.debug("This two triples changed UI and"
|
||||
+ " files: \n UI: " + stmt
|
||||
+ " \n file: " +stmt2);
|
||||
changedInUIandFileStatements.add(stmt2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// remove triples which were changed in the user model (UI) from the list
|
||||
changesModel.remove(changedInUIandFileStatements);
|
||||
}
|
||||
|
||||
}
|
||||
/**
|
||||
* Remove all triples where subject or object is blank (Anon)
|
||||
*/
|
||||
public static void removeBlankTriples(Model model) {
|
||||
List<Statement> removeStatement = new ArrayList<Statement>();
|
||||
StmtIterator stmts = model.listStatements();
|
||||
while (stmts.hasNext()) {
|
||||
Statement stmt = stmts.nextStatement();
|
||||
if(stmt.getSubject().isAnon() || stmt.getObject().isAnon())
|
||||
{
|
||||
removeStatement.add(stmt);
|
||||
}
|
||||
}
|
||||
model.remove(removeStatement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check 'isomorphism' for purposes of propagating firsttime changes.
|
||||
* Run Jena's isomorphism check, but if it fails only due to blank nodes,
|
||||
* ignore and treat as isomorphic anyway. (Auto-updating firsttime
|
||||
* changes should occur only with named nodes.)
|
||||
* @param m1
|
||||
* @param m2
|
||||
* @return true if models are isomorphic or any lack of isomorphism exists
|
||||
* only in blank nodes
|
||||
*/
|
||||
public static boolean areIsomporphic(Model m1, Model m2) {
|
||||
boolean isIsomorphic = m1.isIsomorphicWith(m2);
|
||||
if(isIsomorphic) {
|
||||
return true;
|
||||
} else {
|
||||
Model diff1 = m1.difference(m2);
|
||||
Model diff2 = m2.difference(m1);
|
||||
removeBlankTriples(diff1);
|
||||
removeBlankTriples(diff2);
|
||||
return (diff1.isEmpty() && diff2.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import org.apache.jena.rdf.model.Model;
|
||||
import org.apache.jena.rdf.model.ModelFactory;
|
||||
import org.apache.jena.vocabulary.RDFS;
|
||||
|
||||
import edu.cornell.mannlib.vitro.testing.AbstractTestClass;
|
||||
|
||||
public class RDFFilesLoaderTest extends AbstractTestClass {
|
||||
|
||||
@org.junit.Test
|
||||
public void testFirsttimeUpdate() {
|
||||
|
||||
// the current state of the firsttime file on the filesystem
|
||||
String fileModelRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish 'n' chips\"@en-GB . \n"
|
||||
+ ":n1 rdfs:label \"fish and fries\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"Subway!\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"metrou\"@ro-RO . \n";
|
||||
|
||||
// the backup of the previous state of the firsttime file
|
||||
String backupModelRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish 'n' chips\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"nooo\"@no-NO . \n";
|
||||
|
||||
// the current state of the user-editable model
|
||||
String userModelRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish and chips\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"subway\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"nooo\"@no-NO . \n";
|
||||
|
||||
// the expected state of the user-editable model after firsttime
|
||||
// updates have been applied
|
||||
String userModelExpectedRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish and chips\"@en-GB . \n"
|
||||
+ ":n1 rdfs:label \"fish and fries\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"subway\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"metrou\"@ro-RO . \n";
|
||||
|
||||
Model fileModel = ModelFactory.createDefaultModel();
|
||||
fileModel.read(new StringReader(fileModelRdf), null, "N3");
|
||||
Model backupModel = ModelFactory.createDefaultModel();
|
||||
backupModel.read(new StringReader(backupModelRdf), null, "N3");
|
||||
Model userModel = ModelFactory.createDefaultModel();
|
||||
userModel.read(new StringReader(userModelRdf), null, "N3");
|
||||
Model userModelExpected = ModelFactory.createDefaultModel();
|
||||
userModelExpected.read(new StringReader(userModelExpectedRdf), null, "N3");
|
||||
|
||||
Model additionsModel = fileModel.difference(backupModel);
|
||||
Model retractionsModel = backupModel.difference(fileModel);
|
||||
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(backupModel, userModel, additionsModel);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(backupModel, userModel, retractionsModel);
|
||||
|
||||
userModel.remove(retractionsModel);
|
||||
userModel.add(additionsModel);
|
||||
|
||||
// For any given triple (S, P, O) changed in the fileModel, it
|
||||
// should only be propagated to the user model if the user model
|
||||
// doesn't already have a conflicting triple (S, P, X) where O and X
|
||||
// have the same language tag.
|
||||
assertTrue("expected: " + userModelExpected + " but was: " + userModel,
|
||||
userModelExpected.isIsomorphicWith(userModel));
|
||||
}
|
||||
|
||||
@org.junit.Test
|
||||
public void testFirsttimeUpdateEmptyBackup() {
|
||||
|
||||
// the current state of the firsttime file on the filesystem
|
||||
String fileModelRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish 'n' chips\"@en-GB . \n"
|
||||
+ ":n1 rdfs:label \"fish and fries\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"Subway!\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"metrou\"@ro-RO . \n";
|
||||
|
||||
// the current state of the user-editable model
|
||||
String userModelRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish and chips\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"subway\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"nooo\"@no-NO . \n";
|
||||
|
||||
// the expected state of the user-editable model after firsttime
|
||||
// updates have been applied
|
||||
String userModelExpectedRdf = "@prefix rdfs: <" + RDFS.getURI() + "> .\n"
|
||||
+ "@prefix : <http://example.com/individual/> .\n"
|
||||
+ ":n1 rdfs:label \"fish and chips\"@en-GB . \n"
|
||||
+ ":n1 rdfs:label \"fish and fries\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"tube\"@en-GB . \n"
|
||||
+ ":n2 rdfs:label \"subway\"@en-US . \n"
|
||||
+ ":n2 rdfs:label \"metrou\"@ro-RO . \n"
|
||||
+ ":n2 rdfs:label \"nooo\"@no-NO . \n";
|
||||
|
||||
Model fileModel = ModelFactory.createDefaultModel();
|
||||
fileModel.read(new StringReader(fileModelRdf), null, "N3");
|
||||
Model backupModel = ModelFactory.createDefaultModel();
|
||||
Model userModel = ModelFactory.createDefaultModel();
|
||||
userModel.read(new StringReader(userModelRdf), null, "N3");
|
||||
Model userModelExpected = ModelFactory.createDefaultModel();
|
||||
userModelExpected.read(new StringReader(userModelExpectedRdf), null, "N3");
|
||||
|
||||
Model additionsModel = fileModel.difference(backupModel);
|
||||
Model retractionsModel = backupModel.difference(fileModel);
|
||||
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(backupModel, userModel, additionsModel);
|
||||
RDFFilesLoader.removeChangesThatConflictWithUIEdits(backupModel, userModel, retractionsModel);
|
||||
|
||||
userModel.remove(retractionsModel);
|
||||
userModel.add(additionsModel);
|
||||
|
||||
// For any given triple (S, P, O) found in the fileModel, it
|
||||
// should only be propagated to the user model if the user model
|
||||
// doesn't already have a conflicting triple (S, P, X) where O and X
|
||||
// have the same language tag.
|
||||
assertTrue("expected: " + userModelExpected + " but was: " + userModel,
|
||||
userModelExpected.isIsomorphicWith(userModel));
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue