Merge r5933:5935 and r5937 from nihvivo-rel-1.1-maint

This commit is contained in:
rjy7 2010-09-24 21:35:03 +00:00
parent 715fad38f4
commit 503652796c

View file

@ -63,15 +63,15 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
private static final int MAX_GROUP_DISPLAY_RANK = 99; private static final int MAX_GROUP_DISPLAY_RANK = 99;
/** Don't include these properties in the list. */ /** Don't include these properties in the list. */
private static final Collection<String> SUPPRESSED_OBJECT_PROPERTIES = Collections private static final Collection<String> SUPPRESSED_OBJECT_PROPERTIES = Collections
.unmodifiableCollection(Arrays .unmodifiableCollection(Arrays
.asList(new String[] { VitroVocabulary.IND_MAIN_IMAGE })); .asList(new String[] { VitroVocabulary.IND_MAIN_IMAGE }));
public void doGet( HttpServletRequest request, HttpServletResponse res ) public void doGet( HttpServletRequest request, HttpServletResponse res )
throws IOException, ServletException { throws IOException, ServletException {
VitroRequest req = new VitroRequest(request); VitroRequest req = new VitroRequest(request);
try { try {
super.doGet(req, res); super.doGet(req, res);
Object obj = req.getAttribute("entity"); Object obj = req.getAttribute("entity");
@ -118,12 +118,12 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
List<ObjectProperty> objectPropertyList = subject.getObjectPropertyList(); List<ObjectProperty> objectPropertyList = subject.getObjectPropertyList();
for (ObjectProperty op : objectPropertyList) { for (ObjectProperty op : objectPropertyList) {
if (!SUPPRESSED_OBJECT_PROPERTIES.contains(op)) { if (!SUPPRESSED_OBJECT_PROPERTIES.contains(op)) {
op.setEditLabel(op.getDomainPublic()); op.setEditLabel(op.getDomainPublic());
mergedPropertyList.add(op); mergedPropertyList.add(op);
}else{ }else{
log.debug("suppressed " + op.getURI()); log.debug("suppressed " + op.getURI());
} }
} }
if (editMode) { if (editMode) {
@ -215,10 +215,16 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
if (g.getPropertyList()!=null && g.getPropertyList().size()>0) { if (g.getPropertyList()!=null && g.getPropertyList().size()>0) {
for (Property p : g.getPropertyList()) { for (Property p : g.getPropertyList()) {
if (p instanceof ObjectProperty) { if (p instanceof ObjectProperty) {
ObjectProperty op = (ObjectProperty)p; ObjectProperty op = (ObjectProperty)p;
if (op.getObjectPropertyStatements()!=null && op.getObjectPropertyStatements().size()>0) { List<ObjectPropertyStatement> opStmts = op.getObjectPropertyStatements();
statementCount += op.getObjectPropertyStatements().size(); if (op.getObjectPropertyStatements()!=null && opStmts.size()>0) {
} statementCount += opStmts.size();
// If not collated, we need to apply custom sorting now.
applyCustomSortToUncollatedProperty(op, opStmts);
}
} }
} }
} }
@ -228,18 +234,26 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
} catch (Exception ex) { } 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());
} }
mergedPropertyList.clear(); mergedPropertyList.clear();
} else { // ungrouped mode
for (Property p : mergedPropertyList) {
if (p instanceof ObjectProperty) {
ObjectProperty op = (ObjectProperty)p;
applyCustomSortToUncollatedProperty(op, op.getObjectPropertyStatements());
}
}
} }
} }
if (groupedMode) { if (groupedMode) {
req.setAttribute("groupsList",groupsList); req.setAttribute("groupsList",groupsList);
} else { } else {
UnaryFunctor<List<Property>,List<Property>> entityPropertyListFilter = PropertyMaskingSetup.getEntityPropertyListFilter(getServletContext()); UnaryFunctor<List<Property>,List<Property>> entityPropertyListFilter = PropertyMaskingSetup.getEntityPropertyListFilter(getServletContext());
if (entityPropertyListFilter != null) { if (entityPropertyListFilter != null) {
mergedPropertyList = entityPropertyListFilter.fn(mergedPropertyList); mergedPropertyList = entityPropertyListFilter.fn(mergedPropertyList);
} }
req.setAttribute("mergedList",mergedPropertyList); req.setAttribute("mergedList",mergedPropertyList);
} }
@ -260,7 +274,7 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException { throws ServletException,IOException {
doGet(request, response); doGet(request, response);
} }
@ -299,7 +313,7 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
} }
switch (count) { switch (count) {
case 0: log.warn("groupsList has no groups on entering populateGroupsListWithProperties(); will create a new group \"other\""); case 0: log.warn("groupsList has no groups on entering populateGroupsListWithProperties(); will create a new group \"other\"");
break; break;
case 1: break; case 1: break;
default: try { default: try {
Collections.sort(groupsList); Collections.sort(groupsList);
@ -439,13 +453,20 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
private List<Property> collateBySubclass(List<Property> mergedPropertyList) { private List<Property> collateBySubclass(List<Property> mergedPropertyList) {
for( Property prop : mergedPropertyList){ for( Property prop : mergedPropertyList){
if( prop instanceof ObjectProperty && ((ObjectProperty)prop).getCollateBySubclass() ){ if( prop instanceof ObjectProperty ) {
collateBySubclass((ObjectProperty)prop); ObjectProperty op = (ObjectProperty) prop;
} if (op.getCollateBySubclass() ){
} log.debug("Collating property " + prop.getURI() + " by subclass");
return mergedPropertyList; collateBySubclass(op);
} } else {
}
}
}
return mergedPropertyList;
}
/** /**
* Sort the object property statements for each property so that they * Sort the object property statements for each property so that they
@ -454,128 +475,272 @@ public class EntityMergedPropertyListController extends VitroHttpServlet {
* This will be tricky since "subclass" is vaguely defined. Here directly * This will be tricky since "subclass" is vaguely defined. Here directly
* asserted classes are used. * asserted classes are used.
*/ */
private void collateBySubclass(ObjectProperty prop) { private void collateBySubclass(ObjectProperty prop) {
List<ObjectPropertyStatement> orgStmtList = prop.getObjectPropertyStatements(); List<ObjectPropertyStatement> orgStmtList = prop.getObjectPropertyStatements();
if( orgStmtList == null ) if( orgStmtList == null )
return; return;
Map<String,VClass> directClasses = getDirectClasses( getObjectsFromStmts( orgStmtList ) ); Map<String,VClass> directClasses = getDirectClasses( getObjectsFromStmts( orgStmtList ) );
//don't do collateBySubclass if there is only one class //don't do collateBySubclass if there is only one class
if( directClasses.size() < 2 ) if( directClasses.size() < 2 ) {
prop.setCollateBySubclass(false); //this overrides the value from the model prop.setCollateBySubclass(false); //this overrides the value from the model
else{ }
System.out.println("statements for object property: " + orgStmtList.size()); else{
//get list of direct classes and sort them log.debug("statements for object property: " + orgStmtList.size());
List<VClass> vclasses = new LinkedList<VClass>(directClasses.values()); //get list of direct classes and sort them
Collections.sort( List<VClass> vclasses = new LinkedList<VClass>(directClasses.values());
vclasses, Collections.sort(
new Comparator<VClass>(){ vclasses,
public int compare(VClass o1, VClass o2) { new Comparator<VClass>(){
return o1.getName().compareTo(o2.getName()); public int compare(VClass o1, VClass o2) {
} return o1.getName().compareTo(o2.getName());
}); }
});
//order object property statements by sorted direct class list
List<ObjectPropertyStatement> sortedStmtList = new LinkedList<ObjectPropertyStatement>(); //order object property statements by sorted direct class list
for (VClass clazz : vclasses) { List<ObjectPropertyStatement> sortedStmtList = new LinkedList<ObjectPropertyStatement>();
// get all obj prop stmts with objects of this class for (VClass clazz : vclasses) {
List<ObjectPropertyStatement> stmtsForClass = new ArrayList<ObjectPropertyStatement>(); // get all obj prop stmts with objects of this class
List<ObjectPropertyStatement> stmtsForClass = new ArrayList<ObjectPropertyStatement>();
System.out.println("statements for object property: " + orgStmtList.size());
Iterator<ObjectPropertyStatement> it = orgStmtList.iterator(); log.debug("statements for object property: " + orgStmtList.size());
while( it.hasNext()){ Iterator<ObjectPropertyStatement> it = orgStmtList.iterator();
ObjectPropertyStatement stmt = it.next(); while( it.hasNext()){
//if (stmt.getObject().getVClasses(true).contains(clazz)) { ObjectPropertyStatement stmt = it.next();
//if (stmt.getObject().getVClasses(true).contains(clazz)) {
Individual obj = stmt.getObject();
List<VClass> vclassesForObj = obj.getVClasses(true); Individual obj = stmt.getObject();
if (vclassesForObj != null && vclassesForObj.contains(clazz)) { List<VClass> vclassesForObj = obj.getVClasses(true);
System.out.println("adding " + stmt + " to class " if (vclassesForObj != null && vclassesForObj.contains(clazz)) {
+ clazz.getURI()); log.debug("adding " + stmt + " to class "
System.out.println("subjectURI " + stmt.getSubjectURI() + clazz.getURI());
+ " objectURI" + stmt.getObject().getURI()); log.debug("subjectURI " + stmt.getSubjectURI()
System.out.println("stmtsForclass size: " + " objectURI" + stmt.getObject().getURI());
+ stmtsForClass.size()); log.debug("stmtsForclass size: "
System.out.println("stmtsForclass size: " + stmtsForClass.size());
+ stmtsForClass.size()); log.debug("stmtsForclass size: "
+ stmtsForClass.size());
stmtsForClass.add(stmt);
} stmtsForClass.add(stmt);
} }
}
//bdc34: What do we do if a object individual is directly asserted to two different
//types? For now we just show them in whichever type shows up first. related to NIHVIVO-876 //bdc34: What do we do if a object individual is directly asserted to two different
orgStmtList.removeAll(stmtsForClass); //types? For now we just show them in whichever type shows up first. related to NIHVIVO-876
orgStmtList.removeAll(stmtsForClass);
Collections.sort(stmtsForClass,
new Comparator<ObjectPropertyStatement>() { sortStatements(prop, stmtsForClass);
public int compare(ObjectPropertyStatement o1,
ObjectPropertyStatement o2) { log.debug("stmtsForclass size after sort: "
return o1.getObject().getName().compareTo( + stmtsForClass.size());
o2.getObject().getName()); log.debug("sortedStmtList size before add: "
} + sortedStmtList.size());
});
System.out.println("stmtsForclass size after sort: " sortedStmtList.addAll(stmtsForClass);
+ stmtsForClass.size());
System.out.println("sortedStmtList size before add: " log.debug("sortedStmtList size after add: "
+ sortedStmtList.size()); + sortedStmtList.size());
sortedStmtList.addAll(stmtsForClass); }
System.out.println("sortedStmtList size after add: " prop.setObjectPropertyStatements(sortedStmtList);
+ sortedStmtList.size()); }
}
prop.setObjectPropertyStatements(sortedStmtList); }
}
}
private void sortStatements(ObjectProperty prop, List<ObjectPropertyStatement> statements) {
if (!applyCustomSort(prop, statements)) {
Collections.sort(statements,
new Comparator<ObjectPropertyStatement>() {
public int compare(ObjectPropertyStatement o1,
ObjectPropertyStatement o2) {
return o1.getObject().getName().compareTo(
o2.getObject().getName());
}
});
}
}
// rjy7 Quick and dirty fix to achieve custom sorting for specific properties in the VIVO ontology.
// See NIHVIVO-426, NIHVIVO-1158, NIHVIVO-1160. Some of these involve sorting on data properties of an
// individual two graph edges away from the individual being displayed, for which there is currently
// no provision. A better strategy will be designed and implemented in a later version, in particular
// one that does not involve hard-coded references to the VIVO ontology in the Vitro core.
private boolean applyCustomSort(ObjectProperty prop, List<ObjectPropertyStatement> statements) {
String vivoCoreOntology = "http://vivoweb.org/ontology/core#";
String propertyUri = prop.getURI();
// Positions in an organization
if (propertyUri.equals(vivoCoreOntology + "organizationForPosition")) {
sortByRelatedIndividualNames(statements, vivoCoreOntology + "positionForPerson");
return true;
}
// Person's positions
if (propertyUri.equals(vivoCoreOntology + "personInPosition")) {
sortReverseChron(statements, vivoCoreOntology + "endYear", vivoCoreOntology + "startYear");
return true;
}
// // Person's publications
// if (propertyUri.equals(vivoCoreOntology + "authorInAuthorship")) {
// sortByReverseChronAndRelatedIndividualName(statements, vivoCoreOntology + " ", vivoCoreOntology + " ");
// return true;
// }
return false;
}
private List<Individual> getObjectsFromStmts(List<ObjectPropertyStatement> orgStmtList) { // Apply custom sorting to an uncollated property. If the property is collated, the custom sorting has already
List<Individual> individuals = new LinkedList<Individual>(); // been applied to each subclass listing individually.
for( ObjectPropertyStatement stmt : orgStmtList ){ private void applyCustomSortToUncollatedProperty(ObjectProperty op, List<ObjectPropertyStatement> opStmts) {
individuals.add( stmt.getObject() ); // This includes the case where the ontology doesn't specify collating, as well as the case
} // where we don't collate because only one subclass is populated, since then we've set
return individuals; // the collation value to false.
} if (!op.getCollateBySubclass()) {
if (applyCustomSort(op, opStmts)) {
op.setObjectPropertyStatements(opStmts);
}
}
}
private void sortReverseChron(List<ObjectPropertyStatement> statements, String endYearPredicate, String startYearPredicate) {
// 1. Sort by end date descending, null dates first
// 2. Then by start date descending, null dates last
// 3. No sorting for entries with no start or end date - just put at the bottom in random order
final String endYearProperty = endYearPredicate;
final String startYearProperty = startYearPredicate;
Collections.sort(statements, new Comparator<ObjectPropertyStatement>() {
public int compare(ObjectPropertyStatement left, ObjectPropertyStatement right) {
String endLeftValue = left.getObject().getDataValue(endYearProperty);
Integer endLeft = endLeftValue == null ? null : Integer.valueOf(endLeftValue);
private Map<String,VClass> getDirectClasses(List<Individual> objectsFromStmts) { String startLeftValue = left.getObject().getDataValue(startYearProperty);
Map<String,VClass> directClasses = new HashMap<String,VClass>(); Integer startLeft = startLeftValue == null ? null : Integer.valueOf(startLeftValue);
String endRightValue = right.getObject().getDataValue(endYearProperty);
Integer endRight = endRightValue == null ? null : Integer.valueOf(endRightValue);
for (Individual ind : objectsFromStmts) { String startRightValue = right.getObject().getDataValue(startYearProperty);
for (VClass clazz : ind.getVClasses(true)) { Integer startRight = startRightValue == null ? null : Integer.valueOf(startRightValue);
directClasses.put(clazz.getURI(),clazz);
} // No sorting for entries with no start or end date - just put at the bottom in random order
} if (endLeft == null && startLeft == null) {
return directClasses; return 1;
} }
if (endRight == null && startRight == null) {
return -1;
}
// First sort by end date
// A null end date precedes
// But if both end dates are null, compare start dates
if ( ! (endLeft == null && endRight == null) ) {
if (endLeft == null) {
return -1;
}
if (endRight == null) {
return 1;
}
int endComp = endLeft.compareTo(endRight);
if (endComp != 0) {
return 0 - endComp;
}
}
// If end dates are equal, sort by start date
// A null start date follows
if (startLeft == null) {
return 1;
}
if (startRight == null) {
return -1;
}
return 0 - startLeft.compareTo(startRight);
}
});
}
// private void sortByReverseChronAndRelatedIndividualName(List<ObjectPropertyStatement> statements,
// String datePredicate, String relatedIndividualPredicate) {
//
// }
// Sort statements by the name of the individual on the other side of the context node.
private void sortByRelatedIndividualNames(List<ObjectPropertyStatement> statements, String predicateUri) {
log.debug("In sortByRelatedIndividualNames(), before sorting");
if (log.isDebugEnabled()) {
for (ObjectPropertyStatement ops : statements) {
log.debug(ops.getObject().getRelatedIndividual(predicateUri).getName());
}
}
final String propertyUri = predicateUri;
Collections.sort(statements, new Comparator<ObjectPropertyStatement>() {
public int compare(ObjectPropertyStatement left, ObjectPropertyStatement right) {
Individual indLeft = left.getObject().getRelatedIndividual(propertyUri);
Individual indRight = right.getObject().getRelatedIndividual(propertyUri);
return indLeft.getName().compareTo(indRight.getName());
}
});
log.debug("In sortByRelatedIndividualNames(), after sorting");
if (log.isDebugEnabled()) {
for (ObjectPropertyStatement ops : statements) {
log.debug(ops.getObject().getRelatedIndividual(predicateUri).getName());
}
}
}
/** private List<Individual> getObjectsFromStmts(List<ObjectPropertyStatement> orgStmtList) {
* Look for filter in servlet context and filter properties with it if there is one. List<Individual> individuals = new LinkedList<Individual>();
* for( ObjectPropertyStatement stmt : orgStmtList ){
* This allows a vitro instance to have specialized filtering for display. It was originally individuals.add( stmt.getObject() );
* created to deal with problems caused by custom short views. }
* * return individuals;
* @param objectPropertyList }
* @param wdf
* @return private Map<String,VClass> getDirectClasses(List<Individual> objectsFromStmts) {
*/ Map<String,VClass> directClasses = new HashMap<String,VClass>();
private Individual filterFromContext(Individual ind ) {
try{ for (Individual ind : objectsFromStmts) {
UnaryFunctor<Individual,Individual> filter = getMergedPropertyListFilter(getServletContext()); for (VClass clazz : ind.getVClasses(true)) {
if( filter == null ) directClasses.put(clazz.getURI(),clazz);
return ind; }
else }
return filter.fn(ind); return directClasses;
}catch(Throwable t){ }
log.error(t,t);
} /**
return ind; * Look for filter in servlet context and filter properties with it if there is one.
} *
* This allows a vitro instance to have specialized filtering for display. It was originally
public static void setMergedPropertyListFilter( UnaryFunctor<Individual,Individual>fn, ServletContext sc){ * created to deal with problems caused by custom short views.
sc.setAttribute("EntityMergedPropertyListController.toFilteringIndividual", fn); * *
} * @param objectPropertyList
* @param wdf
public static UnaryFunctor<Individual,Individual> getMergedPropertyListFilter( ServletContext sc){ * @return
return(UnaryFunctor<Individual,Individual>)sc.getAttribute("EntityMergedPropertyListController.toFilteringIndividual"); */
} private Individual filterFromContext(Individual ind ) {
try{
UnaryFunctor<Individual,Individual> filter = getMergedPropertyListFilter(getServletContext());
if( filter == null )
return ind;
else
return filter.fn(ind);
}catch(Throwable t){
log.error(t,t);
}
return ind;
}
public static void setMergedPropertyListFilter( UnaryFunctor<Individual,Individual>fn, ServletContext sc){
sc.setAttribute("EntityMergedPropertyListController.toFilteringIndividual", fn);
}
public static UnaryFunctor<Individual,Individual> getMergedPropertyListFilter( ServletContext sc){
return(UnaryFunctor<Individual,Individual>)sc.getAttribute("EntityMergedPropertyListController.toFilteringIndividual");
}
} }