diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java index 9e17ba90b..0208a9f70 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/GroupedPropertyList.java @@ -9,7 +9,6 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,85 +28,95 @@ import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; /* -public class GroupedPropertyList extends ArrayList { -If this class extends a List type, Freemarker does not let the templates call methods -on it. Since the class must then contain a list rather than be a list, the template -syntax is less idiomatic: e.g., groups.all rather than simply groups. An alternative -is to make the get methods (getProperty and getPropertyAndRemoveFromList) methods -of the IndividualTemplateModel. Then this class doesn't need methods, and can extend -a List type. -*/ + public class GroupedPropertyList extends ArrayList { + If this class extends a List type, Freemarker does not let the templates call methods + on it. Since the class must then contain a list rather than be a list, the template + syntax is less idiomatic: e.g., groups.all rather than simply groups. An alternative + is to make the get methods (getProperty and getPropertyAndRemoveFromList) methods + of the IndividualTemplateModel. Then this class doesn't need methods, and can extend + a List type. + */ public class GroupedPropertyList extends BaseTemplateModel { private static final long serialVersionUID = 1L; private static final Log log = LogFactory.getLog(GroupedPropertyList.class); private static final int MAX_GROUP_DISPLAY_RANK = 99; - + @SuppressWarnings("serial") - protected static final List VITRO_PROPS_TO_ADD_TO_LIST = new ArrayList() {{ - add(VitroVocabulary.IND_MAIN_IMAGE); - }}; - + protected static final List VITRO_PROPS_TO_ADD_TO_LIST = new ArrayList() { + { + add(VitroVocabulary.IND_MAIN_IMAGE); + } + }; + private final Individual subject; private final VitroRequest vreq; private final WebappDaoFactory wdf; private List groups; - - GroupedPropertyList(Individual subject, VitroRequest vreq, EditingPolicyHelper policyHelper) { + + GroupedPropertyList(Individual subject, VitroRequest vreq, + EditingPolicyHelper policyHelper) { this.vreq = vreq; this.subject = subject; this.wdf = vreq.getWebappDaoFactory(); - + boolean editing = policyHelper != null; - - // Create the property list for the subject. The properties will be put into groups later. + + // Create the property list for the subject. The properties will be put + // into groups later. List propertyList = new ArrayList(); - - // First get all the object properties that occur in statements in the db with this subject as subject. - // This may include properties that are not defined as "possible properties" for a subject of this class, + + // First get all the object properties that occur in statements in the + // db with this subject as subject. + // This may include properties that are not defined as + // "possible properties" for a subject of this class, // so we cannot just rely on getting that list. - List populatedObjectPropertyList = subject.getPopulatedObjectPropertyList(); + List populatedObjectPropertyList = subject + .getPopulatedObjectPropertyList(); propertyList.addAll(populatedObjectPropertyList); - + // If editing this page, merge in object properties applicable to the individual that are currently // unpopulated, so the properties are displayed to allow statements to be added to these properties. - // RY In future, we should limit this to properties that the user CAN add properties to. + // RY In future, we should limit this to properties that the user has permission to add properties to. if (editing) { - mergeAllPossibleObjectProperties(populatedObjectPropertyList, propertyList); + mergeAllPossibleObjectProperties(populatedObjectPropertyList, propertyList); } - + // Now do much the same with data properties: get the list of populated data properties, then add in placeholders for missing ones // rjy7 Currently we are getting the list of properties in one sparql query, then doing a separate query // to get values for each property. This could be optimized by doing a single query to get a map of properties to // DataPropertyStatements. Note that this does not apply to object properties, because the queries // can be customized and thus differ from property to property. So it's easier for now to keep the // two working in parallel. - List populatedDataPropertyList = subject.getPopulatedDataPropertyList(); + List populatedDataPropertyList = subject + .getPopulatedDataPropertyList(); propertyList.addAll(populatedDataPropertyList); - + if (editing) { - mergeAllPossibleDataProperties(propertyList); + mergeAllPossibleDataProperties(propertyList); } - - sort(propertyList); - - // Put the list into groups + + sort(propertyList); + + // Put the list into groups List propertyGroupList = addPropertiesToGroups(propertyList); - + // Build the template data model from the groupList - groups = new ArrayList(propertyGroupList.size()); - for (PropertyGroup propertyGroup: propertyGroupList) { - groups.add(new PropertyGroupTemplateModel(vreq, propertyGroup, subject, - policyHelper, populatedDataPropertyList, populatedObjectPropertyList)); - } - + groups = new ArrayList( + propertyGroupList.size()); + for (PropertyGroup propertyGroup : propertyGroupList) { + groups.add(new PropertyGroupTemplateModel(vreq, propertyGroup, + subject, policyHelper, populatedDataPropertyList, + populatedObjectPropertyList)); + } + if (!editing) { pruneEmptyProperties(); } - + } - + // It's possible that an 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 elements in queries.) @@ -116,7 +125,8 @@ public class GroupedPropertyList extends BaseTemplateModel { Iterator iGroups = groups.iterator(); while (iGroups.hasNext()) { PropertyGroupTemplateModel pgtm = iGroups.next(); - Iterator iProperties = pgtm.getProperties().iterator(); + Iterator iProperties = pgtm.getProperties() + .iterator(); while (iProperties.hasNext()) { PropertyTemplateModel property = iProperties.next(); if (property instanceof ObjectPropertyTemplateModel) { @@ -124,38 +134,44 @@ public class GroupedPropertyList extends BaseTemplateModel { // 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() ) { + if (((ObjectPropertyTemplateModel) property).isEmpty()) { iProperties.remove(); } } - } + } if (pgtm.isEmpty()) { iGroups.remove(); } - } + } } @SuppressWarnings("unchecked") - protected void sort(List propertyList) { + protected void sort(List propertyList) { try { Collections.sort(propertyList, new PropertyRanker(vreq)); } catch (Exception ex) { - log.error("Exception sorting merged property list: " + ex.getMessage()); + log.error("Exception sorting merged property list: " + + ex.getMessage()); } } - - private void mergeAllPossibleObjectProperties(List populatedObjectPropertyList, List propertyList) { - + + private void mergeAllPossibleObjectProperties( + List populatedObjectPropertyList, + List propertyList) { + // There is no ObjectPropertyDao.getAllPossibleObjectPropertiesForIndividual() parallel to // DataPropertyDao.getAllPossibleDatapropsForIndividual(). The comparable method for object properties // is defined using PropertyInstance rather than ObjectProperty. PropertyInstanceDao piDao = wdf.getPropertyInstanceDao(); - Collection allPropInstColl = piDao.getAllPossiblePropInstForIndividual(subject.getURI()); + Collection allPropInstColl = piDao + .getAllPossiblePropInstForIndividual(subject.getURI()); if (allPropInstColl != null) { for (PropertyInstance pi : allPropInstColl) { if (pi != null) { - if (! alreadyOnObjectPropertyList(populatedObjectPropertyList, pi)) { - addObjectPropertyToPropertyList(pi.getPropertyURI(), propertyList); + if (!alreadyOnObjectPropertyList( + populatedObjectPropertyList, pi)) { + addObjectPropertyToPropertyList(pi.getPropertyURI(), + propertyList); } } else { log.error("a property instance in the Collection created by PropertyInstanceDao.getAllPossiblePropInstForIndividual() is unexpectedly null"); @@ -163,19 +179,20 @@ public class GroupedPropertyList extends BaseTemplateModel { } } else { log.error("a null Collection is returned from PropertyInstanceDao.getAllPossiblePropInstForIndividual()"); - } - + } + // These properties are outside the ontologies (in vitro and vitro public) but need to be added to the list. // In future, vitro ns props will be phased out. Vitro public properties should be changed so they do not // constitute a special case (i.e., included in piDao.getAllPossiblePropInstForIndividual()). for (String propertyUri : VITRO_PROPS_TO_ADD_TO_LIST) { - if ( ! alreadyOnPropertyList(propertyList, propertyUri) ) { + if (!alreadyOnPropertyList(propertyList, propertyUri)) { addObjectPropertyToPropertyList(propertyUri, propertyList); - } + } } - } + } - private boolean alreadyOnObjectPropertyList(List opList, PropertyInstance pi) { + private boolean alreadyOnObjectPropertyList(List opList, + PropertyInstance pi) { if (pi.getPropertyURI() == null) { return false; } @@ -186,28 +203,30 @@ public class GroupedPropertyList extends BaseTemplateModel { } return false; } - - private void addObjectPropertyToPropertyList(String propertyUri, List propertyList) { + + private void addObjectPropertyToPropertyList(String propertyUri, + List propertyList) { ObjectPropertyDao opDao = wdf.getObjectPropertyDao(); ObjectProperty op = opDao.getObjectPropertyByURI(propertyUri); if (op == null) { log.error("ObjectProperty op returned null from opDao.getObjectPropertyByURI()"); } else if (op.getURI() == null) { log.error("ObjectProperty op returned with null propertyURI from opDao.getObjectPropertyByURI()"); - } else { + } else { propertyList.add(op); - } + } } - + protected void mergeAllPossibleDataProperties(List propertyList) { DataPropertyDao dpDao = wdf.getDataPropertyDao(); - Collection allDatapropColl = dpDao.getAllPossibleDatapropsForIndividual(subject.getURI()); + Collection allDatapropColl = dpDao + .getAllPossibleDatapropsForIndividual(subject.getURI()); if (allDatapropColl != null) { - for (DataProperty dp : allDatapropColl ) { - if (dp!=null) { + for (DataProperty dp : allDatapropColl) { + if (dp != null) { if (dp.getURI() == null) { log.error("DataProperty dp returned with null propertyURI from dpDao.getAllPossibleDatapropsForIndividual()"); - } else if (! alreadyOnPropertyList(propertyList, dp)) { + } else if (!alreadyOnPropertyList(propertyList, dp)) { propertyList.add(dp); } } else { @@ -216,173 +235,189 @@ public class GroupedPropertyList extends BaseTemplateModel { } } else { log.error("a null Collection is returned from DataPropertyDao.getAllPossibleDatapropsForIndividual())"); - } + } } - private boolean alreadyOnPropertyList(List propertyList, Property p) { + private boolean alreadyOnPropertyList(List propertyList, + Property p) { if (p.getURI() == null) { log.error("Property p has no propertyURI in alreadyOnPropertyList()"); return true; // don't add to list } return (alreadyOnPropertyList(propertyList, p.getURI())); } - - private boolean alreadyOnPropertyList(List propertyList, String propertyUri) { + + private boolean alreadyOnPropertyList(List propertyList, + String propertyUri) { for (Property p : propertyList) { String uri = p.getURI(); if (uri != null && uri.equals(propertyUri)) { return true; } } - return false; + return false; } - - private List addPropertiesToGroups(List propertyList) { - + + private List addPropertiesToGroups( + List propertyList) { + // Get the property groups - PropertyGroupDao pgDao = wdf.getPropertyGroupDao(); + PropertyGroupDao pgDao = wdf.getPropertyGroupDao(); List groupList = pgDao.getPublicGroups(false); // may be returned empty but not null - // To test no property groups defined, use: - // List groupList = new ArrayList(); - + // To test no property groups defined, use: + // List groupList = new ArrayList(); + int groupCount = groupList.size(); - - /* - * If no property groups are defined, create a dummy group with a null name to signal to the template that it's - * not a real group. This allows the looping structure in the template to be the same whether there are groups or not. + + /* + * If no property groups are defined, create a dummy group with a null + * name to signal to the template that it's not a real group. This + * allows the looping structure in the template to be the same whether + * there are groups or not. */ if (groupCount == 0) { log.warn("groupList has no groups on entering addPropertiesToGroups(); will create a new group"); PropertyGroup dummyGroup = pgDao.createDummyPropertyGroup(null, 1); dummyGroup.getPropertyList().addAll(propertyList); groupList.add(dummyGroup); - return groupList; - } - - /* - * This group will hold properties that are not assigned to any groups. In case no real property groups are - * populated, we end up with the dummy group case above, and we will change the name to null to signal to the - * template that it shouldn't be treated like a group. + return groupList; + } + + /* + * This group will hold properties that are not assigned to any groups. + * In case no real property groups are populated, we end up with the + * dummy group case above, and we will change the name to null to signal + * to the template that it shouldn't be treated like a group. */ - PropertyGroup groupForUnassignedProperties = pgDao.createDummyPropertyGroup("", MAX_GROUP_DISPLAY_RANK); - + PropertyGroup groupForUnassignedProperties = pgDao + .createDummyPropertyGroup("", MAX_GROUP_DISPLAY_RANK); + if (groupCount > 1) { try { Collections.sort(groupList); } catch (Exception ex) { log.error("Exception on sorting groupList in addPropertiesToGroups()"); - } + } } - - populateGroupListWithProperties(groupList, groupForUnassignedProperties, propertyList); - + + populateGroupListWithProperties(groupList, + groupForUnassignedProperties, propertyList); + // Remove unpopulated groups try { int removedCount = pgDao.removeUnpopulatedGroups(groupList); if (removedCount == 0) { - log.warn("Of "+groupCount+" groups, none removed by removeUnpopulatedGroups"); + log.warn("Of " + groupCount + + " groups, none removed by removeUnpopulatedGroups"); } - groupCount -= removedCount; + groupCount -= removedCount; } catch (Exception ex) { - log.error("Exception on trying to prune groups list with properties: "+ex.getMessage()); + log.error("Exception on trying to prune groups list with properties: " + + ex.getMessage()); } - - // If the group for unassigned properties is populated, add it to the group list. + + // If the group for unassigned properties is populated, add it to the + // group list. if (groupForUnassignedProperties.getPropertyList().size() > 0) { - groupList.add(groupForUnassignedProperties); - // If no real property groups are populated, the groupForUnassignedProperties moves from case 2 to case 1 above, so change - // the name to null to signal to the templates that there are no real groups. + groupList.add(groupForUnassignedProperties); + // If no real property groups are populated, the groupForUnassignedProperties + // moves from case 2 to case 1 above, so change the name to null + // to signal to the templates that there are no real groups. if (groupCount == 0) { groupForUnassignedProperties.setName(null); } } - + return groupList; } - - private void populateGroupListWithProperties(List groupList, - PropertyGroup groupForUnassignedProperties, List propertyList) { - + + private void populateGroupListWithProperties(List groupList, + PropertyGroup groupForUnassignedProperties, + List propertyList) { + // Clear out the property lists on the groups for (PropertyGroup pg : groupList) { - if (pg.getPropertyList().size()>0) { + if (pg.getPropertyList().size() > 0) { pg.getPropertyList().clear(); - } + } } - + // Assign the properties to the groups for (Property p : propertyList) { if (p.getURI() == null) { log.error("Property p has null URI in populateGroupListWithProperties()"); - // If the property is not assigned to any group, add it to the group for unassigned properties + // If the property is not assigned to any group, add it to the + // group for unassigned properties } else { - String groupUriForProperty = p.getGroupURI(); + String groupUriForProperty = p.getGroupURI(); boolean assignedToGroup = false; - + if (groupUriForProperty != null) { for (PropertyGroup pg : groupList) { - String groupUri = pg.getURI(); - if (groupUriForProperty.equals(groupUri)) { - pg.getPropertyList().add(p); - assignedToGroup = true; - break; - } + String groupUri = pg.getURI(); + if (groupUriForProperty.equals(groupUri)) { + pg.getPropertyList().add(p); + assignedToGroup = true; + break; + } } } - + // Either the property is not assigned to a group, or it is assigned to a group // not in the list (i.e., a non-existent group). - if (! assignedToGroup) { - if (groupForUnassignedProperties!=null) { + if (!assignedToGroup) { + if (groupForUnassignedProperties != null) { groupForUnassignedProperties.getPropertyList().add(p); - log.debug("adding property " + getLabel(p) + " to group for unassigned properties"); - } + log.debug("adding property " + getLabel(p) + + " to group for unassigned properties"); + } } - } - } + } + } } private class PropertyRanker implements Comparator { - + WebappDaoFactory wdf; PropertyGroupDao pgDao; - + private PropertyRanker(VitroRequest vreq) { this.wdf = vreq.getWebappDaoFactory(); this.pgDao = wdf.getPropertyGroupDao(); } - + public int compare(Property p1, Property p2) { - + int diff = determineDisplayRank(p1) - determineDisplayRank(p2); - if (diff==0) { + if (diff == 0) { return getLabel(p1).compareTo(getLabel(p2)); } else { return diff; } } - + private int determineDisplayRank(Property p) { if (p instanceof DataProperty) { - DataProperty dp = (DataProperty)p; + DataProperty dp = (DataProperty) p; return dp.getDisplayTier(); } else if (p instanceof ObjectProperty) { - ObjectProperty op = (ObjectProperty)p; - String tierStr = op.getDomainDisplayTier(); + ObjectProperty op = (ObjectProperty) p; + String tierStr = op.getDomainDisplayTier(); try { return Integer.parseInt(tierStr); } catch (NumberFormatException ex) { - log.error("Cannot decode object property display tier value "+tierStr+" as an integer"); + log.error("Cannot decode object property display tier value " + + tierStr + " as an integer"); } } else { - log.error("Property is of unknown class in PropertyRanker()"); + log.error("Property is of unknown class in PropertyRanker()"); } return 0; } } - - // Since we're now including some vitro properties in the property list, which don't have labels, - // use their local name instead. + + // Since we're now including some vitro properties in the property list, + // which don't have labels, use their local name instead. private String getLabel(Property property) { String label = property.getLabel(); if (label == null) { @@ -390,13 +425,13 @@ public class GroupedPropertyList extends BaseTemplateModel { } return label; } - + /* Access methods for templates */ - + public List getAll() { return groups; } - + public PropertyTemplateModel getProperty(String propertyUri) { for (PropertyGroupTemplateModel pgtm : groups) { @@ -406,31 +441,30 @@ public class GroupedPropertyList extends BaseTemplateModel { return ptm; } } - } + } return null; } public PropertyTemplateModel pullProperty(String propertyUri) { - + for (PropertyGroupTemplateModel pgtm : groups) { List properties = pgtm.getProperties(); for (PropertyTemplateModel ptm : properties) { - if (propertyUri.equals(ptm.getUri())) { + if (propertyUri.equals(ptm.getUri())) { // 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. + // NB Works with a for-each loop instead of an iterator, + // since iteration doesn't continue after the remove. properties.remove(ptm); // 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) { - groups.remove(pgtm); + groups.remove(pgtm); } return ptm; } } - } + } return null; } } -