From 6166b48357f3ebd8a0012b0581fd809e358c0011 Mon Sep 17 00:00:00 2001 From: j2blake Date: Fri, 27 Feb 2015 15:41:41 -0500 Subject: [PATCH] VIVO-946 Add labels of objects across Role nodes. --- .../searchIndexerConfigurationVivo.n3 | 24 +++- .../extensions/LabelsAcrossContextNodes.java | 109 +++++++++++++----- .../LabelsAcrossContextNodesTest.java | 3 + 3 files changed, 103 insertions(+), 33 deletions(-) diff --git a/rdf/display/everytime/searchIndexerConfigurationVivo.n3 b/rdf/display/everytime/searchIndexerConfigurationVivo.n3 index b085807c..4c7d4df8 100644 --- a/rdf/display/everytime/searchIndexerConfigurationVivo.n3 +++ b/rdf/display/everytime/searchIndexerConfigurationVivo.n3 @@ -15,10 +15,30 @@ # ------------------------------------ -:extension_forContextNodes +:extension_forContextNodes_1 a , , - . + ; + rdfs:label "Labels across relatedBy/relates" ; + :hasIncomingProperty "http://vivoweb.org/ontology/core#relatedBy" ; + :hasOutgoingProperty "http://vivoweb.org/ontology/core#relates" . + +:extension_forContextNodes_2 + a , + , + ; + rdfs:label "Labels across bearerOf/contributesTo" ; + :hasIncomingProperty "http://purl.obolibrary.org/obo/RO_0000053" ; + :hasOutgoingProperty "http://vivoweb.org/ontology/core#roleContributesTo" . + +:extension_forContextNodes_3 + a , + , + ; + rdfs:label "Labels across contributor/inheresIn" ; + :hasIncomingProperty "http://vivoweb.org/ontology/core#contributingRole" ; + :hasOutgoingProperty "http://purl.obolibrary.org/obo/RO_0000052" . + # ------------------------------------ diff --git a/src/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodes.java b/src/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodes.java index 35e983d0..95766a3e 100644 --- a/src/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodes.java +++ b/src/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodes.java @@ -36,8 +36,10 @@ import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation; * individual should include the labels of the partners across those nodes. The * labels will be added to the ALLTEXT and ALLTEXTUNSTEMMED fields. * - * We can add restrictions to say that this only applies to individuals of - * certain types. We can also restrict the type of the applicable context nodes. + * We must specify what property leads to a context node (incoming), and what + * property leads from a context node (outgoing). We may add restrictions to say + * that this only applies to individuals of certain types. We may also restrict + * the type of the applicable context nodes. * * An instance of this class acts as both a DocumentModifier and an * IndexingUriFinder: @@ -52,6 +54,8 @@ import edu.cornell.mannlib.vitro.webapp.utils.configuration.Validation; *
  * Configuration:
  *     rdfs:label -- Optional. Appears in the timings and debug statements.
+ *     :hasIncomingProperty -- Required. Property leading to the context node.
+ *     :hasOutgoingProperty -- Required. Property leading from the context node.
  *     :hasTypeRestriction -- Optional. Match any. If none, then no restriction.
  *     :appliesToContextNodeType -- Optional. Match any. If none, then no restriction.
  * 
@@ -69,6 +73,16 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, */ private String label; + /** + * The URI of the property that leads into the context node. Required. + */ + private String incomingPropertyUri; + + /** + * The URI of the property that leads from the context node. Required. + */ + private String outgoingPropertyUri; + /** * URIs of the types of individuals to whom this instance applies. * @@ -95,6 +109,28 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, label = l; } + @Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasIncomingProperty") + public void setIncomingProperty(String incomingUri) { + if (incomingPropertyUri == null) { + incomingPropertyUri = incomingUri; + } else { + throw new IllegalStateException( + "Configuration includes multiple declarations for hasIncomingProperty: " + + incomingPropertyUri + ", and " + incomingUri); + } + } + + @Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasOutgoingProperty") + public void setOutgoingProperty(String outgoingUri) { + if (outgoingPropertyUri == null) { + outgoingPropertyUri = outgoingUri; + } else { + throw new IllegalStateException( + "Configuration includes multiple declarations for hasOutgoingProperty: " + + outgoingPropertyUri + ", and " + outgoingUri); + } + } + @Property(uri = "http://vitro.mannlib.cornell.edu/ns/vitro/ApplicationSetup#hasTypeRestriction") public void addTypeRestriction(String typeUri) { typeRestrictions.add(typeUri); @@ -113,6 +149,14 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, formatRestrictions(typeRestrictions), formatRestrictions(contextNodeClasses)); } + if (incomingPropertyUri == null) { + throw new IllegalStateException( + "Configuration did not declare hasIncomingProperty."); + } + if (outgoingPropertyUri == null) { + throw new IllegalStateException( + "Configuration did not declare hasOutgoingProperty."); + } } private String formatRestrictions(Set uris) { @@ -146,23 +190,21 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, // ---------------------------------------------------------------------- private static final String LABELS_WITHOUT_RESTRICTION = "" - + "PREFIX vivo: \n" + "PREFIX rdfs: \n" + "SELECT ?label \n" // + "WHERE { \n" // - + " ?uri vivo:relatedBy ?contextNode . \n" // - + " ?contextNode vivo:relates ?partner . \n" // + + " ?uri ?incoming ?contextNode . \n" // + + " ?contextNode ?outgoing ?partner . \n" // + " ?partner rdfs:label ?label . \n" // + " FILTER( ?uri != ?partner ) \n" // + "} \n"; private static final String LABELS_FOR_SPECIFIC_CONTEXT_NODE_TYPE = "" - + "PREFIX vivo: \n" + "PREFIX rdfs: \n" + "SELECT ?label \n" // + "WHERE { \n" // - + " ?uri vivo:relatedBy ?contextNode . \n" // + + " ?uri ?incoming ?contextNode . \n" // + " ?contextNode a ?nodeType . \n" // - + " ?contextNode vivo:relates ?partner . \n" // + + " ?contextNode ?outgoing ?partner . \n" // + " ?partner rdfs:label ?label . \n" // + " FILTER( ?uri != ?partner ) \n" // + "} \n"; @@ -202,8 +244,10 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, SearchInputDocument doc) { addValuesToTextFields(doc, createQueryContext(rdfService, LABELS_WITHOUT_RESTRICTION) - .bindVariableToUri("uri", ind.getURI()).execute() - .getStringFields("label").flatten()); + .bindVariableToUri("uri", ind.getURI()) + .bindVariableToUri("incoming", incomingPropertyUri) + .bindVariableToUri("outgoing", outgoingPropertyUri) + .execute().getStringFields("label").flatten()); } private void addLabelsFromContextNodeClass(Individual ind, @@ -214,6 +258,8 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, LABELS_FOR_SPECIFIC_CONTEXT_NODE_TYPE) .bindVariableToUri("uri", ind.getURI()) .bindVariableToUri("nodeType", contextNodeClass) + .bindVariableToUri("incoming", incomingPropertyUri) + .bindVariableToUri("outgoing", outgoingPropertyUri) .execute().getStringFields("label").flatten()); } @@ -234,30 +280,25 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, // IndexingUriFinder // ---------------------------------------------------------------------- - private static final String URI_VIVO_RELATES = "http://vivoweb.org/ontology/core#relates"; - private static final String LOCATE_PARTNERS_WITHOUT_RESTRICTION = "" - + "PREFIX vivo: \n" + "SELECT ?partner \n" // + "WHERE { \n" // - + " ?uri vivo:relatedBy ?contextNode . \n" // - + " ?contextNode vivo:relates ?partner . \n" // + + " ?uri ?incoming ?contextNode . \n" // + + " ?contextNode ?outgoing ?partner . \n" // + " FILTER( ?uri != ?partner ) \n" // + "} \n"; private static final String LOCATE_PARTNERS_ON_CONTEXT_NODE_TYPE = "" - + "PREFIX vivo: \n" + "SELECT ?partner \n" // + "WHERE { \n" // - + " ?uri vivo:relatedBy ?contextNode . \n" // - + " ?contextNode vivo:relates ?partner . \n" // + + " ?uri ?incoming ?contextNode . \n" // + + " ?contextNode ?outgoing ?partner . \n" // + " ?contextNode a ?nodeType . \n" // + " FILTER( ?uri != ?partner ) \n" // + "} \n"; private static final String LOCATE_OTHER_PARTNERS_ON_THIS_NODE = "" - + "PREFIX vivo: \n" + "SELECT ?partner \n" // + "WHERE { \n" // - + " ?contextNode vivo:relates ?partner . \n" // + + " ?contextNode ?outgoing ?partner . \n" // + " FILTER( ?uri != ?partner ) \n" // + "} \n"; private static final String GET_TYPES = "" // @@ -275,17 +316,18 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, * If this is a "label" statement, check to see if the subject has any * acceptable partners across acceptable context nodes. * - * If this is a "relates" statement on an acceptable context node, check to - * see if there are any other acceptable partners on this node. + * If this is a statement that involves the specified outgoing property on + * an acceptable context node, check to see if there are any other + * acceptable partners on this node. * - * We could also check for "relatedBy" statements, but they should happen in - * pairs with the "relates" statements. + * We could also check for statements that involve the specified incoming + * property, but they should happen in pairs with the "outgoing" statements. */ @Override public List findAdditionalURIsToIndex(Statement stmt) { if (isLabelStatement(stmt)) { return filterByType(locatePartners(stmt)); - } else if (isRelatesStatementOnAcceptableContextNode(stmt)) { + } else if (isOutgoingStatementOnAcceptableContextNode(stmt)) { return filterByType(locateOtherPartners(stmt)); } return Collections.emptyList(); @@ -308,11 +350,13 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, return uris; } } - + private Set locatePartnersWithoutRestriction(String uri) { return createQueryContext(rdfService, LOCATE_PARTNERS_WITHOUT_RESTRICTION) - .bindVariableToUri("uri", uri).execute() + .bindVariableToUri("uri", uri) + .bindVariableToUri("incoming", incomingPropertyUri) + .bindVariableToUri("outgoing", outgoingPropertyUri).execute() .getStringFields("partner").flattenToSet(); } @@ -321,15 +365,17 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, return createQueryContext(rdfService, LOCATE_PARTNERS_ON_CONTEXT_NODE_TYPE) .bindVariableToUri("uri", uri) - .bindVariableToUri("nodeType", contextNodeClass).execute() + .bindVariableToUri("nodeType", contextNodeClass) + .bindVariableToUri("incoming", incomingPropertyUri) + .bindVariableToUri("outgoing", outgoingPropertyUri).execute() .getStringFields("partner").flattenToSet(); } - private boolean isRelatesStatementOnAcceptableContextNode(Statement stmt) { + private boolean isOutgoingStatementOnAcceptableContextNode(Statement stmt) { String subjectUri = stmt.getSubject().getURI(); String predicateUri = stmt.getPredicate().getURI(); - if (URI_VIVO_RELATES.equals(predicateUri) + if (outgoingPropertyUri.equals(predicateUri) && (contextNodeClasses.isEmpty() || isAnyMatch( contextNodeClasses, getTypes(subjectUri)))) { return true; @@ -362,7 +408,8 @@ public class LabelsAcrossContextNodes implements IndexingUriFinder, return createQueryContext(rdfService, LOCATE_OTHER_PARTNERS_ON_THIS_NODE) .bindVariableToUri("contextNode", nodeUri) - .bindVariableToUri("uri", objectUri).execute() + .bindVariableToUri("uri", objectUri) + .bindVariableToUri("outgoing", outgoingPropertyUri).execute() .getStringFields("partner").flattenToSet(); } diff --git a/test/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodesTest.java b/test/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodesTest.java index f3a20c33..a2b5d69d 100644 --- a/test/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodesTest.java +++ b/test/edu/cornell/mannlib/vitro/webapp/searchindex/extensions/LabelsAcrossContextNodesTest.java @@ -126,6 +126,9 @@ public class LabelsAcrossContextNodesTest extends AbstractTestClass { lacn = new LabelsAcrossContextNodes(); lacn.setContextModels(models); + lacn.setIncomingProperty(CORE_RELATED_BY); + lacn.setOutgoingProperty(CORE_RELATES); + lacn.validate(); } // ----------------------------------------------------------------------