diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java index cb4ea280a..ecdc2bfbc 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJena.java @@ -1014,14 +1014,14 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp if (uri.equals(propRegister.getURI())) { property = propRegister.clone(); } else { - property = getObjectPropertyByURI(uri); - if (property != null) { - propRegister = property; + ObjectProperty newProperty = getObjectPropertyByURI(uri); + if (newProperty != null) { + propRegister = newProperty; // add canonical instance of the property first in the list // before the range-changed versions - properties.add(property); + properties.add(newProperty); // isolate the canonical prop from what's about to happen next - property = property.clone(); + property = newProperty.clone(); } } if (property != null) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java index 7d5e88a60..bbc4de90d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyDaoJena.java @@ -595,17 +595,32 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { private void updatePropertyRangeMap(Map map, String propURI, - Resource[] ranges) { + Resource[] ranges, + boolean replaceIfMoreSpecific) { Resource[] existingRanges = map.get(propURI); if (existingRanges == null) { map.put(propURI, ranges); } else if (existingRanges[0] == null && existingRanges[1] != null) { existingRanges[0] = ranges[0]; map.put(propURI, existingRanges); - } else if (existingRanges[0] != null && existingRanges[1] == null) { - existingRanges[1] = ranges[1]; + } else if (existingRanges[0] != null) { + if (existingRanges[1] == null) { + existingRanges[1] = ranges[1]; + } + if (moreSpecificThan(ranges[0], existingRanges[0])) { + existingRanges[0] = ranges[0]; + } map.put(propURI, existingRanges); + } + } + + private boolean moreSpecificThan(Resource r1, Resource r2) { + if(r1.getURI() == null) { + return false; + } else if (r2.getURI() == null) { + return true; } + return getWebappDaoFactory().getVClassDao().isSubClassOf(r1.getURI(), r2.getURI()); } private List listSuperClasses(OntClass ontClass) { @@ -711,10 +726,11 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { Resource[] ranges = new Resource[2]; if (rest.isAllValuesFromRestriction()) { ranges[0] = (rest.asAllValuesFromRestriction()).getAllValuesFrom(); + updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges, true); } else if (rest.isSomeValuesFromRestriction()) { ranges[1] = (rest.asSomeValuesFromRestriction()).getSomeValuesFrom(); + updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges, false); } - updatePropertyRangeMap(applicableProperties, onProperty.getURI(), ranges); } } @@ -736,7 +752,7 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { Resource[] ranges = new Resource[2]; ranges[0] = rangeRes; updatePropertyRangeMap( - applicableProperties, prop.getURI(), ranges); + applicableProperties, prop.getURI(), ranges, false); } } @@ -831,9 +847,9 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { String domainURIStr = (domainRes != null && !domainRes.isAnon()) ? domainURIStr = domainRes.getURI() : null; - if (rangeRes == null) { - pi.setRangeClassURI(OWL.Thing.getURI()); // TODO see above - } else { +// if (rangeRes == null) { +// pi.setRangeClassURI(OWL.Thing.getURI()); // TODO see above + if(rangeRes != null) { String rangeClassURI; if (rangeRes.isAnon()) { rangeClassURI = PSEUDO_BNODE_NS + rangeRes.getId() 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 3c61f3b0b..1240285c3 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 @@ -105,7 +105,7 @@ public class GroupedPropertyList extends BaseTemplateModel { // 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 has permission to add properties to. if (editing) { - mergeAllPossibleObjectProperties(populatedObjectPropertyList, propertyList); + 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 @@ -122,9 +122,11 @@ public class GroupedPropertyList extends BaseTemplateModel { mergeAllPossibleDataProperties(propertyList); } - if (editing) { - propertyList = correctLanguageForProperties(propertyList); - } +// Not currently necessary since the language-specific version is now added +// during the merge +// if (editing) { +// propertyList = correctLanguageForProperties(propertyList); +// } sort(propertyList); @@ -253,7 +255,7 @@ public class GroupedPropertyList extends BaseTemplateModel { } } - private void mergeAllPossibleObjectProperties( + private List mergeAllPossibleObjectProperties( List populatedObjectPropertyList, List propertyList) { @@ -271,10 +273,27 @@ public class GroupedPropertyList extends BaseTemplateModel { if (allPropInstColl != null) { for (PropertyInstance pi : allPropInstColl) { if (pi != null) { - if (!alreadyOnObjectPropertyList( - populatedObjectPropertyList, pi)) { - addObjectPropertyToPropertyList(pi.getPropertyURI(), pi.getDomainClassURI(), pi.getRangeClassURI(), - propertyList); + // use the language-aware wdf because redundancy check + // for display will depend on public label match + ObjectProperty piOp = wdf.getObjectPropertyDao().getObjectPropertyByURIs( + pi.getPropertyURI(), pi.getDomainClassURI(), pi.getRangeClassURI()); + if (piOp == null) { + continue; + } + boolean addToList = true; + int opIndex = 0; + for(ObjectProperty op : populatedObjectPropertyList) { + if(redundant(op, piOp)) { + addToList = false; + if (moreRestrictiveRange(piOp, op, wadf)) { + propertyList = replaceOpWithPiOpInList(piOp, op, opIndex, propertyList); + } + break; + } + opIndex++; + } + if(addToList) { + propertyList.add(piOp); } } else { log.error("a property instance in the Collection created by PropertyInstanceDao.getAllPossiblePropInstForIndividual() is unexpectedly null"); @@ -292,35 +311,73 @@ public class GroupedPropertyList extends BaseTemplateModel { addObjectPropertyToPropertyList(propertyUri, null, null, propertyList); } } + + return propertyList; } - - private boolean alreadyOnObjectPropertyList(List opList, - PropertyInstance pi) { - if (pi.getPropertyURI() == null) { + + private boolean moreRestrictiveRange(ObjectProperty piOp, ObjectProperty op, + WebappDaoFactory wadf) { + if(piOp.getRangeVClassURI() == null) { + return false; + } else if (op.getRangeVClassURI() == null) { + return (piOp.getRangeVClassURI() != null); + } else { + return (wadf.getVClassDao().isSubClassOf( + piOp.getRangeVClassURI(), op.getRangeVClassURI())); + } + } + + private List replaceOpWithPiOpInList(ObjectProperty piOp, + ObjectProperty op, int opIndex, List propertyList) { + + List returnList = new ArrayList(); + int index = 0; + for(Property p : propertyList) { + if(index == opIndex /* p.equals(op) */) { + returnList.add(piOp); + } else { + returnList.add(p); + } + index++; + } + return returnList; + } + + private boolean redundant(ObjectProperty op, ObjectProperty op2) { + if (op2.getURI() == null) { return false; } - for (ObjectProperty op : opList) { - boolean uriMatches = (op.getURI() != null - && op.getURI().equals(pi.getPropertyURI())); - boolean domainMatches = false; - boolean rangeMatches = false; - if(op.getDomainVClassURI() == null) { - if(pi.getDomainClassURI() == null) { - domainMatches = true; - } - } else if (op.getDomainVClassURI().equals(pi.getDomainClassURI())) { - domainMatches = true; + boolean uriMatches = (op.getURI() != null + && op.getURI().equals(op2.getURI())); + boolean domainMatches = false; + boolean rangeMatches = false; + boolean labelMatches = false; + if(op.getDomainPublic() == null) { + if(op2.getDomainPublic() == null) { + labelMatches = true; } - if(op.getRangeVClassURI() == null) { - if (pi.getDomainClassURI() == null) { - rangeMatches = true; - } - } else if (op.getRangeVClassURI().equals(pi.getRangeClassURI())) { + } else if (op.getDomainPublic().equals(op2.getDomainPublic())) { + labelMatches = true; + } + if(uriMatches && labelMatches) { + return true; + } + if(op.getDomainVClassURI() == null) { + if(op2.getDomainVClassURI() == null) { + domainMatches = true; + } + } else if (op.getDomainVClassURI().equals(op2.getDomainVClassURI())) { + domainMatches = true; + } + if(op.getRangeVClassURI() == null) { + if (op2.getRangeVClassURI() == null) { rangeMatches = true; } - if (uriMatches && domainMatches && rangeMatches) { - return true; - } + } else if (op.getRangeVClassURI().equals(op2.getRangeVClassURI())) { + rangeMatches = true; + } + if (uriMatches && domainMatches && rangeMatches) { + return true; } return false; }