diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java
index 7906d799b..add10b116 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/jena/JenaIngestController.java
@@ -598,7 +598,8 @@ public class JenaIngestController extends BaseEditController {
private void processMergeResourceRequest(VitroRequest vreq) {
String uri1 = vreq.getParameter("uri1"); // get primary uri
String uri2 = vreq.getParameter("uri2"); // get secondary uri
- String usePrimaryLabelOnly = vreq.getParameter("usePrimaryLabelOnly");
+ String usePrimaryLabelOnlyStr = vreq.getParameter("usePrimaryLabelOnly");;
+ boolean usePrimaryLabelOnly = usePrimaryLabelOnlyStr != null && !usePrimaryLabelOnlyStr.isEmpty();
if(uri1!=null){
JenaIngestUtils utils = new JenaIngestUtils();
diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/JenaIngestUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/JenaIngestUtils.java
index 14266910e..c3d5b4a39 100644
--- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/JenaIngestUtils.java
+++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/jena/JenaIngestUtils.java
@@ -615,8 +615,17 @@ public class JenaIngestUtils {
}
}
+ /**
+ * Merges statements about resource uri2 into resource uri1 and delete uri2.
+ * @param uri1 The resource to merge to
+ * @param uri2 The resource to merge from
+ * @param baseOntModel The model containing the relevant statements
+ * @param tboxOntModel The model containing class and property data
+ * @param usePrimaryLabelOnly If true, discard rdfs:labels from uri2. Otherwise retain.
+ * @return
+ */
public MergeResult doMerge(String uri1, String uri2, OntModel baseOntModel,
- OntModel tboxOntModel, String usePrimaryLabelOnly){
+ OntModel tboxOntModel, boolean usePrimaryLabelOnly){
boolean functionalPresent = false;
@@ -660,8 +669,7 @@ public class JenaIngestUtils {
// part of the primary resource.
leftoverModel.add(res2, stmt.getPredicate(), stmt.getObject());
functionalPresent = true;
- } else if (stmt.getPredicate().equals(RDFS.label) &&
- usePrimaryLabelOnly!=null && !usePrimaryLabelOnly.isEmpty()) {
+ } else if (stmt.getPredicate().equals(RDFS.label) && usePrimaryLabelOnly) {
// 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());
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/JenaIngestUtilsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/JenaIngestUtilsTest.java
new file mode 100644
index 000000000..3dda8125d
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/JenaIngestUtilsTest.java
@@ -0,0 +1,127 @@
+package edu.cornell.mannlib.vitro.webapp.utils.ingest;
+
+import java.io.StringWriter;
+
+import junit.framework.Assert;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.junit.Test;
+
+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.rdf.model.Statement;
+import com.hp.hpl.jena.rdf.model.StmtIterator;
+
+import edu.cornell.mannlib.vitro.webapp.dao.jena.RDFServiceGraph;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.RDFService;
+import edu.cornell.mannlib.vitro.webapp.rdfservice.impl.jena.model.RDFServiceModel;
+import edu.cornell.mannlib.vitro.webapp.utils.jena.JenaIngestUtils;
+
+public class JenaIngestUtilsTest {
+
+ private final Log log = LogFactory.getLog(JenaIngestUtilsTest.class);
+
+ protected JenaIngestUtils utils = new JenaIngestUtils();
+
+ protected Model makeModel() {
+ Model base = ModelFactory.createDefaultModel();
+ RDFService rdfService = new RDFServiceModel(base);
+ return RDFServiceGraph.createRDFServiceModel(
+ new RDFServiceGraph(rdfService));
+ }
+
+ @Test
+ public void testSmush() {
+ Model model = makeModel();
+ model.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "smush.start.n3"), null, "N3");
+ JenaIngestUtils utils = new JenaIngestUtils();
+ Model actualResult = utils.smushResources(
+ model, model.getProperty("http://example.com/ns/duckCode"));
+ boolean matchesPossibleResult = false;
+ for(int i = 1; i < 7; i++) {
+ Model possibleResult = ModelFactory.createDefaultModel();
+ possibleResult.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "smush.end." + i + ".n3"), null, "N3");
+ if(actualResult.isIsomorphicWith(possibleResult)) {
+ matchesPossibleResult = true;
+ break;
+ }
+ }
+ if (!matchesPossibleResult) {
+ StringWriter s = new StringWriter();
+ actualResult.write(s, "N3");
+ Assert.fail("Smushed model does not match one of the possible results:\n" +
+ s.toString());
+ }
+ }
+
+ @Test
+ public void testRenameBNodes() {
+ Model initialState = ModelFactory.createDefaultModel();
+ initialState.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "renameBlank.n3"), null, "N3");
+ Model renamedState = utils.renameBNodes(
+ initialState, "http://example.org/node/n");
+ Assert.assertEquals("Post-rename model is not the same size as the " +
+ "initial model", initialState.size(), renamedState.size());
+ StmtIterator sit = renamedState.listStatements();
+ boolean lingeringBNodes = false;
+ while(sit.hasNext()) {
+ Statement stmt = sit.nextStatement();
+ if(stmt.getSubject().isAnon() || stmt.getObject().isAnon()) {
+ lingeringBNodes = true;
+ }
+ }
+ if(lingeringBNodes) {
+ StringWriter s = new StringWriter();
+ renamedState.write(s, "N3");
+ Assert.fail("Renamed model still contains blank nodes \n" +
+ s.toString());
+ }
+ }
+
+ @Test
+ public void testGenerateTBox() {
+ Model abox = ModelFactory.createDefaultModel();
+ abox.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "abox.n3"), null, "N3");
+ Model tbox = ModelFactory.createDefaultModel();
+ tbox.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "tbox.n3"), null, "N3");
+ Model generatedTBox = utils.generateTBox(abox);
+ //log.warn(tbox.toString());
+ Assert.assertTrue("Generated TBox does not match expected result",
+ tbox.isIsomorphicWith(generatedTBox));
+ }
+
+ @Test
+ public void testDoMerge() {
+ OntModel model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, makeModel());
+ OntModel tbox = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, makeModel());
+ model.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "merge.n3"), null, "N3");
+ tbox.read(JenaIngestUtilsTest.class.getResourceAsStream("tbox.n3"), null, "N3");
+ Model expectedMergeMultipleLabels = model.read(
+ JenaIngestUtilsTest.class.getResourceAsStream(
+ "mergeResultMultipleLabels.n3"), null, "N3");
+ utils.doMerge("http://example.com/ns/n1", "http://example.com/ns/n1", model, tbox, false);
+ Assert.assertTrue("Merged model with multiple labels does not match " +
+ "expected result", expectedMergeMultipleLabels.isIsomorphicWith(model));
+
+ model = ModelFactory.createOntologyModel(OntModelSpec.OWL_MEM, makeModel());
+ model.read(JenaIngestUtilsTest.class.getResourceAsStream(
+ "merge.n3"), null, "N3");
+ Model expectedMergeSingleLabel = model.read(
+ JenaIngestUtilsTest.class.getResourceAsStream(
+ "mergeResultSingleLabel.n3"), null, "N3");
+ utils.doMerge("http://example.com/ns/n1", "http://example.com/ns/n1", model, tbox, true);
+ Assert.assertTrue("Merged model with multiple labels does not match " +
+ "expected result", expectedMergeSingleLabel.isIsomorphicWith(model));
+
+ }
+
+}
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/abox.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/abox.n3
new file mode 100644
index 000000000..ed327e45f
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/abox.n3
@@ -0,0 +1,12 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese"@en-US .
+ns:n1 ns:o ns:f .
+ns:n2 a ns:Duck .
+ns:n2 ns:upcCode "2" .
+ns:n2 ns:p ns:q .
+ns:n3 a ns:Duck .
+ns:n3 ns:productCode "3"^^ .
+ns:n3 ns:q ns:z .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/merge.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/merge.n3
new file mode 100644
index 000000000..c74730248
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/merge.n3
@@ -0,0 +1,17 @@
+@prefix ns: .
+@prefix rdfs: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 rdfs:label "duck" .
+ns:n1 rdfs:label "duck"@en-US .
+ns:n1 ns:d "cheese"@en-US .
+ns:n1 ns:o ns:f .
+ns:n2 a ns:Duck .
+ns:n2 rdfs:label "goose" .
+ns:n2 ns:upcCode "2" .
+ns:n2 ns:p ns:q .
+ns:n3 a ns:Duck .
+ns:n3 ns:productCode "3"^^ .
+ns:n3 ns:q ns:z .
+ns:n4 ns:q ns:n2 .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultMultipleLabels.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultMultipleLabels.n3
new file mode 100644
index 000000000..5c9f5749e
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultMultipleLabels.n3
@@ -0,0 +1,16 @@
+@prefix ns: .
+@prefix rdfs: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 rdfs:label "duck" .
+ns:n1 rdfs:label "duck"@en-US .
+ns:n1 ns:d "cheese"@en-US .
+ns:n1 ns:o ns:f .
+ns:n1 rdfs:label "goose" .
+ns:n1 ns:upcCode "2" .
+ns:n1 ns:p ns:q .
+ns:n3 a ns:Duck .
+ns:n3 ns:productCode "3"^^ .
+ns:n3 ns:q ns:z .
+ns:n4 ns:q ns:n1 .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultSingleLabel.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultSingleLabel.n3
new file mode 100644
index 000000000..946de525a
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/mergeResultSingleLabel.n3
@@ -0,0 +1,15 @@
+@prefix ns: .
+@prefix rdfs: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 rdfs:label "duck" .
+ns:n1 rdfs:label "duck"@en-US .
+ns:n1 ns:d "cheese"@en-US .
+ns:n1 ns:o ns:f .
+ns:n1 ns:upcCode "2" .
+ns:n1 ns:p ns:q .
+ns:n3 a ns:Duck .
+ns:n3 ns:productCode "3"^^ .
+ns:n3 ns:q ns:z .
+ns:n4 ns:q ns:n1 .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/renameBlank.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/renameBlank.n3
new file mode 100644
index 000000000..fd1d93249
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/renameBlank.n3
@@ -0,0 +1,13 @@
+@prefix ns: .
+
+[] a ns:Duck ;
+ ns:duckCode "1" ;
+ ns:d [
+ a ns:Duck ;
+ ns:duckCode "2" ;
+ ns:d [
+ a ns:Duck ;
+ ns:duckCode "3" ;
+ ns:d "cake" ;
+ ] ;
+ ] .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.1.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.1.n3
new file mode 100644
index 000000000..d35b21ba1
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.1.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n2 a ns:Duck .
+ns:n2 ns:duckCode "2" .
+ns:n2 ns:d "strudel" .
+ns:n2 ns:d "pancake" .
+ns:n3 a ns:Duck .
+ns:n3 ns:duckCode "3" .
+ns:n3 ns:d "cake" .
+ns:n3 ns:d "bacon" .
+ns:n3 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.2.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.2.n3
new file mode 100644
index 000000000..98d3a54dc
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.2.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n2 a ns:Duck .
+ns:n2 ns:duckCode "2" .
+ns:n2 ns:d "strudel" .
+ns:n2 ns:d "pancake" .
+ns:n6 a ns:Duck .
+ns:n6 ns:duckCode "3" .
+ns:n6 ns:d "cake" .
+ns:n6 ns:d "bacon" .
+ns:n6 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.3.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.3.n3
new file mode 100644
index 000000000..743c47b31
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.3.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n2 a ns:Duck .
+ns:n2 ns:duckCode "2" .
+ns:n2 ns:d "strudel" .
+ns:n2 ns:d "pancake" .
+ns:n8 a ns:Duck .
+ns:n8 ns:duckCode "3" .
+ns:n8 ns:d "cake" .
+ns:n8 ns:d "bacon" .
+ns:n8 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.4.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.4.n3
new file mode 100644
index 000000000..17c72bf62
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.4.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n5 a ns:Duck .
+ns:n5 ns:duckCode "2" .
+ns:n5 ns:d "strudel" .
+ns:n5 ns:d "pancake" .
+ns:n3 a ns:Duck .
+ns:n3 ns:duckCode "3" .
+ns:n3 ns:d "cake" .
+ns:n3 ns:d "bacon" .
+ns:n3 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.5.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.5.n3
new file mode 100644
index 000000000..8ae42467a
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.5.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n5 a ns:Duck .
+ns:n5 ns:duckCode "2" .
+ns:n5 ns:d "strudel" .
+ns:n5 ns:d "pancake" .
+ns:n6 a ns:Duck .
+ns:n6 ns:duckCode "3" .
+ns:n6 ns:d "cake" .
+ns:n6 ns:d "bacon" .
+ns:n6 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.6.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.6.n3
new file mode 100644
index 000000000..b96edb0be
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.end.6.n3
@@ -0,0 +1,14 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n5 a ns:Duck .
+ns:n5 ns:duckCode "2" .
+ns:n5 ns:d "strudel" .
+ns:n5 ns:d "pancake" .
+ns:n8 a ns:Duck .
+ns:n8 ns:duckCode "3" .
+ns:n8 ns:d "cake" .
+ns:n8 ns:d "bacon" .
+ns:n8 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.start.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.start.n3
new file mode 100644
index 000000000..2759baebd
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/smush.start.n3
@@ -0,0 +1,20 @@
+@prefix ns: .
+
+ns:n1 a ns:Duck .
+ns:n1 ns:duckCode "1" .
+ns:n1 ns:d "cheese" .
+ns:n2 a ns:Duck .
+ns:n2 ns:duckCode "2" .
+ns:n2 ns:d "strudel" .
+ns:n3 a ns:Duck .
+ns:n3 ns:duckCode "3" .
+ns:n3 ns:d "cake" .
+ns:n5 a ns:Duck .
+ns:n5 ns:duckCode "2" .
+ns:n5 ns:d "pancake" .
+ns:n6 a ns:Duck .
+ns:n6 ns:duckCode "3" .
+ns:n6 ns:d "bacon" .
+ns:n8 a ns:Duck .
+ns:n8 ns:duckCode "3" .
+ns:n8 ns:d "corn" .
diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/tbox.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/tbox.n3
new file mode 100644
index 000000000..21a085b7a
--- /dev/null
+++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/ingest/tbox.n3
@@ -0,0 +1,11 @@
+@prefix ns: .
+@prefix owl: .
+
+ns:Duck a owl:Class .
+ns:duckCode a owl:DatatypeProperty .
+ns:d a owl:DatatypeProperty .
+ns:o a owl:ObjectProperty .
+ns:upcCode a owl:DatatypeProperty .
+ns:p a owl:ObjectProperty .
+ns:productCode a owl:DatatypeProperty .
+ns:q a owl:ObjectProperty .