NIHVIVO-2186 Modify custom list view queries to filter out statements with no linked individual when user is not editing the page. Involves pruning the grouped property list of properties and groups which are thereby empty.
This commit is contained in:
parent
6ea23218c9
commit
f398183c94
6 changed files with 73 additions and 21 deletions
|
@ -82,6 +82,11 @@ public class CollatedObjectPropertyTemplateModel extends ObjectPropertyTemplateM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEmpty() {
|
||||||
|
return subclasses.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
protected ConfigError checkQuery(String queryString) {
|
protected ConfigError checkQuery(String queryString) {
|
||||||
|
|
||||||
if (StringUtils.isBlank(queryString)) {
|
if (StringUtils.isBlank(queryString)) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
@ -100,9 +101,40 @@ public class GroupedPropertyList extends BaseTemplateModel {
|
||||||
for (PropertyGroup propertyGroup: propertyGroupList) {
|
for (PropertyGroup propertyGroup: propertyGroupList) {
|
||||||
groups.add(new PropertyGroupTemplateModel(vreq, propertyGroup, subject,
|
groups.add(new PropertyGroupTemplateModel(vreq, propertyGroup, subject,
|
||||||
policyHelper, populatedDataPropertyList, populatedObjectPropertyList));
|
policyHelper, populatedDataPropertyList, populatedObjectPropertyList));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!editing) {
|
||||||
|
pruneEmptyProperties();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// It's possible that a collated object property retrieved in the call to getPopulatedObjectPropertyList()
|
||||||
|
// is now empty of statements, because if not editing, some statements without a linked individual
|
||||||
|
// are not retrieved by the query. (See <linked-individual-required> elements in queries.)
|
||||||
|
// Remove these properties, and also remove any groups with no remaining properties.
|
||||||
|
private void pruneEmptyProperties() {
|
||||||
|
Iterator<PropertyGroupTemplateModel> iGroups = groups.iterator();
|
||||||
|
while (iGroups.hasNext()) {
|
||||||
|
PropertyGroupTemplateModel pgtm = iGroups.next();
|
||||||
|
Iterator<PropertyTemplateModel> iProperties = pgtm.getProperties().iterator();
|
||||||
|
while (iProperties.hasNext()) {
|
||||||
|
PropertyTemplateModel property = iProperties.next();
|
||||||
|
if (property instanceof ObjectPropertyTemplateModel) {
|
||||||
|
// It's not necessary to do comparable pruning of the subclass list
|
||||||
|
// of a CollatedObjectPropertyTemplateModel, because the collated subclass
|
||||||
|
// list is compiled on the basis of existing statements. There will not
|
||||||
|
// be any empty subclasses.
|
||||||
|
if ( ( (ObjectPropertyTemplateModel) property).isEmpty() ) {
|
||||||
|
iProperties.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (pgtm.isEmpty()) {
|
||||||
|
iGroups.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected void sort(List<Property> propertyList) {
|
protected void sort(List<Property> propertyList) {
|
||||||
|
@ -417,14 +449,18 @@ public class GroupedPropertyList extends BaseTemplateModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public PropertyTemplateModel getPropertyAndRemoveFromList(String propertyUri) {
|
public PropertyTemplateModel getPropertyAndRemoveFromList(String propertyUri) {
|
||||||
|
|
||||||
for (PropertyGroupTemplateModel pgtm : groups) {
|
for (PropertyGroupTemplateModel pgtm : groups) {
|
||||||
List<PropertyTemplateModel> properties = pgtm.getProperties();
|
List<PropertyTemplateModel> properties = pgtm.getProperties();
|
||||||
for (PropertyTemplateModel ptm : properties) {
|
for (PropertyTemplateModel ptm : properties) {
|
||||||
if (propertyUri.equals(ptm.getUri())) {
|
if (propertyUri.equals(ptm.getUri())) {
|
||||||
// Remove the property from the group
|
// Remove the property from the group.
|
||||||
|
// NB Works with a for-each loop instead of an iterator, since
|
||||||
|
// iteration doesn't continue after the remove.
|
||||||
properties.remove(ptm);
|
properties.remove(ptm);
|
||||||
// If this is the only property in the group, remove the group as well
|
// If this is the only property in the group, remove the group as well.
|
||||||
|
// NB Works with a for-each loop instead of an iterator, since
|
||||||
|
// iteration doesn't continue after the remove.
|
||||||
if (properties.size() == 0) {
|
if (properties.size() == 0) {
|
||||||
groups.remove(pgtm);
|
groups.remove(pgtm);
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,6 +118,8 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract boolean isEmpty();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected int getPropertyDisplayTier(Property p) {
|
protected int getPropertyDisplayTier(Property p) {
|
||||||
// For some reason ObjectProperty.getDomainDisplayTier() returns a String
|
// For some reason ObjectProperty.getDomainDisplayTier() returns a String
|
||||||
|
@ -324,8 +326,8 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
||||||
private static final String NODE_NAME_QUERY_SELECT = "query-select";
|
private static final String NODE_NAME_QUERY_SELECT = "query-select";
|
||||||
private static final String NODE_NAME_TEMPLATE = "template";
|
private static final String NODE_NAME_TEMPLATE = "template";
|
||||||
private static final String NODE_NAME_POSTPROCESSOR = "postprocessor";
|
private static final String NODE_NAME_POSTPROCESSOR = "postprocessor";
|
||||||
private static final String NODE_NAME_COLLATION_FRAGMENT = "collation-fragment";
|
private static final String NODE_NAME_COLLATED = "collated";
|
||||||
private static final String NODE_NAME_LINKED_INDIVIDUAL_OPTIONAL = "linked-individual-optional";
|
private static final String NODE_NAME_LINKED_INDIVIDUAL_REQUIRED = "linked-individual-required";
|
||||||
|
|
||||||
/* NB The default post-processor is not the same as the post-processor for the default view. The latter
|
/* NB The default post-processor is not the same as the post-processor for the default view. The latter
|
||||||
* actually defines its own post-processor, whereas the default post-processor is used for custom views
|
* actually defines its own post-processor, whereas the default post-processor is used for custom views
|
||||||
|
@ -463,27 +465,27 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel
|
||||||
Node selectQueryNode = doc.getElementsByTagName(NODE_NAME_QUERY_SELECT).item(0);
|
Node selectQueryNode = doc.getElementsByTagName(NODE_NAME_QUERY_SELECT).item(0);
|
||||||
String value = null;
|
String value = null;
|
||||||
if (selectQueryNode != null) {
|
if (selectQueryNode != null) {
|
||||||
boolean removeCollationFragments = ObjectPropertyTemplateModel.this instanceof UncollatedObjectPropertyTemplateModel;
|
boolean collated = ObjectPropertyTemplateModel.this instanceof CollatedObjectPropertyTemplateModel;
|
||||||
/* If editing the page (policyHelper != null), show statements with missing linked individual; otherwise, hide these
|
/* If not editing the page (policyHelper == null), hide statements with missing linked individual; otherwise, show these
|
||||||
* statements. We might want to refine this based on whether the user can edit the statement in question, but that
|
* statements. We might want to refine this based on whether the user can edit the statement in question, but that
|
||||||
* would require a completely different approach: including the statement in the query results, and then during the
|
* would require a completely different approach: include the statement in the query results, and then during the
|
||||||
* postprocessing phase, checking the editing policy, and removing the statement if it's not editable. We would not
|
* postprocessing phase, check the editing policy, and remove the statement if it's not editable. We would not
|
||||||
* preprocess the query, as here.
|
* preprocess the query, as here.
|
||||||
*/
|
*/
|
||||||
boolean linkedIndividualOptional = policyHelper != null;
|
boolean linkedIndividualRequired = policyHelper == null;
|
||||||
NodeList children = selectQueryNode.getChildNodes();
|
NodeList children = selectQueryNode.getChildNodes();
|
||||||
int childCount = children.getLength();
|
int childCount = children.getLength();
|
||||||
value = "";
|
value = "";
|
||||||
for (int i = 0; i < childCount; i++) {
|
for (int i = 0; i < childCount; i++) {
|
||||||
Node node = children.item(i);
|
Node node = children.item(i);
|
||||||
if (node.getNodeName().equals(NODE_NAME_COLLATION_FRAGMENT)) {
|
if (node.getNodeName().equals(NODE_NAME_COLLATED)) {
|
||||||
if (!removeCollationFragments) {
|
if (collated) {
|
||||||
value += node.getChildNodes().item(0).getNodeValue();
|
value += node.getChildNodes().item(0).getNodeValue();
|
||||||
}
|
} // else ignore this node
|
||||||
} else if (node.getNodeName().equals(NODE_NAME_LINKED_INDIVIDUAL_OPTIONAL)) {
|
} else if (node.getNodeName().equals(NODE_NAME_LINKED_INDIVIDUAL_REQUIRED)) {
|
||||||
if (linkedIndividualOptional) {
|
if (linkedIndividualRequired) {
|
||||||
value += node.getChildNodes().item(0).getNodeValue();
|
value += node.getChildNodes().item(0).getNodeValue();
|
||||||
}
|
} // else ignore this node
|
||||||
} else {
|
} else {
|
||||||
value += node.getNodeValue();
|
value += node.getNodeValue();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,6 +40,10 @@ public class PropertyGroupTemplateModel extends BaseTemplateModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isEmpty() {
|
||||||
|
return properties.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
protected void remove(PropertyTemplateModel ptm) {
|
protected void remove(PropertyTemplateModel ptm) {
|
||||||
properties.remove(ptm);
|
properties.remove(ptm);
|
||||||
|
|
|
@ -55,6 +55,11 @@ public class UncollatedObjectPropertyTemplateModel extends ObjectPropertyTemplat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isEmpty() {
|
||||||
|
return statements.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
/* Access methods for templates */
|
/* Access methods for templates */
|
||||||
|
|
||||||
public List<ObjectPropertyStatementTemplateModel> getStatements() {
|
public List<ObjectPropertyStatementTemplateModel> getStatements() {
|
||||||
|
|
|
@ -11,15 +11,15 @@
|
||||||
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
|
||||||
PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
|
PREFIX afn: <http://jena.hpl.hp.com/ARQ/function#>
|
||||||
|
|
||||||
SELECT <collation-fragment> ?subclass </collation-fragment>
|
SELECT <collated> ?subclass </collated>
|
||||||
?object ?name ?moniker WHERE {
|
?object ?name ?moniker WHERE {
|
||||||
?subject ?property ?object
|
?subject ?property ?object
|
||||||
<collation-fragment> OPTIONAL { ?object a ?subclass }
|
<collated> OPTIONAL { ?object a ?subclass }
|
||||||
FILTER ( afn:namespace(?subclass) != "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#" )
|
FILTER ( afn:namespace(?subclass) != "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#" )
|
||||||
</collation-fragment>
|
</collated>
|
||||||
OPTIONAL { ?object rdfs:label ?name }
|
OPTIONAL { ?object rdfs:label ?name }
|
||||||
OPTIONAL { ?object vitro:moniker ?moniker }
|
OPTIONAL { ?object vitro:moniker ?moniker }
|
||||||
} ORDER BY <collation-fragment> ?subclass </collation-fragment> ?name ?object
|
} ORDER BY <collated> ?subclass </collated> ?name ?object
|
||||||
</query-select>
|
</query-select>
|
||||||
|
|
||||||
<query-construct>
|
<query-construct>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue