NIHVIVO-3516 fixed merge tool so it doesn't strand triples in a graph named with SDB's union URI
This commit is contained in:
parent
f3d6e33a01
commit
2bdb44685f
3 changed files with 814 additions and 791 deletions
|
@ -80,6 +80,7 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent;
|
|||
import edu.cornell.mannlib.vitro.webapp.servlet.setup.JenaDataSourceSetup;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.SparqlQueryUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils.MergeResult;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestWorkflowProcessor;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaOutputUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.jena.WorkflowOntology;
|
||||
|
@ -621,23 +622,25 @@ public class JenaIngestController extends BaseEditController {
|
|||
if(uri1!=null){
|
||||
JenaIngestUtils utils = new JenaIngestUtils();
|
||||
/*
|
||||
* get baseOnt, Ont and infOnt models
|
||||
* get baseOnt and infOnt models
|
||||
*/
|
||||
OntModel baseOntModel = (OntModel) getServletContext().getAttribute("baseOntModel");
|
||||
OntModel ontModel = (OntModel)
|
||||
getServletContext().getAttribute("jenaOntModel");
|
||||
OntModel infOntModel = (OntModel)
|
||||
getServletContext().getAttribute(JenaBaseDao.INFERENCE_ONT_MODEL_ATTRIBUTE_NAME);
|
||||
OntModel baseOntModel = ModelContext.getBaseOntModel(
|
||||
getServletContext());
|
||||
OntModel tboxOntModel = ModelContext.getUnionOntModelSelector(
|
||||
getServletContext()).getTBoxModel();
|
||||
|
||||
/*
|
||||
* calling method that does the merge operation.
|
||||
*/
|
||||
String result = utils.doMerge(uri1,uri2,baseOntModel,ontModel,infOntModel,usePrimaryLabelOnly);
|
||||
vreq.getSession().setAttribute("leftoverModel", utils.getLeftOverModel());
|
||||
MergeResult result = utils.doMerge(
|
||||
uri1, uri2, baseOntModel, tboxOntModel, usePrimaryLabelOnly);
|
||||
|
||||
vreq.getSession().setAttribute(
|
||||
"leftoverModel", result.getLeftoverModel());
|
||||
vreq.setAttribute("result", result);
|
||||
vreq.setAttribute("title", "Merge Resources");
|
||||
vreq.setAttribute("bodyJsp", MERGE_RESULT);
|
||||
}
|
||||
else{
|
||||
} else{
|
||||
vreq.setAttribute("title","Merge Resources");
|
||||
vreq.setAttribute("bodyJsp",MERGE_RESOURCES);
|
||||
}
|
||||
|
@ -1192,7 +1195,7 @@ public class JenaIngestController extends BaseEditController {
|
|||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
if(!namespacePresent){
|
||||
result = "0 resource renamed";
|
||||
result = "no resources renamed";
|
||||
return result;
|
||||
}
|
||||
for( String oldURIStr : urisToChange){
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
package edu.cornell.mannlib.vitro.webapp.utils.jena;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
|
@ -16,15 +15,12 @@ import java.util.Random;
|
|||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.openrdf.model.vocabulary.RDFS;
|
||||
|
||||
import com.hp.hpl.jena.ontology.FunctionalProperty;
|
||||
import com.hp.hpl.jena.ontology.OntModel;
|
||||
import com.hp.hpl.jena.ontology.OntModelSpec;
|
||||
import com.hp.hpl.jena.ontology.OntProperty;
|
||||
import com.hp.hpl.jena.rdf.model.Literal;
|
||||
import com.hp.hpl.jena.rdf.model.Model;
|
||||
import com.hp.hpl.jena.rdf.model.ModelFactory;
|
||||
|
@ -41,11 +37,11 @@ import com.hp.hpl.jena.util.ResourceUtils;
|
|||
import com.hp.hpl.jena.util.iterator.ClosableIterator;
|
||||
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.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.InsertException;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.jena.JenaBaseDao;
|
||||
|
||||
public class JenaIngestUtils {
|
||||
|
||||
|
@ -591,132 +587,151 @@ public class JenaIngestUtils {
|
|||
}
|
||||
}
|
||||
|
||||
public String doMerge(String uri1,String uri2,OntModel baseOntModel,OntModel ontModel,OntModel infOntModel,String usePrimaryLabelOnly){
|
||||
public class MergeResult {
|
||||
private String resultText;
|
||||
private Model leftoverModel;
|
||||
|
||||
public MergeResult() {}
|
||||
|
||||
public MergeResult(String resultText, Model leftoverModel) {
|
||||
this.resultText = resultText;
|
||||
this.leftoverModel = leftoverModel;
|
||||
}
|
||||
|
||||
public void setResultText(String resultText) {
|
||||
this.resultText = resultText;
|
||||
}
|
||||
|
||||
public String getResultText() {
|
||||
return this.resultText;
|
||||
}
|
||||
|
||||
public void setLeftoverModel(Model leftoverModel) {
|
||||
this.leftoverModel = leftoverModel;
|
||||
}
|
||||
|
||||
public Model getLeftoverModel() {
|
||||
return this.leftoverModel;
|
||||
}
|
||||
}
|
||||
|
||||
public MergeResult doMerge(String uri1, String uri2, OntModel baseOntModel,
|
||||
OntModel tboxOntModel, String usePrimaryLabelOnly){
|
||||
|
||||
boolean functionalPresent = false;
|
||||
|
||||
Resource res1 = baseOntModel.getResource(uri1); // primary resource
|
||||
Model res1Model = ModelFactory.createDefaultModel();
|
||||
Resource res2 = baseOntModel.getResource(uri2); // secondary resource
|
||||
String result = null;
|
||||
baseOntModel.enterCriticalSection(Lock.WRITE);
|
||||
Model res2Model = ModelFactory.createDefaultModel();
|
||||
|
||||
/*
|
||||
* get statements of both the resources
|
||||
*/
|
||||
StmtIterator stmtItr1 = baseOntModel.listStatements(res1,(Property)null,(RDFNode)null);
|
||||
StmtIterator stmtItr2 = baseOntModel.listStatements(res2,(Property)null,(RDFNode)null);
|
||||
StmtIterator stmtItr3 = baseOntModel.listStatements((Resource)null,(Property)null,(RDFNode)res2);
|
||||
// get statements of both the resources
|
||||
baseOntModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
res1Model.add(
|
||||
baseOntModel.listStatements(res1, (Property)null, (RDFNode)null));
|
||||
res2Model.add(
|
||||
baseOntModel.listStatements(res2, (Property)null, (RDFNode)null));
|
||||
res2Model.add(
|
||||
baseOntModel.listStatements(
|
||||
(Resource)null, (Property)null, (RDFNode)res2));
|
||||
} finally {
|
||||
baseOntModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
/*
|
||||
* if primary resource has no statements, return
|
||||
*/
|
||||
if(!stmtItr1.hasNext()){
|
||||
result = "resource 1 not present";
|
||||
res1.removeAll((Property)null);
|
||||
baseOntModel.leaveCriticalSection();
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
* if secondary resource has no statements, return
|
||||
*/
|
||||
else if(!stmtItr2.hasNext()){
|
||||
result = "resource 2 not present";
|
||||
res2.removeAll((Property)null);
|
||||
baseOntModel.leaveCriticalSection();
|
||||
return result;
|
||||
// if primary resource has no statements, return
|
||||
if (res1Model.isEmpty()){
|
||||
return new MergeResult("resource 1 not present", null);
|
||||
} else if(res2Model.isEmpty()){
|
||||
return new MergeResult("resource 2 not present", null);
|
||||
}
|
||||
|
||||
int counter = 0;
|
||||
Model leftoverModel = ModelFactory.createDefaultModel();
|
||||
ontModel.enterCriticalSection(Lock.WRITE);
|
||||
infOntModel.enterCriticalSection(Lock.WRITE);
|
||||
try{
|
||||
|
||||
/*
|
||||
* Iterate through statements of secondary resource
|
||||
*/
|
||||
|
||||
// Iterate through statements of secondary resource
|
||||
StmtIterator stmtItr2 = res2Model.listStatements(
|
||||
res2, (Property) null, (RDFNode) null);
|
||||
while(stmtItr2.hasNext()){
|
||||
|
||||
Statement stmt = stmtItr2.next();
|
||||
Property prop = stmt.getPredicate();
|
||||
OntProperty oprop = baseOntModel.getOntProperty(prop.getURI());
|
||||
|
||||
/*
|
||||
* if the property is null or functional then dump the statement into leftover model
|
||||
* else add it to base, ont and inf models as a part of primary resource.
|
||||
*/
|
||||
if(oprop!=null && oprop.isFunctionalProperty()){
|
||||
Statement stmt = stmtItr2.nextStatement();
|
||||
if(isFunctional(stmt.getPredicate(), tboxOntModel)) {
|
||||
// if the property is null or functional then dump the statement into
|
||||
// the leftover model, else add it to base, ont and inf models as a
|
||||
// part of the primary resource.
|
||||
leftoverModel.add(res2, stmt.getPredicate(), stmt.getObject());
|
||||
functionalPresent = true;
|
||||
}
|
||||
/*
|
||||
* if the checkbox is checked, use primary resource rdfs:labels only and dump secondary resource rdfs:labels
|
||||
* into leftoverModel
|
||||
*/
|
||||
else if(prop.getURI().equals("http://www.w3.org/2000/01/rdf-schema#label") &&
|
||||
} else if (stmt.getPredicate().equals(RDFS.label) &&
|
||||
usePrimaryLabelOnly!=null && !usePrimaryLabelOnly.isEmpty()) {
|
||||
// if the checkbox is checked, use primary resource rdfs:labels only
|
||||
// and dump secondary resource rdfs:labels into leftoverModel
|
||||
leftoverModel.add(res2, stmt.getPredicate(), stmt.getObject());
|
||||
functionalPresent = true;
|
||||
}
|
||||
else{
|
||||
} else {
|
||||
baseOntModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
baseOntModel.add(res1, stmt.getPredicate(), stmt.getObject());
|
||||
ontModel.add(res1,stmt.getPredicate(),stmt.getObject());
|
||||
infOntModel.add(res1,stmt.getPredicate(),stmt.getObject());
|
||||
counter++;
|
||||
} finally {
|
||||
baseOntModel.leaveCriticalSection();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* replace secondary resource with primary resource in all the statements where
|
||||
* secondary resource is present as an object.
|
||||
*/
|
||||
}
|
||||
|
||||
// replace secondary resource with primary resource in all the statements
|
||||
// where secondary resource is present as an object.
|
||||
StmtIterator stmtItr3 = res2Model.listStatements(
|
||||
(Resource) null, (Property) null, res2);
|
||||
while (stmtItr3.hasNext()){
|
||||
Statement stmt = stmtItr3.nextStatement();
|
||||
Resource sRes = stmt.getSubject();
|
||||
Property sProp = stmt.getPredicate();
|
||||
baseOntModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
baseOntModel.add(sRes, sProp, res1);
|
||||
ontModel.add(sRes,sProp,res1);
|
||||
infOntModel.add(sRes,sProp,res1);
|
||||
}
|
||||
Resource ontRes = ontModel.getResource(res2.getURI());
|
||||
Resource infRes = infOntModel.getResource(res2.getURI());
|
||||
|
||||
/*
|
||||
* Remove all the statements of secondary resource from all the models.
|
||||
*/
|
||||
|
||||
baseOntModel.removeAll((Resource)null,(Property)null,(RDFNode)res2);
|
||||
ontModel.removeAll((Resource)null,(Property)null,(RDFNode)res2);
|
||||
infOntModel.removeAll((Resource)null,(Property)null,(RDFNode)res2);
|
||||
res2.removeAll((Property)null);
|
||||
ontRes.removeAll((Property)null);
|
||||
infRes.removeAll((Property)null);
|
||||
}
|
||||
finally{
|
||||
counter++;
|
||||
} finally {
|
||||
baseOntModel.leaveCriticalSection();
|
||||
infOntModel.leaveCriticalSection();
|
||||
ontModel.leaveCriticalSection();
|
||||
}
|
||||
setLeftOverModel(leftoverModel);
|
||||
if(counter>0 && functionalPresent)
|
||||
result = "merged " + counter + " statements. Some statements could not be merged.";
|
||||
else if(counter>0 && !functionalPresent)
|
||||
result = "merged " + counter + " statements.";
|
||||
else if(counter==0)
|
||||
result = "No statements merged";
|
||||
}
|
||||
|
||||
// Remove all the statements of secondary resource
|
||||
baseOntModel.enterCriticalSection(Lock.WRITE);
|
||||
try {
|
||||
baseOntModel.remove(res2Model);
|
||||
} finally {
|
||||
baseOntModel.leaveCriticalSection();
|
||||
}
|
||||
|
||||
MergeResult result = new MergeResult();
|
||||
if (!leftoverModel.isEmpty()) {
|
||||
result.setLeftoverModel(leftoverModel);
|
||||
}
|
||||
|
||||
if (counter > 0 && functionalPresent) {
|
||||
result.setResultText("merged " + counter +
|
||||
" statements. Some statements could not be merged.");
|
||||
} else if(counter>0 && !functionalPresent) {
|
||||
result.setResultText("merged " + counter + " statements.");
|
||||
} else if (counter==0) {
|
||||
result.setResultText("No statements merged");
|
||||
}
|
||||
return result;
|
||||
|
||||
}
|
||||
private Model leftoverModel = ModelFactory.createDefaultModel();
|
||||
|
||||
public void setLeftOverModel(Model leftoverModel){
|
||||
this.leftoverModel = leftoverModel;
|
||||
private boolean isFunctional(Property property, OntModel tboxOntModel) {
|
||||
tboxOntModel.enterCriticalSection(Lock.READ);
|
||||
try {
|
||||
return (tboxOntModel.contains(
|
||||
property, RDF.type, OWL.FunctionalProperty));
|
||||
} finally {
|
||||
tboxOntModel.leaveCriticalSection();
|
||||
}
|
||||
public Model getLeftOverModel(){
|
||||
return this.leftoverModel;
|
||||
}
|
||||
|
||||
public void doPermanentURI(String oldModel, String newModel, String oldNamespace,
|
||||
String newNamespace,String dNamespace,ModelMaker maker,VitroRequest vreq){
|
||||
|
||||
String newNamespace, String dNamespace, ModelMaker maker,
|
||||
VitroRequest vreq) {
|
||||
|
||||
WebappDaoFactory wdf = vreq.getFullWebappDaoFactory();
|
||||
Model m = maker.getModel(oldModel);
|
||||
|
@ -733,8 +748,7 @@ public class JenaIngestUtils {
|
|||
tempModel.add(stmt);
|
||||
}
|
||||
rsItr = tempModel.listResourcesWithProperty((Property)null);
|
||||
}
|
||||
else{
|
||||
} else{
|
||||
rsItr = m.listResourcesWithProperty((Property)null);
|
||||
}
|
||||
|
||||
|
@ -799,9 +813,9 @@ public class JenaIngestUtils {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
public String getUnusedURI(String newNamespace,WebappDaoFactory wdf){
|
||||
String uri = null;
|
||||
String errMsg = null;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<%-- $This file is distributed under the terms of the license in /doc/license.txt$ --%>
|
||||
|
||||
<%@page import="edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils.MergeResult"%>
|
||||
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"%>
|
||||
|
||||
<%@taglib prefix="vitro" uri="/WEB-INF/tlds/VitroUtils.tld" %>
|
||||
|
@ -11,8 +12,13 @@
|
|||
|
||||
<h2><a class="ingestMenu" href="ingest">Ingest Menu</a> > Merge Individuals</h2>
|
||||
|
||||
<%String result = (String) request.getAttribute("result");%>
|
||||
<%
|
||||
MergeResult resultObj = (MergeResult) request.getAttribute("result");
|
||||
String result = resultObj.getResultText();
|
||||
%>
|
||||
|
||||
<p><b><%=result%></b></p>
|
||||
|
||||
<%if(!result.equals("resource 1 not present") && !result.equals("resource 2 not present")){
|
||||
if(!result.equals("No statements merged") && !result.endsWith("statements.")){%>
|
||||
<p>Download non-mergeable statements.</p>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue