From 10dc4d3e1fbe65a372ab8c9a1c7fe45a7ac1b3c6 Mon Sep 17 00:00:00 2001 From: rjy7 Date: Wed, 1 Dec 2010 22:28:54 +0000 Subject: [PATCH] NIHVIVO-1333 Lots of work on display of ontology properties on individual page (nothing visible yet). --- .../vitro/webapp/beans/Individual.java | 6 + .../vitro/webapp/beans/IndividualImpl.java | 14 ++ .../vitro/webapp/dao/DataPropertyDao.java | 6 +- .../vitro/webapp/dao/ObjectPropertyDao.java | 6 +- .../vitro/webapp/dao/PropertyListDao.java | 15 -- .../vitro/webapp/dao/WebappDaoFactory.java | 2 - .../filtering/DataPropertyDaoFiltering.java | 15 ++ .../dao/filtering/IndividualFiltering.java | 37 ++- .../filtering/ObjectPropertyDaoFiltering.java | 14 +- .../filtering/WebappDaoFactoryFiltering.java | 11 +- .../webapp/dao/jena/DataPropertyDaoJena.java | 57 ++++- .../vitro/webapp/dao/jena/IndividualJena.java | 17 ++ .../vitro/webapp/dao/jena/IndividualSDB.java | 16 ++ .../vitro/webapp/dao/jena/IndividualSDB2.java | 10 +- .../dao/jena/ObjectPropertyDaoJena.java | 53 ++++ .../webapp/dao/jena/PropertyDaoJena.java | 34 ++- .../webapp/dao/jena/PropertyListDaoJena.java | 74 ------ .../webapp/dao/jena/WebappDaoFactoryJena.java | 11 +- .../individual/CollatedObjectProperty.java | 17 +- .../individual/DataPropertyTemplateModel.java | 18 +- .../individual/GroupedPropertyList.java | 71 ++---- .../individual/IndividualTemplateModel.java | 6 +- .../ObjectPropertyTemplateModel.java | 20 +- .../individual/PropertyList.java | 234 ++++++++++++++++++ .../individual/PropertyListBuilder.java | 177 +++++++++++-- .../individual/PropertyTemplateModel.java | 20 +- .../individual/UncollatedObjectProperty.java | 17 +- .../dao/jena/DataPropertyDaoJenaTest.java | 8 +- .../dao/jena/ObjectPropertyDaoJenaTest.java | 8 +- .../freemarker/body/individual/individual.ftl | 2 +- 30 files changed, 775 insertions(+), 221 deletions(-) delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/dao/PropertyListDao.java delete mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyListDaoJena.java create mode 100644 webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyList.java diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/Individual.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/Individual.java index 422a1cb88..bc299f87d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/Individual.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/Individual.java @@ -46,12 +46,18 @@ public interface Individual extends ResourceBean, VitroTimeWindowedResource, Com List getObjectPropertyList(); void setPropertyList(List propertyList); + List getPopulatedObjectPropertyList(); + void setPopulatedObjectPropertyList(List propertyList); + Map getObjectPropertyMap(); void setObjectPropertyMap(Map propertyMap); List getDataPropertyList(); void setDatatypePropertyList(List datatypePropertyList); + List getPopulatedDataPropertyList(); + void setPopulatedDataPropertyList(List dataPropertyList); + Map getDataPropertyMap(); void setDataPropertyMap(Map propertyMap); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/IndividualImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/IndividualImpl.java index dc2183b7c..876887396 100755 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/IndividualImpl.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/beans/IndividualImpl.java @@ -36,8 +36,10 @@ public class IndividualImpl extends BaseResourceBean implements Individual, Comp protected Date timekey = null; protected Timestamp modTime = null; protected List propertyList = null; + protected List populatedObjectPropertyList = null; protected Map objectPropertyMap = null; protected List datatypePropertyList = null; + protected List populatedDataPropertyList = null; protected Map dataPropertyMap = null; protected List dataPropertyStatements = null; protected List objectPropertyStatements = null; @@ -118,6 +120,12 @@ public class IndividualImpl extends BaseResourceBean implements Individual, Comp public void setPropertyList(List propertyList) { this.propertyList = propertyList; } + public List getPopulatedObjectPropertyList() { + return populatedObjectPropertyList; + } + public void setPopulatedObjectPropertyList(List propertyList) { + populatedObjectPropertyList = propertyList; + } public Map getObjectPropertyMap() { return this.objectPropertyMap; } @@ -130,6 +138,12 @@ public class IndividualImpl extends BaseResourceBean implements Individual, Comp public void setDatatypePropertyList(List datatypePropertyList) { this.datatypePropertyList = datatypePropertyList; } + public List getPopulatedDataPropertyList() { + return populatedDataPropertyList; + } + public void setPopulatedDataPropertyList(List propertyList) { + populatedDataPropertyList = propertyList; + } public Map getDataPropertyMap() { return this.dataPropertyMap; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DataPropertyDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DataPropertyDao.java index e0c67cb7d..02f1c7360 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DataPropertyDao.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/DataPropertyDao.java @@ -34,5 +34,9 @@ public interface DataPropertyDao extends PropertyDao { List getRootDataProperties(); - boolean annotateDataPropertyAsExternalIdentifier(String dataPropertyURI); + boolean annotateDataPropertyAsExternalIdentifier(String dataPropertyURI); + + public List getDataPropertyList(Individual subject); + + public List getDataPropertyList(String subjectUri); } \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyDao.java index 0cb323977..9a966351b 100755 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyDao.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/ObjectPropertyDao.java @@ -50,5 +50,9 @@ public interface ObjectPropertyDao extends PropertyDao { // List /* of ObjectProperty */ getAllObjectProperties(); - List getRootObjectProperties(); + List getRootObjectProperties(); + + public List getObjectPropertyList(Individual subject); + + public List getObjectPropertyList(String subjectUri); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/PropertyListDao.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/PropertyListDao.java deleted file mode 100644 index acd42f18f..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/PropertyListDao.java +++ /dev/null @@ -1,15 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.dao; - -import java.util.List; - -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.Property; - -public interface PropertyListDao { - - public List getPropertyListForSubject(Individual subject); - - public List getPropertyListForSubject(String subjectUri); -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java index 9fc952828..897ca9ef8 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/WebappDaoFactory.java @@ -132,6 +132,4 @@ public interface WebappDaoFactory { public NamespaceDao getNamespaceDao(); public PropertyInstanceDao getPropertyInstanceDao(); - - public PropertyListDao getPropertyListDao(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java index 19aad491e..311fde3d6 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/DataPropertyDaoFiltering.java @@ -5,6 +5,9 @@ package edu.cornell.mannlib.vitro.webapp.dao.filtering; import java.util.Collection; import java.util.List; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; + import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; @@ -188,5 +191,17 @@ class DataPropertyDaoFiltering extends BaseFiltering implements DataPropertyDao{ public List getClassesWithRestrictionOnProperty(String propertyURI) { return innerDataPropertyDao.getClassesWithRestrictionOnProperty(propertyURI); } + + @Override + // This may need to be filtered at some point. + public List getDataPropertyList(Individual subject) { + return innerDataPropertyDao.getDataPropertyList(subject); + } + + @Override + // This may need to be filtered at some point. + public List getDataPropertyList(String subjectUri) { + return innerDataPropertyDao.getDataPropertyList(subjectUri); + } } \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualFiltering.java index 6464df13f..dca2263d8 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/IndividualFiltering.java @@ -70,7 +70,27 @@ public class IndividualFiltering implements Individual { return outdProps; } - + public List getPopulatedDataPropertyList() { + List dprops = _innerIndividual.getPopulatedDataPropertyList(); + LinkedList outdProps = new LinkedList(); + Filter.filter(dprops,_filters.getDataPropertyFilter(), outdProps); + + ListIterator it = outdProps.listIterator(); + while(it.hasNext()){ + DataProperty dp = it.next(); + List filteredStmts = + new LinkedList(); + Filter.filter(dp.getDataPropertyStatements(), + _filters.getDataPropertyStatementFilter(),filteredStmts); + if( filteredStmts == null || filteredStmts.size() == 0 ){ + it.remove(); + }else{ + dp.setDataPropertyStatements(filteredStmts); + } + } + return outdProps; + } + public List getDataPropertyStatements() { List dstmts = _innerIndividual.getDataPropertyStatements(); return filterDataPropertyStatements(dstmts); @@ -112,6 +132,13 @@ public class IndividualFiltering implements Individual { public List getObjectPropertyList() { List oprops = _innerIndividual.getObjectPropertyList(); // List outOProps = new LinkedList(); +// Filter.filter(oprops, _filters.getObjectPropertyFilter(), outOProps); + return ObjectPropertyDaoFiltering.filterAndWrap(oprops, _filters); + } + + public List getPopulatedObjectPropertyList() { + List oprops = _innerIndividual.getPopulatedObjectPropertyList(); +// List outOProps = new LinkedList(); // Filter.filter(oprops, _filters.getObjectPropertyFilter(), outOProps); return ObjectPropertyDaoFiltering.filterAndWrap(oprops, _filters); } @@ -360,6 +387,10 @@ public class IndividualFiltering implements Individual { _innerIndividual.setDatatypePropertyList(datatypePropertyList); } + public void setPopulatedDataPropertyList(List dataPropertyList) { + _innerIndividual.setPopulatedDataPropertyList(dataPropertyList); + } + public void setDescription(String in) { _innerIndividual.setDescription(in); } @@ -452,6 +483,10 @@ public class IndividualFiltering implements Individual { _innerIndividual.setPropertyList(propertyList); } + public void setPopulatedObjectPropertyList(List propertyList) { + _innerIndividual.setPopulatedObjectPropertyList(propertyList); + } + public void setStatus(String s) { _innerIndividual.setStatus(s); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java index 9d1ba0b43..2db06994f 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/ObjectPropertyDaoFiltering.java @@ -9,6 +9,7 @@ import java.util.List; import net.sf.jga.algorithms.Filter; import net.sf.jga.fn.UnaryFunctor; import net.sf.jga.fn.adaptor.AndUnary; +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; @@ -201,5 +202,16 @@ class ObjectPropertyDaoFiltering extends BaseFiltering implements ObjectProperty public List getClassesWithRestrictionOnProperty(String propertyURI) { return innerObjectPropertyDao.getClassesWithRestrictionOnProperty(propertyURI); } - + + @Override + // This may need to be filtered at some point. + public List getObjectPropertyList(Individual subject) { + return innerObjectPropertyDao.getObjectPropertyList(subject); + } + + @Override + // This may need to be filtered at some point. + public List getObjectPropertyList(String subjectUri) { + return innerObjectPropertyDao.getObjectPropertyList(subjectUri); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java index d3f13613a..22144b3a3 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/filtering/WebappDaoFactoryFiltering.java @@ -24,7 +24,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao; import edu.cornell.mannlib.vitro.webapp.dao.PortalDao; import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao; import edu.cornell.mannlib.vitro.webapp.dao.PropertyInstanceDao; -import edu.cornell.mannlib.vitro.webapp.dao.PropertyListDao; import edu.cornell.mannlib.vitro.webapp.dao.TabDao; import edu.cornell.mannlib.vitro.webapp.dao.TabIndividualRelationDao; import edu.cornell.mannlib.vitro.webapp.dao.TabVClassRelationDao; @@ -215,6 +214,11 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory { return innerWebappDaoFactory.getPortalDao(); } +/////////////////////////////////////////////////////////////////// + + + /* ******************* non-filtering DAOs *************************** */ + public Classes2ClassesDao getClasses2ClassesDao() { return innerWebappDaoFactory.getClasses2ClassesDao(); } @@ -230,11 +234,6 @@ public class WebappDaoFactoryFiltering implements WebappDaoFactory { public OntologyDao getOntologyDao() { return innerWebappDaoFactory.getOntologyDao(); } - - // rjy7 This may actually need to be filtered... - public PropertyListDao getPropertyListDao() { - return innerWebappDaoFactory.getPropertyListDao(); - } /* ******************* filtering DAOs *************************** */ diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java index b58b0b68b..cf71dc431 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJena.java @@ -22,6 +22,13 @@ import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.ontology.ProfileException; import com.hp.hpl.jena.ontology.Restriction; import com.hp.hpl.jena.ontology.SomeValuesFromRestriction; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.QuerySolutionMap; +import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; @@ -38,6 +45,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.BaseResourceBean; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.DataPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.Ontology; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; @@ -52,7 +60,28 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements DataPropertyDao { protected static final Log log = LogFactory.getLog(DataPropertyDaoJena.class.getName()); - + + protected static final String dataPropertyQueryString = + PREFIXES + "\n" + + "SELECT DISTINCT ?predicate WHERE { \n" + + //" GRAPH ?g {\n" + + " ?subject ?predicate ?object . \n" + + " ?predicate rdf:type owl:DatatypeProperty . \n" + + //" OPTIONAL { ?predicate vitro:inPropertyGroupAnnot ?group } . \n" + + //" }\n" + + "}" + + "ORDER BY ?predicate\n"; + + static protected Query dataPropertyQuery; + static { + try { + dataPropertyQuery = QueryFactory.create(dataPropertyQueryString); + } catch(Throwable th){ + log.error("could not create SPARQL query for dataPropertyQueryString " + th.getMessage()); + log.error(dataPropertyQueryString); + } + } + private class DataPropertyRanker implements Comparator { public int compare (Object o1, Object o2) { DataProperty dp1 = (DataProperty) o1; @@ -680,4 +709,30 @@ public class DataPropertyDaoJena extends PropertyDaoJena implements return rootProperties; } + @Override + public List getDataPropertyList(Individual subject) { + return getDataPropertyList(subject.getURI()); + } + + @Override + public List getDataPropertyList(String subjectUri) { + log.debug("dataPropertyQuery:\n" + dataPropertyQuery); + ResultSet results = getPropertyQueryResults(subjectUri, dataPropertyQuery); + List properties = new ArrayList(); + while (results.hasNext()) { + QuerySolution sol = results.next(); + Resource resource = sol.getResource("predicate"); + // This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces. + // It will be implemented in a better way in v1.3 (Editing and Display Configuration). + // It must be done here rather than in PropertyList or PropertyListBuilder, because + // those properties must be removed for the IndividualFiltering object. + if ( ! EXCLUDED_NAMESPACES.contains(resource.getNameSpace())) { + String uri = resource.getURI(); + DataProperty property = getDataPropertyByURI(uri); + properties.add(property); + } + } + return properties; + } + } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java index d0c6dfa90..56eaf5fc1 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualJena.java @@ -43,6 +43,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatementImpl; import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao; import edu.cornell.mannlib.vitro.webapp.dao.VClassDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.filestorage.model.ImageInfo; @@ -735,6 +736,14 @@ public class IndividualJena extends IndividualImpl implements Individual { return this.propertyList; } } + + @Override + public List getPopulatedObjectPropertyList() { + if (populatedObjectPropertyList == null) { + populatedObjectPropertyList = webappDaoFactory.getObjectPropertyDao().getObjectPropertyList(this); + } + return populatedObjectPropertyList; + } @Override public Map getObjectPropertyMap() { @@ -782,6 +791,14 @@ public class IndividualJena extends IndividualImpl implements Individual { } } + @Override + public List getPopulatedDataPropertyList() { + if (populatedDataPropertyList == null) { + populatedDataPropertyList = webappDaoFactory.getDataPropertyDao().getDataPropertyList(this); + } + return populatedDataPropertyList; + } + @Override public Map getDataPropertyMap() { if (this.dataPropertyMap != null) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java index 37a1bde51..94cc70211 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB.java @@ -880,6 +880,14 @@ public class IndividualSDB extends IndividualImpl implements Individual { return this.propertyList; } } + + @Override + public List getPopulatedObjectPropertyList() { + if (populatedObjectPropertyList == null) { + populatedObjectPropertyList = webappDaoFactory.getObjectPropertyDao().getObjectPropertyList(this); + } + return populatedObjectPropertyList; + } @Override public Map getObjectPropertyMap() { @@ -926,6 +934,14 @@ public class IndividualSDB extends IndividualImpl implements Individual { return this.datatypePropertyList; } } + + @Override + public List getPopulatedDataPropertyList() { + if (populatedDataPropertyList == null) { + populatedDataPropertyList = webappDaoFactory.getDataPropertyDao().getDataPropertyList(this); + } + return populatedDataPropertyList; + } @Override public Map getDataPropertyMap() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB2.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB2.java index 31b4de176..44cd40986 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB2.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/IndividualSDB2.java @@ -868,7 +868,15 @@ public class IndividualSDB2 extends IndividualImpl implements Individual { return this.propertyList; } } - + + @Override + public List getPopulatedObjectPropertyList() { + if (populatedObjectPropertyList == null) { + populatedObjectPropertyList = webappDaoFactory.getObjectPropertyDao().getObjectPropertyList(this); + } + return populatedObjectPropertyList; + } + @Override public Map getObjectPropertyMap() { if (this.objectPropertyMap != null) { 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 60ebad4d7..a450b0837 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 @@ -17,6 +17,11 @@ import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntProperty; import com.hp.hpl.jena.ontology.OntResource; import com.hp.hpl.jena.ontology.ProfileException; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.ResultSet; +import com.hp.hpl.jena.rdf.model.Literal; import com.hp.hpl.jena.rdf.model.Property; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; @@ -43,6 +48,27 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectPropertyDao { private static final Log log = LogFactory.getLog(ObjectPropertyDaoJena.class.getName()); + protected static final String objectPropertyQueryString = + PREFIXES + "\n" + + "SELECT DISTINCT ?predicate WHERE { \n" + + //" GRAPH ?g {\n" + + " ?subject ?predicate ?object . \n" + + " ?predicate rdf:type owl:ObjectProperty . \n" + + //" OPTIONAL { ?predicate vitro:inPropertyGroupAnnot ?group } . \n" + + //" }\n" + + "}" + + "ORDER BY ?predicate\n"; + + static protected Query objectPropertyQuery; + static { + try { + objectPropertyQuery = QueryFactory.create(objectPropertyQueryString); + } catch(Throwable th){ + log.error("could not create SPARQL query for objectPropertyQueryString " + th.getMessage()); + log.error(objectPropertyQueryString); + } + } + public ObjectPropertyDaoJena(WebappDaoFactoryJena wadf) { super(wadf); } @@ -799,4 +825,31 @@ public class ObjectPropertyDaoJena extends PropertyDaoJena implements ObjectProp return false; } + @Override + public List getObjectPropertyList(Individual subject) { + return getObjectPropertyList(subject.getURI()); + } + + @Override + public List getObjectPropertyList(String subjectUri) { + log.debug("objectPropertyQuery:\n" + objectPropertyQuery); + ResultSet results = getPropertyQueryResults(subjectUri, objectPropertyQuery); + List properties = new ArrayList(); + while (results.hasNext()) { + QuerySolution sol = results.next(); + Resource resource = sol.getResource("predicate"); + // This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces. + // It will be implemented in a better way in v1.3 (Editing and Display Configuration). + // It must be done here rather than in PropertyList or PropertyListBuilder, because + // those properties must be removed for the IndividualFiltering object. + if ( ! EXCLUDED_NAMESPACES.contains(resource.getNameSpace())) { + String uri = resource.getURI(); + ObjectProperty property = getObjectPropertyByURI(uri); + properties.add(property); + } + } + return properties; + } + + } 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 765659d4a..b1133e1c1 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 @@ -3,6 +3,7 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; @@ -14,8 +15,15 @@ import org.apache.commons.logging.LogFactory; import com.hp.hpl.jena.ontology.OntClass; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntProperty; +import com.hp.hpl.jena.query.Query; +import com.hp.hpl.jena.query.QueryExecution; +import com.hp.hpl.jena.query.QueryExecutionFactory; +import com.hp.hpl.jena.query.QuerySolution; +import com.hp.hpl.jena.query.QuerySolutionMap; +import com.hp.hpl.jena.query.ResultSet; import com.hp.hpl.jena.rdf.model.RDFNode; import com.hp.hpl.jena.rdf.model.Resource; +import com.hp.hpl.jena.rdf.model.ResourceFactory; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.shared.Lock; @@ -32,7 +40,20 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.event.EditEvent; public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { protected static final Log log = LogFactory.getLog(PropertyDaoJena.class.getName()); - + + protected static final String PREFIXES = + "PREFIX rdf: \n" + + "PREFIX vitro: \n" + + "PREFIX owl: \n"; + + protected static final List EXCLUDED_NAMESPACES = Arrays.asList( + "http://vitro.mannlib.cornell.edu/ns/vitro/0.7#", + "http://vitro.mannlib.cornell.edu/ns/vitro/public#", + "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + "http://www.w3.org/2000/01/rdf-schema#", + "http://www.w3.org/2002/07/owl#" + ); + public PropertyDaoJena(WebappDaoFactoryJena wadf) { super(wadf); } @@ -369,4 +390,15 @@ public class PropertyDaoJena extends JenaBaseDao implements PropertyDao { return classSet; } + + protected ResultSet getPropertyQueryResults(String subjectUri, Query query) { + log.debug("SPARQL query:\n" + query.toString()); + // Bind the subject's uri to the ?subject query term + QuerySolutionMap subjectBinding = new QuerySolutionMap(); + subjectBinding.add("subject", ResourceFactory.createResource(subjectUri)); + + // Run the SPARQL query to get the properties + QueryExecution qexec = QueryExecutionFactory.create(query, getOntModelSelector().getFullModel(), subjectBinding); + return qexec.execSelect(); + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyListDaoJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyListDaoJena.java deleted file mode 100644 index a9d503796..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/PropertyListDaoJena.java +++ /dev/null @@ -1,74 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.dao.jena; - -import java.util.List; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.query.Query; -import com.hp.hpl.jena.query.QueryExecution; -import com.hp.hpl.jena.query.QueryExecutionFactory; -import com.hp.hpl.jena.query.QueryFactory; -import com.hp.hpl.jena.query.QuerySolutionMap; -import com.hp.hpl.jena.query.ResultSet; -import com.hp.hpl.jena.rdf.model.ResourceFactory; - -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.Property; -import edu.cornell.mannlib.vitro.webapp.dao.PropertyListDao; - -public class PropertyListDaoJena extends JenaBaseDao implements PropertyListDao { - - static final protected String propertyQueryString = - "PREFIX vitro: \n" + - "SELECT ?group ?predicate WHERE {\n" + - " GRAPH ?g {\n" + - " ?subject ?predicate ?object . \n" + - " OPTIONAL { ?predicate vitro:inPropertyGroupAnnot ?group . \n" + - " }\n" + - " }\n" + - "}" + - "ORDER BY DESC(?group) ?predicate\n"; - - - static protected Query propertyQuery; - static { - try { - propertyQuery = QueryFactory.create(propertyQueryString); - } catch(Throwable th){ - log.error("could not create SPARQL query for propertyQueryString " + th.getMessage()); - log.error(propertyQueryString); - } - } - public PropertyListDaoJena(WebappDaoFactoryJena wadf) { - super(wadf); - } - - @Override - protected OntModel getOntModel() { - return getOntModelSelector().getABoxModel(); - } - - @Override - public List getPropertyListForSubject(Individual subject) { - return getPropertyListForSubject(subject.getURI()); - } - - @Override - public List getPropertyListForSubject(String subjectUri) { - - // First get all the properties that occur in statements with this subject as subject. We must get these - // from a db query because they may include properties that are not defined as "possible properties" - // for a subject of this class. - - // Bind the subject's uri to the ?subject query term - QuerySolutionMap subjectBinding = new QuerySolutionMap(); - subjectBinding.add("subject", ResourceFactory.createResource(subjectUri)); - - // Run the SPARQL query to get the properties - QueryExecution qexec = QueryExecutionFactory.create(propertyQuery, getOntModel()); - ResultSet results = qexec.execSelect(); - return null; - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java index 2b7c9a85d..e29ca6b16 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/dao/jena/WebappDaoFactoryJena.java @@ -9,6 +9,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.CopyOnWriteArrayList; import com.hp.hpl.jena.iri.IRI; import com.hp.hpl.jena.iri.IRIFactory; @@ -29,6 +30,7 @@ import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.dao.ApplicationDao; import edu.cornell.mannlib.vitro.webapp.dao.Classes2ClassesDao; import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; @@ -47,7 +49,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.OntologyDao; import edu.cornell.mannlib.vitro.webapp.dao.PortalDao; import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao; import edu.cornell.mannlib.vitro.webapp.dao.PropertyInstanceDao; -import edu.cornell.mannlib.vitro.webapp.dao.PropertyListDao; import edu.cornell.mannlib.vitro.webapp.dao.TabDao; import edu.cornell.mannlib.vitro.webapp.dao.TabIndividualRelationDao; import edu.cornell.mannlib.vitro.webapp.dao.TabVClassRelationDao; @@ -547,14 +548,6 @@ public class WebappDaoFactoryJena implements WebappDaoFactory { propertyInstanceDao = new PropertyInstanceDaoJena(this); return propertyInstanceDao; } - - private PropertyListDao propertyListDao = null; - public PropertyListDao getPropertyListDao() { - if (propertyListDao == null) { - propertyListDao = new PropertyListDaoJena(this); - } - return propertyListDao; - } protected VClassDao vClassDao = null; public VClassDao getVClassDao() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectProperty.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectProperty.java index 6e4ca58f5..997487c3d 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectProperty.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/CollatedObjectProperty.java @@ -2,15 +2,18 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; +import java.util.ArrayList; import java.util.List; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; + public class CollatedObjectProperty extends ObjectPropertyTemplateModel { - private List subclassList = null; + private List subclassList; - CollatedObjectProperty(String predicateUri) { - super(predicateUri); - // TODO Auto-generated constructor stub + CollatedObjectProperty(ObjectProperty property) { + super(property); + subclassList = new ArrayList(); } public List getSubclassList() { @@ -20,4 +23,10 @@ public class CollatedObjectProperty extends ObjectPropertyTemplateModel { public List getStatements() { return subclassList; } + + /* Access methods for templates */ + + public boolean getIsCollatedBySubtype() { + return true; + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java index 026b7a1e9..3632a8680 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java @@ -2,11 +2,21 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -public class DataPropertyTemplateModel extends PropertyTemplateModel { +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; - DataPropertyTemplateModel(String predicateUri) { - super(predicateUri); - // TODO Auto-generated constructor stub +public class DataPropertyTemplateModel extends PropertyTemplateModel { + + private static final String TYPE = "data"; + + DataPropertyTemplateModel(DataProperty property) { + super(property); + } + + + /* Access methods for templates */ + + public String getType() { + return TYPE; } } 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 8d040028d..167f2b3c0 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 @@ -2,25 +2,14 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import edu.cornell.mannlib.vedit.beans.LoginStatusBean; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao; -import edu.cornell.mannlib.vitro.webapp.dao.PropertyListDao; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; /** The entire grouped property list for the subject. @@ -32,60 +21,30 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; public class GroupedPropertyList extends BaseTemplateModel { private static final Log log = LogFactory.getLog(GroupedPropertyList.class); - private static final int MAX_GROUP_DISPLAY_RANK = 99; - - /** Don't include these properties in the list. */ - private static final Collection SUPPRESSED_OBJECT_PROPERTIES = Collections - .unmodifiableCollection(Arrays - .asList(new String[] { VitroVocabulary.IND_MAIN_IMAGE })); - - // RY Do we really want to store subject and vreq as members? Could just pass around. - private Individual subject; - private VitroRequest vreq; private List groups; - GroupedPropertyList(Individual subject, VitroRequest vreq) { - // RY Do we really want to store these as members? Could just pass around. - this.subject = subject; - this.vreq = vreq; + GroupedPropertyList(WebappDaoFactory wdf, PropertyList propertyList) { // Get the property groups - WebappDaoFactory wdf = vreq.getWebappDaoFactory(); - PropertyGroupDao pgDao = wdf.getPropertyGroupDao(); + PropertyGroupDao pgDao = wdf.getPropertyGroupDao(); List groupList = pgDao.getPublicGroups(false); // may be returned empty but not null +// +// List groups = new ArrayList(groupList.size()); +// for (PropertyGroup g : groupList) { +// groups.add(new PropertyGroupTemplateModel(g)); +// // Properties unassigned to any group go in a dummy group with name an empty string. Templates +// // must test for <#if ! group.name?has_content> or <#if group.name == ""> or <#if group.name?length == 0> +// groups.add(new DummyPropertyGroupTemplateModel("")); +// } +// // If there are no groups, create a dummy group, so that the template display logic is the same +// // in both cases. Name is null. Templates must test for <#if ! group.name??> +// if (groups.isEmpty()) { +// groups.add(new DummyPropertyGroupTemplateModel(null)); +// } - List groups = new ArrayList(groupList.size()); - for (PropertyGroup g : groupList) { - groups.add(new PropertyGroupTemplateModel(g)); - // Properties unassigned to any group go in a dummy group with name an empty string. Templates - // must test for <#if ! group.name?has_content> or <#if group.name == ""> or <#if group.name?length == 0> - groups.add(new DummyPropertyGroupTemplateModel("")); - } - // If there are no groups, create a dummy group, so that the template display logic is the same - // in both cases. Name is null. Templates must test for <#if ! group.name??> - if (groups.isEmpty()) { - groups.add(new DummyPropertyGroupTemplateModel(null)); - } - - // Create the property list for the subject. The properties will be put into groups later. - - // First get all the 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. - PropertyListDao plDao = wdf.getPropertyListDao(); - List propertyList = plDao.getPropertyListForSubject(subject); - } - /** - * Return true iff the user is editing. - */ - private boolean getEditingStatus() { - // These tests may change once self-editing issues are straightened out. - boolean isSelfEditing = VitroRequestPrep.isSelfEditing(vreq); - boolean isCurator = LoginStatusBean.getBean(vreq).isLoggedInAtLeast(LoginStatusBean.CURATOR); - return isSelfEditing || isCurator; - } /* * Public getters for templates diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/IndividualTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/IndividualTemplateModel.java index 109a3db3e..0af5407a5 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/IndividualTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/IndividualTemplateModel.java @@ -153,9 +153,9 @@ public class IndividualTemplateModel extends BaseTemplateModel { } public GroupedPropertyList getPropertyList() { -// PropertyListBuilder propListBuilder = new PropertyListBuilder(individual, vreq); -// return propListBuilder.getPropertyList(); - return new GroupedPropertyList(individual, vreq); + PropertyListBuilder propListBuilder = new PropertyListBuilder(individual, vreq); + return propListBuilder.getPropertyList(); + //return new GroupedPropertyList(individual, vreq); } /* These methods simply forward to the methods of the wrapped individual. It would be desirable to diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java index cd5d5607b..ca90c5738 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java @@ -2,11 +2,23 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel { +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; - ObjectPropertyTemplateModel(String predicateUri) { - super(predicateUri); - // TODO Auto-generated constructor stub +public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel { + + private static final String TYPE = "object"; + + ObjectPropertyTemplateModel(ObjectProperty property) { + super(property); } + + + /* Access methods for templates */ + + public String getType() { + return TYPE; + } + + public abstract boolean getIsCollatedBySubtype(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyList.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyList.java new file mode 100644 index 000000000..7f53f756b --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyList.java @@ -0,0 +1,234 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; +import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.Property; +import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup; +import edu.cornell.mannlib.vitro.webapp.beans.PropertyInstance; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyDao; +import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao; +import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao; +import edu.cornell.mannlib.vitro.webapp.dao.PropertyInstanceDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; +import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; + +public class PropertyList extends BaseTemplateModel { + + private static final Log log = LogFactory.getLog(PropertyList.class); + + private List propertyList; + + PropertyList() { + propertyList = new ArrayList(); + } + + protected void addObjectProperties(List propertyList) { + for (ObjectProperty op : propertyList) { + // This is a hack to throw out properties in the vitro, rdf, rdfs, and owl namespaces. + // It will be implemented in a better way in v1.3 (Editing and Display Configuration). + //if (! EXCLUDED_NAMESPACES.contains(op.getNamespace())) { + add(op); + //} else { + // log.debug("Excluded " + op.getURI() + " from displayed property list on the basis of namespace"); + //} + } + } + + protected void add(ObjectProperty op) { + propertyList.add(op.getCollateBySubclass() ? new CollatedObjectProperty(op) : new UncollatedObjectProperty(op)); + } + + protected void addDataProperties(List propertyList) { + for (DataProperty dp : propertyList) { + add(dp); + } + } + + protected void add(DataProperty p) { + propertyList.add(new DataPropertyTemplateModel(p)); + } + + protected boolean contains(Property property) { + if (property.getURI() == null) { + log.error("Property has no propertyURI in alreadyOnPropertyList()"); + return true; // don't add to list + } + for (PropertyTemplateModel ptm : propertyList) { + if (ptm.getUri() != null && ptm.getUri().equals(property.getURI())) { + return true; + } + } + return false; + } + + private static boolean contains(List list, PropertyInstance pi) { + if (pi.getPropertyURI() == null) { + return false; + } + for (ObjectProperty op : list) { + if (op.getURI() != null && op.getURI().equals(pi.getPropertyURI())) { + return op.isSubjectSide() == pi.getSubjectSide(); + } + } + return false; + } + + protected void mergeAllPossibleObjectProperties(WebappDaoFactory wdf, Individual subject, List objectPropertyList) { + PropertyInstanceDao piDao = wdf.getPropertyInstanceDao(); + // RY *** Does this exclude properties in the excluded namespaces already? If not, need same test as above + Collection allPropInstColl = piDao.getAllPossiblePropInstForIndividual(subject.getURI()); + if (allPropInstColl != null) { + for (PropertyInstance pi : allPropInstColl) { + if (pi != null) { + // RY Do we need to check this before checking if it's on the property list?? + if (! contains(objectPropertyList, pi)) { + ObjectPropertyDao opDao = wdf.getObjectPropertyDao(); + ObjectProperty op = opDao.getObjectPropertyByURI(pi.getPropertyURI()); + 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 if (! contains(op)) { + add(op); + } + } + } else { + log.error("a property instance in the Collection created by PropertyInstanceDao.getAllPossiblePropInstForIndividual() is unexpectedly null"); + } + } + } else { + log.error("a null Collection is returned from PropertyInstanceDao.getAllPossiblePropInstForIndividual()"); + } + } + + protected void mergeAllPossibleDataProperties(WebappDaoFactory wdf, Individual subject) { + DataPropertyDao dpDao = wdf.getDataPropertyDao(); + // RY *** Does this exclude properties in the excluded namespaces already? If not, need same test as above + Collection allDatapropColl = dpDao.getAllPossibleDatapropsForIndividual(subject.getURI()); + if (allDatapropColl != 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 (! contains(dp)) { + add(dp); + } + } else { + log.error("a data property in the Collection created in DataPropertyDao.getAllPossibleDatapropsForIndividual() is unexpectedly null)"); + } + } + } else { + log.error("a null Collection is returned from DataPropertyDao.getAllPossibleDatapropsForIndividual())"); + } + } + +// private void addUnique(Property p) { +// if (! contains(p)) { +// add(p); +// } +// } +// +// protected void add(Property p) { +// if (p instanceof ObjectProperty) { +// add((ObjectProperty) p); +// } else if (p instanceof DataProperty) { +// add((DataProperty) p); +// } +// } + + @SuppressWarnings("unchecked") + protected void sort(VitroRequest vreq) { + try { + Collections.sort(propertyList, new PropertyRanker(vreq)); + } catch (Exception ex) { + log.error("Exception sorting merged property list: " + ex.getMessage()); + } + } + + private class PropertyRanker implements Comparator { + + WebappDaoFactory wdf; + PropertyGroupDao pgDao; + + private PropertyRanker(VitroRequest vreq) { + this.wdf = vreq.getWebappDaoFactory(); + this.pgDao = wdf.getPropertyGroupDao(); + } + + public int compare (Object o1, Object o2) { + Property p1 = (Property) o1; + Property p2 = (Property) o2; + + // sort first by property group rank; if the same, then sort by property rank + final int MAX_GROUP_RANK=99; + + int p1GroupRank=MAX_GROUP_RANK; + try { + if (p1.getGroupURI()!=null) { + PropertyGroup pg1 = pgDao.getGroupByURI(p1.getGroupURI()); + if (pg1!=null) { + p1GroupRank=pg1.getDisplayRank(); + } + } + } catch (Exception ex) { + log.error("Cannot retrieve p1GroupRank for group "+p1.getEditLabel()); + } + + int p2GroupRank=MAX_GROUP_RANK; + try { + if (p2.getGroupURI()!=null) { + PropertyGroup pg2 = pgDao.getGroupByURI(p2.getGroupURI()); + if (pg2!=null) { + p2GroupRank=pg2.getDisplayRank(); + } + } + } catch (Exception ex) { + log.error("Cannot retrieve p2GroupRank for group "+p2.getEditLabel()); + } + + // int diff = pgDao.getGroupByURI(p1.getGroupURI()).getDisplayRank() - pgDao.getGroupByURI(p2.getGroupURI()).getDisplayRank(); + int diff=p1GroupRank - p2GroupRank; + if (diff==0) { + diff = determineDisplayRank(p1) - determineDisplayRank(p2); + if (diff==0) { + return p1.getEditLabel().compareTo(p2.getEditLabel()); + } else { + return diff; + } + } + return diff; + } + + private int determineDisplayRank(Property p) { + if (p instanceof DataProperty) { + DataProperty dp = (DataProperty)p; + return dp.getDisplayTier(); + } else if (p instanceof ObjectProperty) { + ObjectProperty op = (ObjectProperty)p; + String tierStr = op.getDomainDisplayTier(); // no longer used: p.isSubjectSide() ? op.getDomainDisplayTier() : op.getRangeDisplayTier(); + try { + return Integer.parseInt(tierStr); + } catch (NumberFormatException ex) { + log.error("Cannot decode object property display tier value "+tierStr+" as an integer"); + } + } else { + log.error("Property is of unknown class in PropertyRanker()"); + } + return 0; + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyListBuilder.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyListBuilder.java index 9426ca92a..4ad130bdd 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyListBuilder.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyListBuilder.java @@ -2,9 +2,6 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; @@ -12,11 +9,15 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vedit.beans.LoginStatusBean; +import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectPropertyStatement; import edu.cornell.mannlib.vitro.webapp.beans.Property; +import edu.cornell.mannlib.vitro.webapp.beans.PropertyGroup; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.dao.PropertyGroupDao; +import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.filters.VitroRequestPrep; /** @@ -32,12 +33,6 @@ public class PropertyListBuilder { private static final Log log = LogFactory.getLog(PropertyListBuilder.class); private static final int MAX_GROUP_DISPLAY_RANK = 99; - /** Don't include these properties in the list. */ - // RY This should perhaps be moved to ObjectPropertyTemplateModel - private static final Collection SUPPRESSED_OBJECT_PROPERTIES = Collections - .unmodifiableCollection(Arrays - .asList(new String[] { VitroVocabulary.IND_MAIN_IMAGE })); - protected Individual subject; protected VitroRequest vreq; @@ -46,35 +41,169 @@ public class PropertyListBuilder { this.vreq = vreq; } + // RY Create the list here first to get it working. Then consider moving to GroupedPropertyList constructor. protected GroupedPropertyList getPropertyList() { // Determine whether we're editing or not. - boolean isEditing = getEditingStatus(); + boolean userCanEditThisProfile = getEditingStatus(); - // Assemble the property list - List mergedPropertyList = new ArrayList(); - // First get the properties this entity actually has, presumably populated with statements - List objectPropertyList = subject.getObjectPropertyList(); + - for (ObjectProperty op : objectPropertyList) { - if (!SUPPRESSED_OBJECT_PROPERTIES.contains(op)) { - op.setEditLabel(op.getDomainPublic()); - mergedPropertyList.add(op); - }else{ - log.debug("suppressed " + op.getURI()); - } + + // Create the property list for the subject. The properties will be put into groups later. + PropertyList propertyList = new PropertyList(); + + // 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 objectPropertyList = subject.getPopulatedObjectPropertyList(); + propertyList.addObjectProperties(objectPropertyList); + + WebappDaoFactory wdf = vreq.getWebappDaoFactory(); + + // 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. + if (userCanEditThisProfile) { + propertyList.mergeAllPossibleObjectProperties(wdf, subject, objectPropertyList); + } + + // Now do much the same with data properties: get the list of populated data properties, then add in placeholders for missing ones + List dataPropertyList = subject.getPopulatedDataPropertyList(); + propertyList.addDataProperties(dataPropertyList); + + if (userCanEditThisProfile) { + propertyList.mergeAllPossibleDataProperties(wdf, subject); } - return null; + propertyList.sort(vreq); + + // *** ADD collation here *** + // Don't include custom sorting, since that will be handled from custom short views + + // Put the list into groups + + +// if (groupedMode) { +// int groupsCount=0; +// try { +// groupsCount = populateGroupsListWithProperties(pgDao,groupList,propertyList); //,groupForUngroupedProperties); +// } catch (Exception ex) { +// log.error("Exception on trying to populate groups list with properties: "+ex.getMessage()); +// ex.printStackTrace(); +// } +// try { +// int removedCount = pgDao.removeUnpopulatedGroups(groupList); +// if (removedCount == 0) { +// log.warn("Of "+groupsCount+" groups, none removed by removeUnpopulatedGroups"); +// /* } else { +// log.warn("Of "+groupsCount+" groups, "+removedCount+" removed by removeUnpopulatedGroups"); */ +// } +// groupsCount -= removedCount; +// //req.setAttribute("groupsCount", new Integer(groupsCount)); +// if (groupsCount > 0) { //still +// for (PropertyGroup g : groupList) { +// int statementCount=0; +// if (g.getPropertyList()!=null && g.getPropertyList().size()>0) { +// for (Property p : g.getPropertyList()) { +// if (p instanceof ObjectProperty) { +// ObjectProperty op = (ObjectProperty)p; +// List opStmts = op.getObjectPropertyStatements(); +// if (op.getObjectPropertyStatements()!=null && opStmts.size()>0) { +// statementCount += opStmts.size(); +// +// // If not collated, we need to apply custom sorting now. +// //applyCustomSortToUncollatedProperty(op, opStmts); +// } +// +// +// } +// } +// } +// g.setStatementCount(statementCount); +// } +// } +// } catch (Exception ex) { +// log.error("Exception on trying to prune groups list with properties: "+ex.getMessage()); +// } +// propertyList.clear(); + +// } else { // ungrouped mode +// for (Property p : mergedPropertyList) { +// if (p instanceof ObjectProperty) { +// ObjectProperty op = (ObjectProperty)p; +// applyCustomSortToUncollatedProperty(op, op.getObjectPropertyStatements()); +// } +// } } + + + return new GroupedPropertyList(wdf, propertyList); } /** * Return true iff the user is editing. + * These tests may change once self-editing issues are straightened out. What we really need to know + * is whether the user can edit this profile, not whether in general they are an editor. */ private boolean getEditingStatus() { - // These tests may change once self-editing issues are straightened out. boolean isSelfEditing = VitroRequestPrep.isSelfEditing(vreq); boolean isCurator = LoginStatusBean.getBean(vreq).isLoggedInAtLeast(LoginStatusBean.CURATOR); return isSelfEditing || isCurator; } + +// private int populateGroupsListWithProperties(PropertyGroupDao pgDao, List groupsList, List mergedPropertyList) {//, String unassignedGroupName) { +// int count = groupsList.size(); +// PropertyGroup tempGroup = null; +// String unassignedGroupName = ""; //temp, for compilation +// if (unassignedGroupName!=null) { +// tempGroup = pgDao.createTempPropertyGroup(unassignedGroupName,MAX_GROUP_DISPLAY_RANK); +// log.debug("creating temp property group "+unassignedGroupName+" for any unassigned properties"); +// } +// switch (count) { +// case 0: log.warn("groupsList has no groups on entering populateGroupsListWithProperties(); will create a new group \"other\""); +// break; +// case 1: break; +// default: try { +// Collections.sort(groupsList); +// } catch (Exception ex) { +// log.error("Exception on sorting groupsList in populateGroupsListWithProperties()"); +// } +// } +// if (count==0 && unassignedGroupName!=null) { +// groupsList.add(tempGroup); +// } +// for (PropertyGroup pg : groupsList) { +// if (pg.getPropertyList().size()>0) { +// pg.getPropertyList().clear(); +// } +// for (Property p : mergedPropertyList) { +// if (p.getURI() == null) { +// log.error("Property p has null URI in populateGroupsListWithProperties()"); +// } else if (p.getGroupURI()==null) { +// if (tempGroup!=null) { // not assigned any group yet and are creating a group for unassigned properties +// if (!alreadyOnPropertyList(tempGroup.getPropertyList(),p)) { +// tempGroup.getPropertyList().add(p); +// log.debug("adding property "+p.getEditLabel()+" to members of temp group "+unassignedGroupName); +// } +// } // otherwise don't put that property on the list +// } else if (p.getGroupURI().equals(pg.getURI())) { +// if (!alreadyOnPropertyList(pg.getPropertyList(),p)) { +// pg.getPropertyList().add(p); +// } +// } +// } +// if (pg.getPropertyList().size()>1) { +// try { +// Collections.sort(pg.getPropertyList(),new Property.DisplayComparatorIgnoringPropertyGroup()); +// } catch (Exception ex) { +// log.error("Exception sorting property group "+pg.getName()+" property list: "+ex.getMessage()); +// } +// } +// } +// if (count>0 && tempGroup!=null && tempGroup.getPropertyList().size()>0) { +// groupsList.add(tempGroup); +// } +// count = groupsList.size(); +// return count; +// } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java index e9ff62e37..a525773a7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/PropertyTemplateModel.java @@ -2,6 +2,7 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; +import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; /** @@ -9,15 +10,26 @@ import edu.cornell.mannlib.vitro.webapp.web.templatemodels.BaseTemplateModel; */ public abstract class PropertyTemplateModel extends BaseTemplateModel { - // Not sure whether we need the property or the uri. - protected String predicateUri = null; + protected Property property; - PropertyTemplateModel(String predicateUri) { - this.predicateUri = predicateUri; + PropertyTemplateModel(Property propertry) { + this.property = property; } + protected Property getProperty() { + return property; + } + + protected String getUri() { + return property.getURI(); + } + + /* Access methods for templates */ + public String getAddLink() { return null; } + + public abstract String getType(); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/UncollatedObjectProperty.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/UncollatedObjectProperty.java index 191f5a761..ab596171c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/UncollatedObjectProperty.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/UncollatedObjectProperty.java @@ -2,19 +2,28 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; +import java.util.ArrayList; import java.util.List; +import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; + public class UncollatedObjectProperty extends ObjectPropertyTemplateModel { - private List statements = null; + private List statements; - UncollatedObjectProperty(String predicateUri) { - super(predicateUri); - // TODO Auto-generated constructor stub + UncollatedObjectProperty(ObjectProperty property) { + super(property); + statements = new ArrayList(); } public List getStatements() { return statements; } + + /* Access methods for templates */ + + public boolean getIsCollatedBySubtype() { + return false; + } } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJenaTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJenaTest.java index eacc22501..b0ee7a139 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJenaTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/DataPropertyDaoJenaTest.java @@ -3,7 +3,9 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; +import org.apache.log4j.Level; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import com.hp.hpl.jena.ontology.DatatypeProperty; @@ -11,10 +13,12 @@ import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; import com.hp.hpl.jena.vocabulary.OWL; import com.hp.hpl.jena.vocabulary.RDF; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; @@ -23,8 +27,8 @@ import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; * */ -public class DataPropertyDaoJenaTest { - +public class DataPropertyDaoJenaTest extends AbstractTestClass { + @Test // Test that the DataPropertyDaoJena::updateDataProperty method will only update the jena model for // those properties in DataProperty that have a different value from what is already in the diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJenaTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJenaTest.java index b496690a6..3356878b5 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJenaTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/dao/jena/ObjectPropertyDaoJenaTest.java @@ -2,23 +2,27 @@ package edu.cornell.mannlib.vitro.webapp.dao.jena; +import org.apache.log4j.Level; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import com.hp.hpl.jena.ontology.OntModel; import com.hp.hpl.jena.ontology.OntModelSpec; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; +import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; import com.hp.hpl.jena.vocabulary.RDFS; +import edu.cornell.mannlib.vitro.testing.AbstractTestClass; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.dao.InsertException; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -public class ObjectPropertyDaoJenaTest { - +public class ObjectPropertyDaoJenaTest extends AbstractTestClass { + @Test public void testCollateBySubclass(){ /* Check that we can save collateBySubclass */ diff --git a/webapp/web/templates/freemarker/body/individual/individual.ftl b/webapp/web/templates/freemarker/body/individual/individual.ftl index 42ef95d5e..0e6a67d6f 100644 --- a/webapp/web/templates/freemarker/body/individual/individual.ftl +++ b/webapp/web/templates/freemarker/body/individual/individual.ftl @@ -71,7 +71,7 @@ - + <#-- <#include "individual-properties.ftl"> --> <#-- Keywords -->