NIHVIVO-1554 Removed controllers and jsps that have been superceded by Freemarker controllers and templates

This commit is contained in:
rjy7 2011-03-04 19:24:27 +00:00
parent 4db82c0585
commit 47b5e4ae52
38 changed files with 183 additions and 6101 deletions

View file

@ -10,7 +10,6 @@ import java.util.Date;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -19,8 +18,6 @@ import org.openrdf.model.impl.URIImpl;
import com.hp.hpl.jena.datatypes.xsd.XSDDatatype;
import edu.cornell.mannlib.vitro.webapp.controller.EntityController;
/**
* a class representing an object property
*

View file

@ -1,50 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
public class AboutController extends VitroHttpServlet {
private static final Log log = LogFactory.getLog(AboutController.class.getName());
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws IOException, ServletException {
try {
super.doGet(request,response);
VitroRequest vreq = new VitroRequest(request);
Portal portal = vreq.getPortal();
request.setAttribute("title", "About " + portal.getAppName());
request.setAttribute("aboutText", portal.getAboutText());
request.setAttribute("acknowledgeText", portal.getAcknowledgeText());
request.setAttribute("bodyJsp", "/about.jsp");
RequestDispatcher rd =
request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
} catch (Throwable e) {
log.error("AboutController could not forward to view.");
log.error(e.getMessage());
log.error(e.getStackTrace());
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}

View file

@ -1,331 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.listeners.StatementListener;
import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.WebappDaoFactoryFiltering;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilterUtils;
import edu.cornell.mannlib.vitro.webapp.dao.filtering.filters.VitroFilters;
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.joda.time.DateTime;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
public class BrowseController extends VitroHttpServlet {
static final long serialVersionUID=2006030721126L;
private transient ConcurrentHashMap<Integer, List> _groupListMap
= new ConcurrentHashMap<Integer, List>();
private transient ConcurrentLinkedQueue<String> _rebuildQueue
= new ConcurrentLinkedQueue<String>();
private RebuildGroupCacheThread _cacheRebuildThread;
private static final Log log = LogFactory.getLog(BrowseController.class.getName());
public void init(javax.servlet.ServletConfig servletConfig)
throws javax.servlet.ServletException {
super.init(servletConfig);
ServletContext sContext = servletConfig.getServletContext();
//BJL23: I'll work on a strategy for avoiding all this craziness.
OntModel model = (OntModel)sContext.getAttribute("jenaOntModel");
OntModel baseModel = (OntModel)sContext.getAttribute("baseOntModel");
OntModel infModel = (OntModel)sContext.getAttribute("inferenceOntModel");
BrowseControllerChangeListener bccl = new BrowseControllerChangeListener(this);
model.register(bccl);
baseModel.register(bccl);
infModel.register(bccl);
_rebuildQueue.add(REBUILD_EVERY_PORTAL);
_cacheRebuildThread = new RebuildGroupCacheThread(this);
_cacheRebuildThread.setDaemon(true);
_cacheRebuildThread.start();
_cacheRebuildThread.informOfQueueChange();
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
/**
* @author bdc34 adapted by jc55
*/
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws IOException, ServletException {
try {
//call doGet of super-class (that would be VitroHttpServlet).
super.doGet(request, response);
VitroRequest vreq = new VitroRequest(request);
if( vreq.getParameter("clearcache") != null ) //mainly for debugging
clearGroupCache();
PortalFlag portalState= vreq.getPortalFlag();
List groups = getGroups(vreq.getWebappDaoFactory().getVClassGroupDao(), vreq.getPortal().getPortalId());
if( groups == null || groups.isEmpty() )
request.setAttribute("classgroupsIsEmpty", true);
// stick the data in the requestScope
request.setAttribute("classgroups",groups);
request.setAttribute("portalState",portalState);
request.setAttribute("title","Index to "+vreq.getPortal().getAppName()+" Contents");
request.setAttribute("bodyJsp",Controllers.BROWSE_GROUP_JSP);
//request.setAttribute("bodyJsp",Controllers.DEBUG_JSP);
//FINALLY: send off to the BASIC_JSP to get turned into HTML
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
// run directly to body for testing: RequestDispatcher rd = request.getRequestDispatcher(Controllers.BROWSE_GROUP_JSP);
rd.forward(request, response);
} catch (Throwable e) {
log.debug("BrowseController.doGet(): "+ e);
request.setAttribute("javax.servlet.jsp.jspException",e);
RequestDispatcher rd = request.getRequestDispatcher("/error.jsp");
rd.forward(request, response);
}
}
public void destroy(){
_cacheRebuildThread.kill();
}
private List getGroups( VClassGroupDao vcgDao, int portalId ){
List grp = _groupListMap.get(portalId);
if( grp == null ){
log.debug("needed to build vclassGroups for portal " + portalId);
// Get all classgroups, each populated with a list of their member vclasses
List groups = vcgDao.getPublicGroupsWithVClasses(ORDER_BY_DISPLAYRANK, !INCLUDE_UNINSTANTIATED, INCLUDE_ENTITY_COUNT);
// now cull out the groups with no populated classes
//removeUnpopulatedClasses( groups);
vcgDao.removeUnpopulatedGroups(groups);
_groupListMap.put(portalId, groups);
return groups;
} else {
return grp;
}
}
private static boolean ORDER_BY_DISPLAYRANK = true;
private static boolean INCLUDE_UNINSTANTIATED = true;
private static boolean INCLUDE_ENTITY_COUNT = true;
// private void removeUnpopulatedClasses( List<VClassGroup> groups){
// if( groups == null || groups.size() == 0 ) return;
// for( VClassGroup grp : groups ){
// ListIterator it = grp.listIterator();
// while(it.hasNext()){
// VClass claz = (VClass)it.next();
// if( claz.getEntityCount() < 1 )
// it.remove();
// }
// }
// }
void requestCacheUpdate(String portalUri){
log.debug("requesting update for portal " + portalUri);
_rebuildQueue.add(portalUri);
_cacheRebuildThread.informOfQueueChange();
}
protected synchronized void refreshGroupCache() {
long start = System.currentTimeMillis();
try{
boolean rebuildAll = false;
HashSet<String> portalURIsToRebuild = new HashSet<String>();
String portalUri;
while ( null != (portalUri = _rebuildQueue.poll()) ){
if( portalUri.equals(REBUILD_EVERY_PORTAL)){
rebuildAll = true;
_rebuildQueue.clear();
break;
}else{
portalURIsToRebuild.add(portalUri);
}
}
ServletContext sContext = getServletConfig().getServletContext();
ApplicationBean appBean = new ApplicationBean();
WebappDaoFactory wdFactory = (WebappDaoFactory)sContext.getAttribute("webappDaoFactory");
if( wdFactory == null ){
log.error("Unable to rebuild cache: could not get 'webappDaoFactory' from Servletcontext");
return;
}
Collection<Portal> portals;
if( rebuildAll ){
portals = wdFactory.getPortalDao().getAllPortals();
} else {
portals = new LinkedList<Portal>();
for( String uri : portalURIsToRebuild){
Portal p =wdFactory.getPortalDao().getPortalByURI(uri);
if( p!= null)
portals.add(wdFactory.getPortalDao().getPortalByURI(uri));
}
}
for(Portal portal : portals){
rebuildCacheForPortal(portal,appBean,wdFactory);
}
log.info("rebuilt ClassGroup cache in " + (System.currentTimeMillis() - start) + " msec");
}catch (Exception ex){
log.error("could not rebuild cache", ex);
}
}
protected synchronized void rebuildCacheForPortalUri(String uri){
ServletContext sContext = getServletConfig().getServletContext();
WebappDaoFactory wdFactory = (WebappDaoFactory)sContext.getAttribute("webappDaoFactory");
if( wdFactory == null ){
log.error("Unable to rebuild cache: could not get 'webappDaoFactory' from Servletcontext");
return;
}
ApplicationBean appBean = new ApplicationBean();
Portal portal = wdFactory.getPortalDao().getPortalByURI(uri);
rebuildCacheForPortal(portal,appBean,wdFactory);
}
protected synchronized void rebuildCacheForPortal(Portal portal, ApplicationBean appBean, WebappDaoFactory wdFactory){
VitroFilters vFilters = null;
if( portal.isFlag1Filtering() ){
PortalFlag pflag = new PortalFlag(portal.getPortalId());
if( vFilters == null)
vFilters = VitroFilterUtils.getFilterFromPortalFlag(pflag);
else
vFilters = vFilters.and( VitroFilterUtils.getFilterFromPortalFlag(pflag));
}
WebappDaoFactory filteringDaoFactory ;
if( vFilters !=null ){
filteringDaoFactory = new WebappDaoFactoryFiltering(wdFactory,vFilters);
}else{
filteringDaoFactory = wdFactory;
}
_groupListMap.remove(portal.getPortalId());
getGroups(filteringDaoFactory.getVClassGroupDao(),portal.getPortalId());
}
private void clearGroupCache(){
_groupListMap = new ConcurrentHashMap<Integer, List>();
}
/* ****************** Jena Model Change Listener***************************** */
private class BrowseControllerChangeListener extends StatementListener {
private BrowseController controller = null;
public BrowseControllerChangeListener(BrowseController controller){
this.controller=controller;
}
public void addedStatement(Statement stmt) {
checkAndDoUpdate(stmt);
}
public void removedStatement(Statement stmt) {
checkAndDoUpdate(stmt);
}
private void checkAndDoUpdate(Statement stmt){
if( stmt==null ) return;
if( log.isDebugEnabled()){
log.debug("subject: " + stmt.getSubject().getURI());
log.debug("predicate: " + stmt.getPredicate().getURI());
}
if( RDF.type.getURI().equals( stmt.getPredicate().getURI()) ){
requestCacheUpdate(REBUILD_EVERY_PORTAL);
} else if( VitroVocabulary.PORTAL_FLAG1FILTERING.equals( stmt.getPredicate().getURI())){
requestCacheUpdate(stmt.getSubject().getURI());
} else if( VitroVocabulary.IN_CLASSGROUP.equals( stmt.getPredicate().getURI() )){
requestCacheUpdate(REBUILD_EVERY_PORTAL);
}
}
}
/* ******************** RebuildGroupCacheThread **************** */
protected class RebuildGroupCacheThread extends Thread {
BrowseController controller;
boolean die = false;
boolean queueChange = false;
long queueChangeMills = 0;
private boolean awareOfQueueChange = false;
RebuildGroupCacheThread(BrowseController controller) {
super("RebuildGroupCacheThread");
this.controller = controller;
}
public void run() {
while(true){
try{
synchronized (this){
if( _rebuildQueue.isEmpty() ){
log.debug("rebuildGroupCacheThread.run() -- queye empty, sleep");
wait(1000 * 60 );
}
if( die ) {
log.debug("doing rebuildGroupCacheThread.run() -- die()");
return;
}
if( queueChange && !awareOfQueueChange){
log.debug("rebuildGroupCacheThread.run() -- awareOfQueueChange, delay start of rebuild");
awareOfQueueChange = true;
wait(200);
}
}
if( awareOfQueueChange && System.currentTimeMillis() - queueChangeMills > 200){
log.debug("rebuildGroupCacheThread.run() -- refreshGroupCache()");
controller.refreshGroupCache();
synchronized( this){
queueChange = false;
}
awareOfQueueChange = false;
}else {
synchronized( this ){
wait(200);
}
}
} catch(InterruptedException e){}
}
}
synchronized void informOfQueueChange(){
queueChange = true;
queueChangeMills = System.currentTimeMillis();
this.notifyAll();
}
synchronized void kill(){
die = true;
notifyAll();
}
}
protected static String REBUILD_EVERY_PORTAL ="Rebuild every portal.";
}

View file

@ -1,89 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.controller.ContactMailServlet;
/**
* Controller for comments ("contact us") page
* * @author bjl23
*/
public class CommentsController extends VitroHttpServlet{
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
@Override
public void doGet( HttpServletRequest request, HttpServletResponse response )
throws IOException, ServletException {
super.doGet(request,response);
VitroRequest vreq = new VitroRequest(request);
try {
//this try block passes any errors to error.jsp
if (!ContactMailServlet.isSmtpHostConfigured(request)) {
request.setAttribute("title", "Comments and Feedback Form");
request.setAttribute("bodyJsp", "/contact_err.jsp");// <<< this is where the body gets set
request.setAttribute("ERR","This application has not yet been configured to send mail -- " +
"smtp host has not been specified in the configuration properties file.");
RequestDispatcher errd = request.getRequestDispatcher(Controllers.BASIC_JSP);
errd.forward(request, response);
}
ApplicationBean appBean=vreq.getAppBean();
Portal portalBean=vreq.getPortal();
if ( (appBean.getMaxSharedPortalId()-appBean.getMinSharedPortalId()) > 1
&& ( (portalBean.getPortalId() >= appBean.getMinSharedPortalId()
&& portalBean.getPortalId() <= appBean.getMaxSharedPortalId() )
|| portalBean.getPortalId() == appBean.getSharedPortalFlagNumeric() )
) {
request.setAttribute("portalType","CALSResearch");
} else
if (portalBean.getAppName().equalsIgnoreCase("CALS Impact")){
request.setAttribute("portalType", "CALSImpact");
} else if (portalBean.getAppName().equalsIgnoreCase("VIVO")) {
request.setAttribute("portalType", "VIVO");
} else {
request.setAttribute("portalType", "clone");
}
request.setAttribute("siteName",portalBean.getAppName());
request.setAttribute("scripts","/js/commentsForm.jsp");
if (request.getHeader("Referer") == null)
request.getSession().setAttribute("commentsFormReferer","none");
else
request.getSession().setAttribute("commentsFormReferer",request.getHeader("Referer"));
request.setAttribute("portalId",Integer.valueOf(portalBean.getPortalId()));
request.setAttribute("title", portalBean.getAppName()+" Comments and Feedback Form");
request.setAttribute("bodyJsp", "/commentsForm.jsp");// <<< this is where the body gets set
request.setAttribute("portalBean",portalBean);
RequestDispatcher rd =
request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
} catch (Throwable e) {
// This is how we use an error.jsp
//it expects javax.servlet.jsp.jspException to be set to the
//exception so that it can display the info out of that.
request.setAttribute("javax.servlet.jsp.jspException", e);
RequestDispatcher rd = request.getRequestDispatcher("/error.jsp");
rd.include(request, response);
}
}
}

View file

@ -22,13 +22,9 @@ public class Controllers {
public static final String ABOUT = "/about";
public static final String CONTACT_URL = "/comments";
public static final String TERMS_OF_USE_URL = "/termsOfUse";
public static final String SEARCH_URL = "/search";
public static final String SEARCH_URL = "/search";
public static final String ENTITY = "/entity";
public static final String ENTITY_PROP_LIST = "/entityPropList";
public static final String ENTITY_LIST = "/entitylist";
public static final String BROWSE_CONTROLLER = "browsecontroller";
public static final String RETRY_URL = "editForm";
public static final String TAB_ENTITIES = "/TabEntitiesController";
@ -43,26 +39,16 @@ public class Controllers {
public static final String TAB = "/index.jsp";
public static final String BASIC_JSP = "/templates/page/basicPage.jsp";
public static final String DEBUG_JSP = "/templates/page/debug.jsp";
public static final Object BODY_MSG = "/templates/page/bodyMsg.jsp";
public static final String ENTITY_JSP = "/templates/entity/entityBasic.jsp";
public static final String ENTITY_PROP_LIST_JSP = "templates/entity/entityPropsList.jsp";
public static final String ENTITY_DATAPROP_LIST_JSP = "templates/entity/entityDatapropsList.jsp";
public static final String ENTITY_MERGED_PROP_LIST_GROUPED_JSP = "templates/entity/entityMergedPropsList.jsp";
public static final String DASHBOARD_PROP_LIST_JSP = "edit/dashboardPropsList.jsp";
public static final String ENTITY_MERGED_PROP_LIST_UNGROUPED_JSP = "templates/entity/entityMergedPropsListUngrouped.jsp";
public static final String ENTITY_KEYWORDS_LIST_JSP = "templates/entity/entityKeywordsList.jsp";
public static final String ENTITY_EDITABLE_JSP = "templates/entity/entityEditable.jsp";
public static final String ENTITY_EDITABLE_PROP_LIST_JSP = "templates/entity/entityEditablePropsList.jsp";
public static final String ENTITY_LIST_JSP = "templates/entity/entityList.jsp";
public static final String ENTITY_LIST_FOR_TABS_JSP = "templates/entity/entityListForTabs.jsp";
public static final String TAB_ENTITIES_LIST_GALLERY_JSP = "templates/entity/entityListForGalleryTab.jsp";
public static final String ENTITY_NOT_FOUND_JSP = "templates/error/entityNotFound.jsp";
public static final String TAB_BASIC_JSP = "/templates/tabs/tabBasic.jsp";
@ -70,15 +56,6 @@ public class Controllers {
public static final String ALPHA_INDEX_JSP = "/templates/alpha/alphaIndex.jsp";
public static final String SEARCH_BASIC_JSP = "/templates/search/searchBasic.jsp";
public static final String SEARCH_PAGED_JSP = "/templates/search/searchPaged.jsp";
public static final String SEARCH_FAILED_JSP = "/templates/search/searchFailed.jsp";
public static final String SEARCH_GROUP_JSP = "/templates/search/searchGroup.jsp";
public static final Object SEARCH_FORM_JSP = "/templates/search/searchForm.jsp";
public static final Object SEARCH_BAD_QUERY_JSP = "/templates/search/searchBadQuery.jsp";
public static final String BROWSE_GROUP_JSP = "/templates/browse/browseGroup.jsp";
public static final String HORIZONTAL_JSP = "/templates/edit/fetch/horizontal.jsp";
public static final String VERTICAL_JSP = "/templates/edit/fetch/vertical.jsp";
@ -88,9 +65,6 @@ public class Controllers {
public static final String VCLASS_RETRY_URL = "vclass_retry";
public static final String TOGGLE_SCRIPT_ELEMENT = "<script language='JavaScript' type='text/javascript' src='js/toggle.js'></script>";
public static final Object SEARCH_ERROR_JSP = "/templates/parts/search_error.jsp";
//public static final String TAB_ENTITIES_LIST_JSP = "templates/tab/tabEntities.jsp";

View file

@ -1,720 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.hp.hpl.jena.datatypes.TypeMapper;
import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.Literal;
import com.hp.hpl.jena.rdf.model.Model;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.RDFNode;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.vocabulary.RDF;
import com.hp.hpl.jena.vocabulary.RDFS;
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
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.ObjectPropertyStatement;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.SelfEditingConfiguration;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
import edu.cornell.mannlib.vitro.webapp.filestorage.model.FileInfo;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQuery;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQueryWrapper;
import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapper;
import edu.cornell.mannlib.vitro.webapp.utils.NamespaceMapperFactory;
import edu.cornell.mannlib.vitro.webapp.web.ContentType;
import edu.cornell.mannlib.vitro.webapp.web.jsptags.StringProcessorTag;
/**
* Handles requests for entity information.
* Calls EntityPropertyListController to draw property list.
*
* @author bdc34
*
*/
public class EntityController extends VitroHttpServlet {
private static final Log log = LogFactory.getLog(EntityController.class.getName());
private String default_jsp = Controllers.BASIC_JSP;
private String default_body_jsp = Controllers.ENTITY_JSP;
private ApplicationBean appBean;
public void doGet( HttpServletRequest req, HttpServletResponse res )
throws IOException, ServletException {
try {
super.doGet(req, res);
VitroRequest vreq = new VitroRequest(req);
//get URL without hostname or servlet context
String url = req.getRequestURI().substring(req.getContextPath().length());
//Check to see if the request is for a non-information resource, redirect if it is.
String redirectURL = checkForRedirect ( url, req.getHeader("accept") );
if( redirectURL != null ){
doRedirect( req, res, redirectURL );
return;
}
ContentType rdfFormat = checkForLinkedDataRequest(url,req.getHeader("accept"));
if( rdfFormat != null ){
doRdf( vreq, res, rdfFormat );
return;
}
Individual indiv = null;
try{
indiv = getEntityFromRequest( vreq);
}catch(Throwable th){
doHelp(res);
return;
}
if( indiv == null || checkForHidden(vreq, indiv) || checkForSunset(vreq, indiv)){
doNotFound(vreq, res);
return;
}
// If this is an uploaded file, redirect to its "alias URL".
String aliasUrl = getAliasUrlForBytestreamIndividual(req, indiv);
if (aliasUrl != null) {
res.sendRedirect(req.getContextPath() + aliasUrl);
return;
}
doHtml( vreq, res , indiv);
return;
} catch (Throwable e) {
log.error(e, e);
req.setAttribute("javax.servlet.jsp.jspException",e);
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
rd.forward(req, res);
}
}
private void doHtml(VitroRequest vreq, HttpServletResponse res, Individual indiv) throws ServletException, IOException {
IndividualDao iwDao = vreq.getWebappDaoFactory().getIndividualDao();
ObjectPropertyDao opDao = vreq.getWebappDaoFactory().getObjectPropertyDao();
//Check if a "relatedSubjectUri" parameter has been supplied, and,
//if so, retrieve the related individual.t
//Some individuals make little sense standing alone and should
//be displayed in the context of their relationship to another.
String relatedSubjectUri = vreq.getParameter("relatedSubjectUri");
if (relatedSubjectUri != null) {
Individual relatedSubjectInd = iwDao.getIndividualByURI(relatedSubjectUri);
if (relatedSubjectInd != null) {
vreq.setAttribute("relatedSubject", relatedSubjectInd);
}
}
String relatingPredicateUri = vreq.getParameter("relatingPredicateUri");
if (relatingPredicateUri != null) {
ObjectProperty relatingPredicateProp = opDao.getObjectPropertyByURI(relatingPredicateUri);
if (relatingPredicateProp != null) {
vreq.setAttribute("relatingPredicate", relatingPredicateProp);
}
}
indiv.setKeywords(iwDao.getKeywordsForIndividualByMode(indiv.getURI(),"visible"));
indiv.sortForDisplay();
String vclassName = "unknown";
String customView = null;
String customCss = null;
if( indiv.getVClass() != null ){
vclassName = indiv.getVClass().getName();
List<VClass> clasList = indiv.getVClasses(true);
for (VClass clas : clasList) {
customView = clas.getCustomDisplayView();
if (customView != null) {
if (customView.length()>0) {
vclassName = clas.getName(); // reset entity vclassname to name of class where a custom view
log.debug("Found direct class ["+clas.getName()+"] with custom view "+customView+"; resetting entity vclassName to this class");
break;
} else {
customView = null;
}
}
}
if (customView == null) { //still
clasList = indiv.getVClasses(false);
for (VClass clas : clasList) {
customView = clas.getCustomDisplayView();
if (customView != null) {
if (customView.length()>0) {
// note that NOT changing entity vclassName here yet
log.debug("Found inferred class ["+clas.getName()+"] with custom view "+customView);
break;
} else {
customView = null;
}
}
}
}
} else if (indiv.getVClassURI() != null) {
log.debug("Individual " + indiv.getURI() + " with class URI " +
indiv.getVClassURI() + ": no class found with that URI");
}
if (customView!=null) {
// RY Transitional hack: ignore Freemarker templates so we can load old individual page with default display view
if (customView.endsWith(".ftl")) {
customView = null;
}
// insert test for whether a css files of the same name exists, and populate the customCss string for use when construction the header
}
String netid = iwDao.getNetId(indiv.getURI());
vreq.setAttribute("netid", netid);
vreq.setAttribute("vclassName", vclassName);
vreq.setAttribute("entity",indiv);
Portal portal = vreq.getPortal();
vreq.setAttribute("portal",String.valueOf(portal));
String view= getViewFromRequest(vreq);
if( view == null){
if (customView == null) {
view = default_jsp;
vreq.setAttribute("bodyJsp", Controllers.ENTITY_JSP);
log.debug("no custom view and no view parameter in request for rendering "+indiv.getName());
} else {
view = default_jsp;
log.debug("setting custom view templates/entity/"+ customView + " for rendering "+indiv.getName());
vreq.setAttribute("bodyJsp", "/templates/entity/"+customView);
}
vreq.setAttribute("entityPropsListJsp",Controllers.ENTITY_PROP_LIST_JSP);
vreq.setAttribute("entityDatapropsListJsp",Controllers.ENTITY_DATAPROP_LIST_JSP);
vreq.setAttribute("entityMergedPropsListJsp",Controllers.ENTITY_MERGED_PROP_LIST_GROUPED_JSP);
vreq.setAttribute("entityKeywordsListJsp",Controllers.ENTITY_KEYWORDS_LIST_JSP);
} else {
log.debug("Found view parameter "+view+" in request for rendering "+indiv.getName());
}
//set title before we do the highlighting so we don't get markup in it.
vreq.setAttribute("title",indiv.getName());
//setup highlighter for search terms
checkForSearch(vreq, indiv);
// set CSS and script elements
String contextPath = "";
if (vreq.getContextPath().length()>1) {
contextPath = vreq.getContextPath();
}
String css = "<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\""
+ contextPath + "/" + portal.getThemeDir() + "css/entity.css\"/>\n"
+ "<script language='JavaScript' type='text/javascript' src='"+contextPath+"/js/toggle.js'></script> \n";
if (customCss!=null) {
css += customCss;
}
if( indiv.getURI().startsWith( vreq.getWebappDaoFactory().getDefaultNamespace() )){
vreq.setAttribute("entityLinkedDataURL", indiv.getURI() + "/" + indiv.getLocalName() + ".rdf");
}
vreq.setAttribute("css",css);
vreq.setAttribute("scripts", "/templates/entity/entity_inject_head.jsp");
RequestDispatcher rd = vreq.getRequestDispatcher( view );
rd.forward(vreq,res);
}
private void doRdf(VitroRequest vreq, HttpServletResponse res,
ContentType rdfFormat) throws IOException, ServletException {
Individual indiv = getEntityFromRequest(vreq);
if( indiv == null ){
doNotFound(vreq, res);
return;
}
OntModel ontModel = null;
HttpSession session = vreq.getSession(false);
if( session != null )
ontModel =(OntModel)session.getAttribute("jenaOntModel");
if( ontModel == null)
ontModel = (OntModel)getServletContext().getAttribute("jenaOntModel");
Model newModel;
newModel = getRDF(indiv, ontModel, ModelFactory.createDefaultModel(), 0);
res.setContentType(rdfFormat.getMediaType());
String format = "";
if ( RDFXML_MIMETYPE.equals(rdfFormat.getMediaType()))
format = "RDF/XML";
else if( N3_MIMETYPE.equals(rdfFormat.getMediaType()))
format = "N3";
else if ( TTL_MIMETYPE.equals(rdfFormat.getMediaType()))
format ="TTL";
newModel.write( res.getOutputStream(), format );
}
private void doRedirect(HttpServletRequest req, HttpServletResponse res,
String redirectURL) {
//It seems like there must be a more standard way to do a redirect in tomcat.
String hn = req.getHeader("Host");
if (req.isSecure()) {
res.setHeader("Location", res.encodeURL("https://" + hn
+ req.getContextPath() + redirectURL));
log.info("doRedirect by using HTTPS");
} else {
res.setHeader("Location", res.encodeURL("http://" + hn
+ req.getContextPath() + redirectURL));
log.info("doRedirect by using HTTP");
}
res.setStatus(res.SC_SEE_OTHER);
}
private static Pattern LINKED_DATA_URL = Pattern.compile("^/individualold/([^/]*)$");
private static Pattern NS_PREFIX_URL = Pattern.compile("^/individualold/([^/]*)/([^/]*)$");
/**
Gets the entity id from the request.
Works for the following styles of URLs:
/individual?id=individualLocalName
/individual?entityId=individualLocalName
/individual?uri=urlencodedURI
/individual?nedit=bdc34
/individual?nedIt=bdc34
/individual/nsprefix/localname
/individual/localname
/individual/localname/localname.rdf
/individual/localname/localname.n3
/individual/localname/localname.ttl
/individual/localname/localname.html
@return null on failure.
*/
public static Individual getEntityFromRequest(VitroRequest vreq) {
String netIdStr = null;
Individual entity = null;
IndividualDao iwDao = vreq.getWebappDaoFactory().getIndividualDao();
String entityIdStr = vreq.getParameter("id");
if (entityIdStr == null || entityIdStr.equals(""))
entityIdStr = vreq.getParameter("entityId");
if( entityIdStr != null){
try {
String entityURI = vreq.getWebappDaoFactory().getDefaultNamespace()+"individual"+entityIdStr;
entity = iwDao.getIndividualByURI(entityURI);
} catch ( Exception e ) {
log.warn("Could not parse entity id: " + entityIdStr);
return null;
}
return entity;
}
String entityURIStr = vreq.getParameter("uri");
if (entityURIStr != null) {
try {
entity = iwDao.getIndividualByURI(entityURIStr);
} catch (Exception e) {
log.warn("Could not retrieve entity "+entityURIStr);
return null;
}
return entity;
}
//get URL without hostname or servlet context
String url = vreq.getRequestURI().substring(vreq.getContextPath().length());
/* check for parts of URL that indicate request for RDF
http://vivo.cornell.edu/individual/n23/n23.rdf
http://vivo.cornell.edu/individual/n23/n23.n3
http://vivo.cornell.edu/individual/n23/n23.ttl */
String uri = null;
Matcher m = RDF_REQUEST.matcher(url);
if( m.matches() && m.groupCount() == 1)
uri = m.group(1);
m = N3_REQUEST.matcher(url);
if( m.matches() && m.groupCount() == 1)
uri = m.group(1);
m = TTL_REQUEST.matcher(url);
if( m.matches() && m.groupCount() == 1)
uri= m.group(1);
m = HTML_REQUEST.matcher(url);
if( m.matches() && m.groupCount() == 1)
uri= m.group(1);
if( uri != null )
return iwDao.getIndividualByURI(vreq.getWebappDaoFactory().getDefaultNamespace() + uri);
// see if we can get the URI from a name space prefix and a local name
Matcher prefix_match = NS_PREFIX_URL.matcher(url);
if( prefix_match.matches() && prefix_match.groupCount() == 2){
String prefix = prefix_match.group(1);
String localName = prefix_match.group(2);
//String[] requestParts = requestURI.split("/individual/");
//String[] URIParts = requestParts[1].split("/");
//String localName = URIParts[1];
String namespace = "";
NamespaceMapper namespaceMapper = NamespaceMapperFactory.getNamespaceMapper(vreq.getSession().getServletContext());
String t;
namespace = ( (t = namespaceMapper.getNamespaceForPrefix(prefix)) != null) ? t : "";
return iwDao.getIndividualByURI(namespace+localName);
}
// see if we can get a local name
Matcher linkedDataMatch = LINKED_DATA_URL.matcher(url);
if( linkedDataMatch.matches() && linkedDataMatch.groupCount() == 1){
String localName = linkedDataMatch.group(1);
String ns = vreq.getWebappDaoFactory().getDefaultNamespace();
return iwDao.getIndividualByURI( ns + localName );
}
//so we try to get the netid
netIdStr = vreq.getParameter("netId");
if (netIdStr==null || netIdStr.equals(""))
netIdStr = vreq.getParameter("netid");
if ( netIdStr != null ){
SelfEditingConfiguration sec = SelfEditingConfiguration.getBean(vreq);
uri = sec.getIndividualUriFromUsername(iwDao, netIdStr);
return iwDao.getIndividualByURI(uri);
}
return null;
}
private static Pattern URI_PATTERN = Pattern.compile("^/individualold/([^/]*)$");
//Redirect if the request is for http://hostname/individual/localname
// if accept is nothing or text/html redirect to ???
// if accept is some RDF thing redirect to the URL for RDF
private String checkForRedirect(String url, String acceptHeader) {
Matcher m = URI_PATTERN.matcher(url);
if( m.matches() && m.groupCount() == 1 ){
ContentType c = checkForLinkedDataRequest(url, acceptHeader);
if( c != null ){
String redirectUrl = "/individualold/" + m.group(1) + "/" + m.group(1) ;
if( RDFXML_MIMETYPE.equals( c.getMediaType()) ){
return redirectUrl + ".rdf";
}else if( N3_MIMETYPE.equals( c.getMediaType() )){
return redirectUrl + ".n3";
}else if( TTL_MIMETYPE.equals( c.getMediaType() )){
return redirectUrl + ".ttl";
}//else send them to html
}
//else redirect to HTML representation
return "/display/" + m.group(1) ;
}else{
return null;
}
}
private static Pattern RDF_REQUEST = Pattern.compile("^/individualold/([^/]*)/\\1.rdf$");
private static Pattern N3_REQUEST = Pattern.compile("^/individualold/([^/]*)/\\1.n3$");
private static Pattern TTL_REQUEST = Pattern.compile("^/individualold/([^/]*)/\\1.ttl$");
private static Pattern HTML_REQUEST = Pattern.compile("^/displayold/([^/]*)$");
/**
* @return null if this is not a linked data request, returns content type if it is a
* linked data request.
*/
protected ContentType checkForLinkedDataRequest(String url, String acceptHeader) {
try {
//check the accept header
if (acceptHeader != null) {
List<ContentType> actualContentTypes = new ArrayList<ContentType>();
actualContentTypes.add(new ContentType( XHTML_MIMETYPE ));
actualContentTypes.add(new ContentType( HTML_MIMETYPE ));
actualContentTypes.add(new ContentType( RDFXML_MIMETYPE ));
actualContentTypes.add(new ContentType( N3_MIMETYPE ));
actualContentTypes.add(new ContentType( TTL_MIMETYPE ));
ContentType best = ContentType.getBestContentType(acceptHeader,actualContentTypes);
if (best!=null && (
RDFXML_MIMETYPE.equals(best.getMediaType()) ||
N3_MIMETYPE.equals(best.getMediaType()) ||
TTL_MIMETYPE.equals(best.getMediaType()) ))
return best;
}
/*
* check for parts of URL that indicate request for RDF
http://vivo.cornell.edu/individual/n23/n23.rdf
http://vivo.cornell.edu/individual/n23/n23.n3
http://vivo.cornell.edu/individual/n23/n23.ttl
*/
Matcher m = RDF_REQUEST.matcher(url);
if( m.matches() )
return new ContentType(RDFXML_MIMETYPE);
m = N3_REQUEST.matcher(url);
if( m.matches() )
return new ContentType(N3_MIMETYPE);
m = TTL_REQUEST.matcher(url);
if( m.matches() )
return new ContentType(TTL_MIMETYPE);
} catch (Throwable th) {
log.error("problem while checking accept header " , th);
}
return null;
}
private boolean checkForSunset(VitroRequest vreq, Individual entity) {
// TODO Auto-generated method stub
return false;
}
private boolean checkForHidden(VitroRequest vreq, Individual entity){
// TODO Auto-generated method stub
return false;
}
/**
* If this entity represents a File Bytestream, get its alias URL so we can
* properly serve the file contents.
*/
private String getAliasUrlForBytestreamIndividual(HttpServletRequest req, Individual entity)
throws IOException {
FileInfo fileInfo = FileInfo.instanceFromBytestreamUri(new VitroRequest(
req).getWebappDaoFactory(), entity.getURI());
if (fileInfo == null) {
log.trace("Entity '" + entity.getURI() + "' is not a bytestream.");
return null;
}
String url = fileInfo.getBytestreamAliasUrl();
log.debug("Alias URL for '" + entity.getURI() + "' is '" + url + "'");
if (entity.getURI().equals(url)) {
// Avoid a tight loop; if the alias URL is equal to the URI, then
// don't recognize it as a File Bytestream.
return null;
} else {
return url;
}
}
private Model getRDF(Individual entity, OntModel contextModel, Model newModel, int recurseDepth ) {
Resource subj = newModel.getResource(entity.getURI());
List<DataPropertyStatement> dstates = entity.getDataPropertyStatements();
//System.out.println("data: "+dstates.size());
TypeMapper typeMapper = TypeMapper.getInstance();
for (DataPropertyStatement ds: dstates) {
Property dp = newModel.getProperty(ds.getDatapropURI());
Literal lit = null;
if ((ds.getLanguage()) != null && (ds.getLanguage().length()>0)) {
lit = newModel.createLiteral(ds.getData(),ds.getLanguage());
} else if ((ds.getDatatypeURI() != null) && (ds.getDatatypeURI().length()>0)) {
lit = newModel.createTypedLiteral(ds.getData(),typeMapper.getSafeTypeByName(ds.getDatatypeURI()));
} else {
lit = newModel.createLiteral(ds.getData());
}
newModel.add(newModel.createStatement(subj, dp, lit));
}
if( recurseDepth < 5 ){
List<ObjectPropertyStatement> ostates = entity.getObjectPropertyStatements();
for (ObjectPropertyStatement os: ostates) {
ObjectProperty objProp = os.getProperty();
Property op = newModel.getProperty(os.getPropertyURI());
Resource obj = newModel.getResource(os.getObjectURI());
newModel.add(newModel.createStatement(subj, op, obj));
if( objProp.getStubObjectRelation() )
newModel.add(getRDF(os.getObject(), contextModel, newModel, recurseDepth + 1));
}
}
newModel = getLabelAndTypes(entity, contextModel, newModel );
return newModel;
}
/* Get the properties that are difficult to get via a filtered WebappDaoFactory. */
private Model getLabelAndTypes(Individual entity, Model ontModel, Model newModel){
for( VClass vclass : entity.getVClasses()){
newModel.add(newModel.getResource(entity.getURI()), RDF.type, newModel.getResource(vclass.getURI()));
}
ontModel.enterCriticalSection(Lock.READ);
try {
newModel.add(ontModel.listStatements(ontModel.getResource(entity.getURI()), RDFS.label, (RDFNode)null));
} finally {
ontModel.leaveCriticalSection();
}
return newModel;
}
private void checkForSearch(HttpServletRequest req, Individual ent) {
if (req.getSession().getAttribute("LastQuery") != null) {
VitroQueryWrapper qWrap = (VitroQueryWrapper) req.getSession()
.getAttribute("LastQuery");
if (qWrap.getRequestCount() > 0 && qWrap.getQuery() != null) {
VitroQuery query = qWrap.getQuery();
//set query text so we can get it in JSP
req.setAttribute("querytext", query.getTerms());
//setup highlighting for output
StringProcessorTag.putStringProcessorInRequest(req, qWrap.getHighlighter());
qWrap.setRequestCount(qWrap.getRequestCount() - 1);
} else {
req.getSession().removeAttribute("LastQuery");
}
}
}
private Pattern badrequest= Pattern.compile(".*([&\\?=]|\\.\\.).*");
public String getViewFromRequest(HttpServletRequest request){
String viewParam = request.getParameter("view");
if( viewParam != null ){
if( badrequest.matcher(viewParam).matches() ){
log.debug("request for a non-default view was bad: " + viewParam);
return null;
}else{
log.debug("view request : " + viewParam);
return viewParam;
}
}
return null;
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
private void doHelp(HttpServletResponse res)
throws IOException, ServletException {
ServletOutputStream out = res.getOutputStream();
res.setContentType("text/html; charset=UTF-8");
out.println("<html><body><h2>Quick Notes on using entity:</h2>");
out.println("<p>id is the id of the entity to query for. netid also works.</p>");
out.println("</body></html>");
}
private void doNotFound(HttpServletRequest req, HttpServletResponse res)
throws IOException, ServletException {
VitroRequest vreq = new VitroRequest(req);
Portal portal = vreq.getPortal();
ApplicationBean appBean = ApplicationBean.getAppBean(getServletContext());
int allPortalId = appBean.getAllPortalFlagNumeric();
//If an Individual is not found, there is possibility that it
//was requested from a portal where it was not visible.
//In this case redirect to the all portal.
try{
Portal allPortal =
vreq.getWebappDaoFactory().getPortalDao().getPortal(allPortalId);
// there must be a portal defined with the ID of the all portal
// for this to work
if( portal.getPortalId() != allPortalId && allPortal != null ) {
//bdc34:
// this is hard coded to get the all portal
// I didn't find a way to get the id of the all portal
// it is likely that redirecting will not work in non VIVO clones
String portalPrefix = null;
String portalParam = null;
if( allPortal != null && allPortal.getUrlprefix() != null )
portalPrefix = allPortal.getUrlprefix();
else
portalParam = "home=" + allPortalId;
String queryStr = req.getQueryString();
if( queryStr == null && portalParam != null && !"".equals(portalParam)){
queryStr = portalParam;
} else {
if( portalParam != null && !"".equals(portalParam))
queryStr = queryStr + "&" + portalParam;
}
if( queryStr != null && !queryStr.startsWith("?") )
queryStr = "?" + queryStr;
StringBuilder url = new StringBuilder();
url.append( req.getContextPath() );
if( req.getContextPath() != null && !req.getContextPath().endsWith("/"))
url.append('/');
if( portalPrefix != null && !"".equals(portalPrefix))
url.append( portalPrefix ).append('/');
String servletPath = req.getServletPath();
String spath = "";
if( servletPath != null ){
if( servletPath.startsWith("/") )
spath = servletPath.substring(1);
else
spath = servletPath;
}
if( spath != null && !"".equals(spath))
url.append( spath );
if( req.getPathInfo() != null )
url.append( req.getPathInfo() );
if( queryStr != null && !"".equals(queryStr ))
url.append( queryStr );
res.sendRedirect(url.toString());
return;
}
}catch(Throwable th){
log.error("could not do a redirect", th);
}
//set title before we do the highlighting so we don't get markup in it.
req.setAttribute("title","not found");
res.setStatus(HttpServletResponse.SC_NOT_FOUND);
String css = "<link rel=\"stylesheet\" type=\"text/css\" media=\"screen\" href=\""
+ portal.getThemeDir() + "css/entity.css\"/>"
+ "<script language='JavaScript' type='text/javascript' src='js/toggle.js'></script>";
req.setAttribute("css",css);
req.setAttribute("bodyJsp","/"+Controllers.ENTITY_NOT_FOUND_JSP);
RequestDispatcher rd = req.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(req,res);
}
private String forURL(String frag)
{
String result = null;
try
{
result = URLEncoder.encode(frag, "UTF-8");
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("UTF-8 not supported", ex);
}
return result;
}
private class HelpException extends Throwable{}
private class EntityNotFoundException extends Throwable{}
}

View file

@ -1,321 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.TabEntitiesController.PageRecord;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.flags.FlagException;
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
import edu.cornell.mannlib.vitro.webapp.utils.FlagMathUtils;
public class EntityListController extends VitroHttpServlet {
public static final int ENTITY_LIST_CONTROLLER_MAX_RESULTS = 30000;
public static final int INDIVIDUALS_PER_PAGE = 30;
long startTime = -1;
private static final Log log = LogFactory.getLog(EntityListController.class.getName());
/**
* This generates a list of entities and then sends that
* off to a jsp to be displayed.
*
* Expected parameters:
*
* Expected Attributes:
* entity - set to entity to display properties for.
*
* @author bdc34
*/
public void doGet( HttpServletRequest req, HttpServletResponse res )
throws IOException, ServletException {
startTime = System.currentTimeMillis(); // TODO: remove
try {
super.doGet(req, res);
VitroRequest vreq = new VitroRequest(req);
Object obj = req.getAttribute("vclass");
VClass vclass=null;
if( obj == null ) { // look for vitroclass id parameter
String vitroClassIdStr=req.getParameter("vclassId");
if (vitroClassIdStr!=null && !vitroClassIdStr.equals("")) {
try {
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vitroClassIdStr);
if (vclass == null) {
log.error("Couldn't retrieve vclass "+vitroClassIdStr);
res.sendRedirect(Controllers.BROWSE_CONTROLLER+"?"+req.getQueryString());
}
} catch (Exception ex) {
throw new HelpException("EntityListController: request parameter 'vclassId' must be a URI string");
}
}
} else if (obj instanceof VClass) {
vclass = (VClass)obj;
} else {
throw new HelpException("EntityListController: attribute 'vclass' must be of type "
+ VClass.class.getName() );
}
if (vclass!=null)
doVClass(vreq, res, vclass);
else
log.debug("no vclass found for " + obj);
} catch (HelpException help){
doHelp(res);
} catch (Throwable e) {
req.setAttribute("javax.servlet.jsp.jspException",e);
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
rd.forward(req, res);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
/**
* Perform the actions needed for the entity list jsp.
* @param request
* @param res
* @param vclass
* @throws ServletException
* @throws IOException
*/
private void doVClass(VitroRequest request, HttpServletResponse res, VClass vclass)
throws ServletException, IOException, FlagException {
Map<String,Object> results = getResultsForVClass(
vclass.getURI(),
getPageParameter(request),
getAlphaParamter(request),
request.getPortal(),
request.getWebappDaoFactory().getPortalDao().isSinglePortal(),
request.getWebappDaoFactory().getIndividualDao(),
getServletContext());
/* copy values from results in to request attributes */
request.setAttribute("entities", results.get("entities"));
request.setAttribute("count",results.get("count"));
request.setAttribute("totalCount",results.get("totalCount"));
request.setAttribute("alpha",results.get("alpha"));
request.setAttribute("showPages",results.get("showPages"));
request.setAttribute("pages",results.get("pages"));
/* Setup any additional attributes that are needed */
request.setAttribute("servlet",Controllers.ENTITY_LIST);
request.setAttribute("vclassId", vclass.getURI());
request.setAttribute("controllerParam","vclassId=" + URLEncoder.encode(vclass.getURI(),"UTF-8"));
request.setAttribute("showAlpha","1");
request.setAttribute("letters",Controllers.getLetters());
VClassGroup classGroup=vclass.getGroup();
if (classGroup==null) {
request.setAttribute("title",vclass.getName()/* + "&nbsp;("+vclass.getEntityCount()+")"*/);
} else {
request.setAttribute("title",classGroup.getPublicName());
request.setAttribute("subTitle",vclass.getName()/* + "&nbsp;("+vclass.getEntityCount()+")"*/);
}
//FINALLY: send off to the BASIC_JSP to get turned into html
request.setAttribute("bodyJsp",Controllers.ENTITY_LIST_JSP);
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
// use this for more direct debugging: RequestDispatcher rd = request.getRequestDispatcher(Controllers.ENTITY_LIST_JSP);
res.setContentType("text/html; charset=UTF-8");
request.setAttribute("pageTime", System.currentTimeMillis()-startTime);
rd.include(request,res);
}
/**
* This method is now called in a couple of places. It should be refactored
* into a DAO or similar object.
*/
public static Map<String,Object> getResultsForVClass(String vclassURI, int page, String alpha, Portal portal, boolean isSinglePortal, IndividualDao indDao, ServletContext context)
throws CorruptIndexException, IOException, ServletException{
Map<String,Object> rvMap = new HashMap<String,Object>();
int portalId = 1;
if( portal != null )
portalId = portal.getPortalId();
//make lucene query for this rdf:type
Query query = getQuery(vclassURI,alpha, isSinglePortal, portalId);
//execute lucene query for individuals of the specified type
IndexSearcher index = LuceneIndexFactory.getIndexSearcher(context);
TopDocs docs = null;
try{
docs = index.search(query, null,
ENTITY_LIST_CONTROLLER_MAX_RESULTS,
new Sort(Entity2LuceneDoc.term.NAMELOWERCASE));
}catch(Throwable th){
log.error("Could not run search. " + th.getMessage());
docs = null;
}
if( docs == null )
throw new ServletException("Could not run search in EntityListController");
//get list of individuals for the search results
int size = docs.totalHits;
log.debug("Number of search results: " + size);
// don't get all the results, only get results for the requestedSize
List<Individual> individuals = new ArrayList<Individual>(INDIVIDUALS_PER_PAGE);
int individualsAdded = 0;
int ii = (page-1)*INDIVIDUALS_PER_PAGE;
while( individualsAdded < INDIVIDUALS_PER_PAGE && ii < size ){
ScoreDoc hit = docs.scoreDocs[ii];
if (hit != null) {
Document doc = index.doc(hit.doc);
if (doc != null) {
String uri = doc.getField(Entity2LuceneDoc.term.URI).stringValue();
Individual ind = indDao.getIndividualByURI( uri );
if( ind != null ){
individuals.add( ind );
individualsAdded++;
}
} else {
log.warn("no document found for lucene doc id " + hit.doc);
}
} else {
log.debug("hit was null");
}
ii++;
}
rvMap.put("count", size);
if( size > INDIVIDUALS_PER_PAGE ){
rvMap.put("showPages", Boolean.TRUE);
List<PageRecord> pageRecords = TabEntitiesController.makePagesList(size, INDIVIDUALS_PER_PAGE, page);
rvMap.put("pages", pageRecords);
}else{
rvMap.put("showPages", Boolean.FALSE);
rvMap.put("pages", Collections.emptyList());
}
rvMap.put("alpha",alpha);
rvMap.put("totalCount", size);
rvMap.put("entities",individuals);
if (individuals == null)
log.debug("entities list is null for vclass " + vclassURI );
return rvMap;
}
private static BooleanQuery getQuery(String vclassUri, String alpha , boolean isSinglePortal, int portalId){
BooleanQuery query = new BooleanQuery();
try{
//query term for rdf:type
query.add(
new TermQuery( new Term(Entity2LuceneDoc.term.RDFTYPE, vclassUri)),
BooleanClause.Occur.MUST );
//check for portal filtering
if( ! isSinglePortal ){
if( portalId < 16 ){ //could be a normal portal
query.add(
new TermQuery( new Term(Entity2LuceneDoc.term.PORTAL, Integer.toString(1 << portalId ))),
BooleanClause.Occur.MUST);
}else{ //could be a combined portal
BooleanQuery tabQueries = new BooleanQuery();
Long[] ids= FlagMathUtils.numeric2numerics(portalId);
for( Long id : ids){
tabQueries.add(
new TermQuery( new Term(Entity2LuceneDoc.term.PORTAL,id.toString()) ),
BooleanClause.Occur.SHOULD);
}
query.add(tabQueries,BooleanClause.Occur.MUST);
}
}
//Add alpha filter if it is needed
Query alphaQuery = null;
if( alpha != null && !"".equals(alpha) && alpha.length() == 1){
alphaQuery =
new PrefixQuery(new Term(Entity2LuceneDoc.term.NAMELOWERCASE, alpha.toLowerCase()));
query.add(alphaQuery,BooleanClause.Occur.MUST);
}
log.debug("Query: " + query);
return query;
}catch (Exception ex){
log.error(ex,ex);
return new BooleanQuery();
}
}
public static int getPageParameter(VitroRequest request) {
String pageStr = request.getParameter("page");
if( pageStr != null ){
try{
return Integer.parseInt(pageStr);
}catch(NumberFormatException nfe){
log.debug("could not parse page parameter");
return 1;
}
}else{
return 1;
}
}
public static String getAlphaParamter(VitroRequest request){
return request.getParameter("alpha");
}
private void doHelp(HttpServletResponse res)
throws IOException, ServletException {
ServletOutputStream out = res.getOutputStream();
res.setContentType("text/html; charset=UTF-8");
out.println("<html><body><h2>Quick Notes on using EntityList:</h2>");
out.println("<p>request.attributes 'entities' must be set by servlet before calling."
+" It must be a List of Entity objects </p>");
out.println("</body></html>");
}
private class HelpException extends Throwable{
public HelpException(String string) {
super(string);
}
}
}

View file

@ -1,823 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jga.fn.UnaryFunctor;
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.ObjectPropertyStatement;
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.beans.VClass;
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.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import edu.cornell.mannlib.vitro.webapp.servlet.setup.PropertyMaskingSetup;
public class EntityMergedPropertyListController extends VitroHttpServlet {
/**
* This gets the Entity object in the requestScope "entity" and
* sets up a merged property list for it. This merged list includes
* Object and Data properties.
*
* After that a jsp is called to draw the data.
*
* Expected parameters:
*
* Expected Attributes:
* entity - set to entity to display properties for.
*
* @author jc55 forked this file from EntityPropertyListController
*/
private static final Log log = LogFactory.getLog(EntityMergedPropertyListController.class.getName());
private static final int MAX_GROUP_DISPLAY_RANK = 99;
private static final String VIVO_CORE_NAMESPACE = "http://vivoweb.org/ontology/core#";
/** Don't include these properties in the list. */
private static final Collection<String> SUPPRESSED_OBJECT_PROPERTIES = Collections
.unmodifiableCollection(Arrays
.asList(new String[] { VitroVocabulary.IND_MAIN_IMAGE }));
public void doGet( HttpServletRequest request, HttpServletResponse res )
throws IOException, ServletException {
VitroRequest req = new VitroRequest(request);
try {
super.doGet(req, res);
Object obj = req.getAttribute("entity");
if( obj == null || !(obj instanceof Individual))
throw new HelpException("EntityMergedPropertyListController requires request.attribute 'entity' to be of"
+" type " + Individual.class.getName() );
Individual subject =(Individual)obj;
subject = filterFromContext( subject );
// determine whether are just displaying populated properties or also interleaving unpopulated ones
boolean editMode = false;
String modeStr = req.getParameter("mode");
if (modeStr != null && modeStr.indexOf("edit")>=0) {
editMode = true;
}
boolean groupedMode = false;
String groupedStr = req.getParameter("grouped");
if (groupedStr != null && groupedStr.equalsIgnoreCase("true")) {
groupedMode = true;
}
String groupForUngroupedProperties = null;
String unassignedStr = req.getParameter("unassignedPropsGroupName");
if (unassignedStr != null && unassignedStr.length()>0) {
groupForUngroupedProperties = unassignedStr;
//pass this on to entityMergedPropsList.jsp
req.setAttribute("unassignedPropsGroupName", unassignedStr);
log.debug("found temp group parameter \""+unassignedStr+"\" for unassigned properties");
}
// set up a new list for the combined object and data properties
VitroRequest vreq = new VitroRequest(req);
WebappDaoFactory wdf = vreq.getWebappDaoFactory();
PropertyGroupDao pgDao = null;
List <PropertyGroup> groupsList = null;
if (groupedMode) {
pgDao = wdf.getPropertyGroupDao();
groupsList = pgDao.getPublicGroups(false); // may be returned empty but not null
}
List<Property> mergedPropertyList = new ArrayList<Property>();
// now first get the properties this entity actually has, presumably populated with statements
List<ObjectProperty> objectPropertyList = subject.getObjectPropertyList();
for (ObjectProperty op : objectPropertyList) {
if (!SUPPRESSED_OBJECT_PROPERTIES.contains(op)) {
op.setLabel(op.getDomainPublic());
mergedPropertyList.add(op);
}else{
log.debug("suppressed " + op.getURI());
}
}
if (editMode) {
// for the full list, in order to show empty properties, now need to merge in new ObjectProperty objects with null objectPropertyStatements
PropertyInstanceDao piDao = wdf.getPropertyInstanceDao();
ObjectPropertyDao opDao = wdf.getObjectPropertyDao();
Collection<PropertyInstance> allPropInstColl = piDao.getAllPossiblePropInstForIndividual(subject.getURI());
if (allPropInstColl != null) {
for (PropertyInstance pi : allPropInstColl) {
if (pi!=null) {
if (!alreadyOnObjectPropertyList(objectPropertyList,pi)) {
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 (!alreadyOnPropertyList(mergedPropertyList,op)) {
op.setLabel(op.getDomainPublic());
mergedPropertyList.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()");
}
}
// now do much the same with data properties: get the list of populated data properties, then add in placeholders for missing ones
List<DataProperty> dataPropertyList = subject.getDataPropertyList();
for (DataProperty dp : dataPropertyList) {
dp.setLabel(dp.getPublicName());
mergedPropertyList.add(dp);
}
if (editMode) {
DataPropertyDao dpDao = wdf.getDataPropertyDao();
Collection <DataProperty> 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 (!alreadyOnPropertyList(mergedPropertyList,dp)) {
dp.setLabel(dp.getPublicName());
mergedPropertyList.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())");
}
}
if (mergedPropertyList!=null) {
try {
Collections.sort(mergedPropertyList,new PropertyRanker(vreq));
} catch (Exception ex) {
log.error("Exception sorting merged property list: " + ex.getMessage());
}
//deal with collateBySubclass annotations on object properties
mergedPropertyList = collateBySubclass( mergedPropertyList );
if (groupedMode) {
int groupsCount=0;
try {
groupsCount = populateGroupsListWithProperties(pgDao,groupsList,mergedPropertyList,groupForUngroupedProperties);
} catch (Exception ex) {
log.error("Exception on trying to populate groups list with properties: "+ex.getMessage());
ex.printStackTrace();
}
try {
int removedCount = pgDao.removeUnpopulatedGroups(groupsList);
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 : groupsList) {
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<ObjectPropertyStatement> 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());
}
mergedPropertyList.clear();
} else { // ungrouped mode
for (Property p : mergedPropertyList) {
if (p instanceof ObjectProperty) {
ObjectProperty op = (ObjectProperty)p;
applyCustomSortToUncollatedProperty(op, op.getObjectPropertyStatements());
}
}
}
}
if (groupedMode) {
req.setAttribute("groupsList",groupsList);
} else {
UnaryFunctor<List<Property>,List<Property>> entityPropertyListFilter = PropertyMaskingSetup.getEntityPropertyListFilter(getServletContext());
if (entityPropertyListFilter != null) {
mergedPropertyList = entityPropertyListFilter.fn(mergedPropertyList);
}
req.setAttribute("mergedList",mergedPropertyList);
}
req.setAttribute("entity",subject);
RequestDispatcher rd = req.getRequestDispatcher(groupedMode ? Controllers.ENTITY_MERGED_PROP_LIST_GROUPED_JSP : Controllers.ENTITY_MERGED_PROP_LIST_UNGROUPED_JSP);
rd.include(req,res);
} catch (HelpException help){
doHelp(res);
} catch (Throwable e) {
req.setAttribute("javax.servlet.jsp.jspException",e);
log.error("exception thrown: "+e.getMessage());
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
// rd.forward(req, res); response has already been committed
rd.include(req, res);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
private boolean alreadyOnObjectPropertyList(List<ObjectProperty> opList, PropertyInstance pi) {
if (pi.getPropertyURI() == null) {
return false;
}
for (ObjectProperty op : opList) {
if (op.getURI() != null && op.getURI().equals(pi.getPropertyURI())) {
return op.isSubjectSide() == pi.getSubjectSide();
}
}
return false;
}
private boolean alreadyOnPropertyList(List<Property> propsList, Property p) {
if (p.getURI() == null) {
log.error("Property p has no propertyURI in alreadyOnPropertyList()");
return true; // don't add to list
}
for (Property ptest : propsList) {
if (ptest.getURI() != null && ptest.getURI().equals(p.getURI())) {
return true;
}
}
return false;
}
private int populateGroupsListWithProperties(PropertyGroupDao pgDao, List<PropertyGroup> groupsList, List<Property> mergedPropertyList, String unassignedGroupName) {
int count = groupsList.size();
PropertyGroup tempGroup = null;
if (unassignedGroupName!=null) {
tempGroup = pgDao.createDummyPropertyGroup(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.getLabel()+" 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;
}
private void doHelp(HttpServletResponse res)
throws IOException, ServletException {
ServletOutputStream out = res.getOutputStream();
res.setContentType("text/html; charset=UTF-8");
out.println("<html><body><h2>Quick Notes on using EntityMergedPropList:</h2>");
out.println("<p>request.attributes 'entity' must be set by Entity servlet before calling."
+" It should already be 'filled out.' </p>");
out.println("</body></html>");
}
private class HelpException extends Throwable{
public HelpException(String string) {
super(string);
}
}
private class PropertyRanker implements Comparator {
VitroRequest vreq;
WebappDaoFactory wdf;
PropertyGroupDao pgDao;
private PropertyRanker(VitroRequest vreq) {
this.vreq = 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.getLabel());
}
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.getLabel());
}
// 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.getLabel().compareTo(p2.getLabel());
} 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;
}
}
private List<Property> collateBySubclass(List<Property> mergedPropertyList) {
for( Property prop : mergedPropertyList){
if( prop instanceof ObjectProperty ) {
ObjectProperty op = (ObjectProperty) prop;
if (op.getCollateBySubclass() ){
log.debug("Collating property " + prop.getURI() + " by subclass");
collateBySubclass(op);
} else {
}
}
}
return mergedPropertyList;
}
/**
* Sort the object property statements for each property so that they
* are sorted first by subclass and then by rdfs:label.
*
* This will be tricky since "subclass" is vaguely defined. Here directly
* asserted classes are used.
*/
private void collateBySubclass(ObjectProperty prop) {
List<ObjectPropertyStatement> orgStmtList = getStatementsToCollate(prop);
if( orgStmtList == null ) {
return;
}
Map<String,VClass> directClasses = getDirectClasses( getObjectsFromStmts( orgStmtList ) );
//don't do collateBySubclass if there is only one class
if( directClasses.size() < 2 ) {
// rjy7 Removed this, so we still get the heading for the single populated subclass
//prop.setCollateBySubclass(false); //this overrides the value from the model
// Still need to apply custom sort. Since we no longer set collateBySubclass to false,
// we won't know in applyCustomSortToUncollatedProperty whether the statements have
// been sorted or not, so we must do that now.
applyCustomSortToUncollatedStatements(prop, orgStmtList);
} else {
log.debug("statements for object property: " + orgStmtList.size());
//get list of direct classes and sort them
List<VClass> vclasses = new LinkedList<VClass>(directClasses.values());
Collections.sort(
vclasses,
new Comparator<VClass>(){
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>();
for (VClass clazz : vclasses) {
// get all obj prop stmts with objects of this class
List<ObjectPropertyStatement> stmtsForClass = new ArrayList<ObjectPropertyStatement>();
log.debug("statements for object property: " + orgStmtList.size());
Iterator<ObjectPropertyStatement> it = orgStmtList.iterator();
while( it.hasNext()){
ObjectPropertyStatement stmt = it.next();
//if (stmt.getObject().getVClasses(true).contains(clazz)) {
Individual obj = stmt.getObject();
List<VClass> vclassesForObj = obj.getVClasses(true);
if (vclassesForObj != null && vclassesForObj.contains(clazz)) {
log.debug("adding " + stmt + " to class "
+ clazz.getURI());
log.debug("subjectURI " + stmt.getSubjectURI()
+ " objectURI" + stmt.getObject().getURI());
log.debug("stmtsForclass size: "
+ stmtsForClass.size());
log.debug("stmtsForclass size: "
+ stmtsForClass.size());
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
orgStmtList.removeAll(stmtsForClass);
sortStatements(prop, stmtsForClass);
log.debug("stmtsForclass size after sort: "
+ stmtsForClass.size());
log.debug("sortedStmtList size before add: "
+ sortedStmtList.size());
sortedStmtList.addAll(stmtsForClass);
log.debug("sortedStmtList size after add: "
+ sortedStmtList.size());
}
prop.setObjectPropertyStatements(sortedStmtList);
}
}
private List<ObjectPropertyStatement> getStatementsToCollate(ObjectProperty prop) {
List<ObjectPropertyStatement> statements = prop.getObjectPropertyStatements();
if (statements != null) {
String propertyUri = prop.getURI();
if (propertyUri.equals(VIVO_CORE_NAMESPACE + "authorInAuthorship")) {
return getStatementsForRelatedIndividuals(statements, VIVO_CORE_NAMESPACE + "linkedInformationResource");
}
}
return statements;
}
private List<ObjectPropertyStatement> getStatementsForRelatedIndividuals(List<ObjectPropertyStatement> statements, String op) {
List<ObjectPropertyStatement> relatedStatements = new ArrayList<ObjectPropertyStatement>(statements.size());
for (ObjectPropertyStatement statement : statements) {
Individual object = statement.getObject();
List<ObjectPropertyStatement> statementsForObject = object.getObjectPropertyStatements(op);
// Could be empty for statements with no linked individual.
if ( ! statementsForObject.isEmpty() ) {
relatedStatements.add(statementsForObject.get(0));
}
}
return relatedStatements;
}
private void sortStatements(ObjectProperty prop, List<ObjectPropertyStatement> statements) {
if (statements.size() < 2) {
return;
}
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 propertyUri = prop.getURI();
// Positions in an organization
if (propertyUri.equals(VIVO_CORE_NAMESPACE + "organizationForPosition")) {
sortByRelatedIndividualName(statements, VIVO_CORE_NAMESPACE + "positionForPerson");
return true;
}
// Person's positions
if (propertyUri.equals(VIVO_CORE_NAMESPACE + "personInPosition")) {
sortReverseChron(statements, VIVO_CORE_NAMESPACE + "endYear", VIVO_CORE_NAMESPACE + "startYear");
return true;
}
// Person's publications
// Note that, due to the custom collation, the object property statements actually have predicate
// linkedInformationResource. The property being sorted is still authorInAuthorship, however.
if (propertyUri.equals(VIVO_CORE_NAMESPACE + "authorInAuthorship")) {
sortByYearAndName(statements, VIVO_CORE_NAMESPACE + "year");
return true;
}
return false;
}
private void applyCustomSortToUncollatedProperty(ObjectProperty op, List<ObjectPropertyStatement> opStmts) {
if (!op.getCollateBySubclass()) {
applyCustomSortToUncollatedStatements(op, opStmts);
}
}
// Apply custom sorting to an uncollated property. If the property is collated, the custom sorting has already
// been applied to each subclass listing individually.
private void applyCustomSortToUncollatedStatements(ObjectProperty op, List<ObjectPropertyStatement> opStmts) {
if (applyCustomSort(op, opStmts)) {
op.setObjectPropertyStatements(opStmts);
}
}
private void sortReverseChron(List<ObjectPropertyStatement> statements, String endYearPredicate, String startYearPredicate) {
// 1. Sort by end year descending, nulls first
// 2. Then by start year descending, nulls last
// 3. No sorting for entries with no start or end year - 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) {
Individual objLeft = left.getObject();
String endLeftValue = objLeft.getDataValue(endYearProperty);
Integer endLeft = endLeftValue == null ? null : Integer.valueOf(endLeftValue);
String startLeftValue = objLeft.getDataValue(startYearProperty);
Integer startLeft = startLeftValue == null ? null : Integer.valueOf(startLeftValue);
Individual objRight = right.getObject();
String endRightValue = objRight.getDataValue(endYearProperty);
Integer endRight = endRightValue == null ? null : Integer.valueOf(endRightValue);
String startRightValue = objRight.getDataValue(startYearProperty);
Integer startRight = startRightValue == null ? null : Integer.valueOf(startRightValue);
// No sorting for entries with no start or end year - just put at the bottom in random order
if (endLeft == null && startLeft == null) {
return 1;
}
if (endRight == null && startRight == null) {
return -1;
}
// First sort by end year
// A null end year precedes
// But if both end years are null, compare start years
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 years are equal, sort by start year
// A null start year follows
if (startLeft == null) {
return 1;
}
if (startRight == null) {
return -1;
}
return 0 - startLeft.compareTo(startRight);
}
});
}
private void sortByYearAndName(List<ObjectPropertyStatement> statements, String yearPredicate) {
// 1. Sort by year descending, nulls at end
// 2. If years are the same, sort by name
final String yearProperty = yearPredicate;
Collections.sort(statements, new Comparator<ObjectPropertyStatement>() {
public int compare(ObjectPropertyStatement left, ObjectPropertyStatement right) {
Individual indLeft = left.getObject();
String leftYearValue = indLeft.getDataValue(yearProperty);
Integer leftYear = leftYearValue == null ? null : Integer.valueOf(leftYearValue);
Individual indRight = right.getObject();
String rightYearValue = indRight.getDataValue(yearProperty);
Integer rightYear = rightYearValue == null ? null : Integer.valueOf(rightYearValue);
// First sort by year, nulls at end
// But if both null, sort by name
if ( ! (leftYear == null && rightYear == null) ) {
if (leftYear == null) {
return 1;
}
if (rightYear == null) {
return -1;
}
int yearComp = leftYear.compareTo(rightYear);
if (yearComp != 0) {
return 0 - yearComp;
}
}
// If years are equal, sort by publication name
return indLeft.getName().compareTo(indRight.getName());
}
});
}
// Sort statements by the name of the individual on the other side of the context node.
private void sortByRelatedIndividualName(List<ObjectPropertyStatement> statements, String predicateUri) {
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);
if (indLeft == null) {
return indRight == null ? 0 : 1;
}
if (indRight == null) {
return -1;
}
return indLeft.getName().compareTo(indRight.getName());
}
});
}
private List<Individual> getObjectsFromStmts(List<ObjectPropertyStatement> orgStmtList) {
List<Individual> individuals = new LinkedList<Individual>();
for( ObjectPropertyStatement stmt : orgStmtList ){
individuals.add( stmt.getObject() );
}
return individuals;
}
private Map<String,VClass> getDirectClasses(List<Individual> objectsFromStmts) {
Map<String,VClass> directClasses = new HashMap<String,VClass>();
for (Individual ind : objectsFromStmts) {
for (VClass clazz : ind.getVClasses(true)) {
directClasses.put(clazz.getURI(),clazz);
}
}
return directClasses;
}
/**
* 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
* created to deal with problems caused by custom short views.
* *
* @param objectPropertyList
* @param wdf
* @return
*/
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");
}
}

View file

@ -1,74 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.controller;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class EntityPropertyListController extends VitroHttpServlet {
/**
* This gets the Entity object in the requestScope "entity" and
* sets up the property list for it. After that a jsp is
* called to draw the data.
*
* Expected parameters:
*
* Expected Attributes:
* entity - set to entity to display properties for.
*
* @author bdc34
*/
public void doGet( HttpServletRequest req, HttpServletResponse res )
throws IOException, ServletException {
try {
//we don't need to call super because this method does no DAO calls.
//super.doGet(req, res);
Object obj = req.getAttribute("entity");
if( obj == null || !(obj instanceof Individual))
throw new HelpException("EntityPropertyListController requires request.attribute 'entity' to be of"
+" type " + Individual.class.getName() );
Individual entity =(Individual)obj;
//sort property list in display order
entity.sortForDisplay();
req.setAttribute("entity",entity);
RequestDispatcher rd = req.getRequestDispatcher(Controllers.ENTITY_PROP_LIST_JSP);
rd.include(req,res);
} catch (HelpException help){
doHelp(res);
} catch (Throwable e) {
req.setAttribute("javax.servlet.jsp.jspException",e);
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
rd.forward(req, res);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException,IOException {
doGet(request, response);
}
private void doHelp(HttpServletResponse res)
throws IOException, ServletException {
ServletOutputStream out = res.getOutputStream();
res.setContentType("text/html; charset=UTF-8");
out.println("<html><body><h2>Quick Notes on using EntityPropList:</h2>");
out.println("<p>request.attributes 'entity' must be set by Entity servlet before calling."
+" It should already be 'filled out.' </p>");
out.println("</body></html>");
}
private class HelpException extends Throwable{
public HelpException(String string) {
super(string);
}}
}

View file

@ -8,7 +8,6 @@ import java.io.Writer;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
@ -35,6 +34,7 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.TabEntitiesController.PageRecord;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder;
import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
@ -43,8 +43,6 @@ import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.EditConfiguration;
import edu.cornell.mannlib.vitro.webapp.edit.n3editing.SelectListGenerator;
import edu.cornell.mannlib.vitro.webapp.search.beans.ProhibitedFromSearch;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassTemplateModel;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.IndividualTemplateModel;
/**
@ -222,9 +220,9 @@ public class JSONServlet extends VitroHttpServlet {
.put("name",vclass.getName()));
if (vclass != null) {
String alpha = EntityListController.getAlphaParamter(vreq);
int page = EntityListController.getPageParameter(vreq);
Map<String,Object> map = EntityListController.getResultsForVClass(
String alpha = IndividualListController.getAlphaParameter(vreq);
int page = IndividualListController.getPageParameter(vreq);
Map<String,Object> map = IndividualListController.getResultsForVClass(
vclass.getURI(),
page,
alpha,

View file

@ -47,7 +47,6 @@ public class OntologyController extends VitroHttpServlet{
private static final Log log = LogFactory.getLog(OntologyController.class.getName());
private String default_jsp = Controllers.BASIC_JSP;
private String default_body_jsp = Controllers.ENTITY_JSP;
private ApplicationBean appBean;
public void doPost(HttpServletRequest request, HttpServletResponse response)

View file

@ -2,23 +2,45 @@
package edu.cornell.mannlib.vitro.webapp.controller.freemarker;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.PrefixQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.EntityListController;
import edu.cornell.mannlib.vitro.webapp.controller.TabEntitiesController;
import edu.cornell.mannlib.vitro.webapp.controller.TabEntitiesController.PageRecord;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ExceptionResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.ResponseValues;
import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
import edu.cornell.mannlib.vitro.webapp.utils.FlagMathUtils;
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
import edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual.ListedIndividualTemplateModel;
import freemarker.ext.beans.BeansWrapper;
@ -32,6 +54,9 @@ public class IndividualListController extends FreemarkerHttpServlet {
private static final long serialVersionUID = 1L;
private static final Log log = LogFactory.getLog(IndividualListController.class.getName());
public static final int ENTITY_LIST_CONTROLLER_MAX_RESULTS = 30000;
public static final int INDIVIDUALS_PER_PAGE = 30;
private static final String TEMPLATE_DEFAULT = "individualList.ftl";
@Override
@ -69,9 +94,9 @@ public class IndividualListController extends FreemarkerHttpServlet {
body.put("vclassId", vclass.getURI());
if (vclass != null) {
String alpha = EntityListController.getAlphaParamter(vreq);
int page = EntityListController.getPageParameter(vreq);
Map<String,Object> map = EntityListController.getResultsForVClass(
String alpha = getAlphaParameter(vreq);
int page = getPageParameter(vreq);
Map<String,Object> map = getResultsForVClass(
vclass.getURI(),
page,
alpha,
@ -132,4 +157,144 @@ public class IndividualListController extends FreemarkerHttpServlet {
super(string);
}
}
public static String getAlphaParameter(VitroRequest request){
return request.getParameter("alpha");
}
public static int getPageParameter(VitroRequest request) {
String pageStr = request.getParameter("page");
if( pageStr != null ){
try{
return Integer.parseInt(pageStr);
}catch(NumberFormatException nfe){
log.debug("could not parse page parameter");
return 1;
}
}else{
return 1;
}
}
/**
* This method is now called in a couple of places. It should be refactored
* into a DAO or similar object.
*/
public static Map<String,Object> getResultsForVClass(String vclassURI, int page, String alpha, Portal portal, boolean isSinglePortal, IndividualDao indDao, ServletContext context)
throws CorruptIndexException, IOException, ServletException{
Map<String,Object> rvMap = new HashMap<String,Object>();
int portalId = 1;
if( portal != null )
portalId = portal.getPortalId();
//make lucene query for this rdf:type
Query query = getQuery(vclassURI,alpha, isSinglePortal, portalId);
//execute lucene query for individuals of the specified type
IndexSearcher index = LuceneIndexFactory.getIndexSearcher(context);
TopDocs docs = null;
try{
docs = index.search(query, null,
ENTITY_LIST_CONTROLLER_MAX_RESULTS,
new Sort(Entity2LuceneDoc.term.NAMELOWERCASE));
}catch(Throwable th){
log.error("Could not run search. " + th.getMessage());
docs = null;
}
if( docs == null )
throw new ServletException("Could not run search in IndividualListController");
//get list of individuals for the search results
int size = docs.totalHits;
log.debug("Number of search results: " + size);
// don't get all the results, only get results for the requestedSize
List<Individual> individuals = new ArrayList<Individual>(INDIVIDUALS_PER_PAGE);
int individualsAdded = 0;
int ii = (page-1)*INDIVIDUALS_PER_PAGE;
while( individualsAdded < INDIVIDUALS_PER_PAGE && ii < size ){
ScoreDoc hit = docs.scoreDocs[ii];
if (hit != null) {
Document doc = index.doc(hit.doc);
if (doc != null) {
String uri = doc.getField(Entity2LuceneDoc.term.URI).stringValue();
Individual ind = indDao.getIndividualByURI( uri );
if( ind != null ){
individuals.add( ind );
individualsAdded++;
}
} else {
log.warn("no document found for lucene doc id " + hit.doc);
}
} else {
log.debug("hit was null");
}
ii++;
}
rvMap.put("count", size);
if( size > INDIVIDUALS_PER_PAGE ){
rvMap.put("showPages", Boolean.TRUE);
List<PageRecord> pageRecords = TabEntitiesController.makePagesList(size, INDIVIDUALS_PER_PAGE, page);
rvMap.put("pages", pageRecords);
}else{
rvMap.put("showPages", Boolean.FALSE);
rvMap.put("pages", Collections.emptyList());
}
rvMap.put("alpha",alpha);
rvMap.put("totalCount", size);
rvMap.put("entities",individuals);
if (individuals == null)
log.debug("entities list is null for vclass " + vclassURI );
return rvMap;
}
private static BooleanQuery getQuery(String vclassUri, String alpha , boolean isSinglePortal, int portalId){
BooleanQuery query = new BooleanQuery();
try{
//query term for rdf:type
query.add(
new TermQuery( new Term(Entity2LuceneDoc.term.RDFTYPE, vclassUri)),
BooleanClause.Occur.MUST );
//check for portal filtering
if( ! isSinglePortal ){
if( portalId < 16 ){ //could be a normal portal
query.add(
new TermQuery( new Term(Entity2LuceneDoc.term.PORTAL, Integer.toString(1 << portalId ))),
BooleanClause.Occur.MUST);
}else{ //could be a combined portal
BooleanQuery tabQueries = new BooleanQuery();
Long[] ids= FlagMathUtils.numeric2numerics(portalId);
for( Long id : ids){
tabQueries.add(
new TermQuery( new Term(Entity2LuceneDoc.term.PORTAL,id.toString()) ),
BooleanClause.Occur.SHOULD);
}
query.add(tabQueries,BooleanClause.Occur.MUST);
}
}
//Add alpha filter if it is needed
Query alphaQuery = null;
if( alpha != null && !"".equals(alpha) && alpha.length() == 1){
alphaQuery =
new PrefixQuery(new Term(Entity2LuceneDoc.term.NAMELOWERCASE, alpha.toLowerCase()));
query.add(alphaQuery,BooleanClause.Occur.MUST);
}
log.debug("Query: " + query);
return query;
}catch (Exception ex){
log.error(ex,ex);
return new BooleanQuery();
}
}
}

View file

@ -2,6 +2,12 @@
package edu.cornell.mannlib.vitro.webapp.dao.jena;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.logging.Log;
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.rdf.model.Resource;
@ -9,27 +15,16 @@ import com.hp.hpl.jena.rdf.model.Statement;
import com.hp.hpl.jena.shared.Lock;
import com.hp.hpl.jena.util.iterator.ClosableIterator;
import com.hp.hpl.jena.vocabulary.RDF;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Tab;
import edu.cornell.mannlib.vitro.webapp.beans.TabIndividualRelation;
import edu.cornell.mannlib.vitro.webapp.controller.EntityController;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.dao.TabIndividualRelationDao;
import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
public class TabIndividualRelationDaoJena extends JenaBaseDao implements TabIndividualRelationDao {
private static final Log log = LogFactory.getLog(EntityController.class.getName());
private static final Log log = LogFactory.getLog(TabIndividualRelationDaoJena.class.getName());
public TabIndividualRelationDaoJena(WebappDaoFactoryJena wadf) {
super(wadf);

View file

@ -1,640 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.controller;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.WildcardQuery;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassDao;
import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupDao;
import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary;
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
import edu.cornell.mannlib.vitro.webapp.search.SearchException;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQuery;
import edu.cornell.mannlib.vitro.webapp.search.lucene.Entity2LuceneDoc;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneIndexFactory;
import edu.cornell.mannlib.vitro.webapp.search.lucene.LuceneSetup;
import edu.cornell.mannlib.vitro.webapp.utils.FlagMathUtils;
/**
* PagedSearchController is the new search controller that interacts
* directly with the lucene API and returns paged, relevance ranked results.
*
* @author bdc34
*
*/
public class PagedSearchController extends VitroHttpServlet {
private static final Log log = LogFactory.getLog(PagedSearchController.class.getName());
String NORESULT_MSG = "The search returned no results.";
private int defaultHitsPerPage = 25;
private int defaultMaxSearchSize= 1000;
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
super.doGet(request,response);
VitroRequest vreq = new VitroRequest(request);
Portal portal = vreq.getPortal();
PortalFlag portalFlag = vreq.getPortalFlag();
//make sure an IndividualDao is available
if( vreq.getWebappDaoFactory() == null
|| vreq.getWebappDaoFactory().getIndividualDao() == null ){
log.error("makeUsableBeans() could not get IndividualDao ");
doSearchError(request, response, "Could not access Model", portalFlag);
return;
}
IndividualDao iDao = vreq.getWebappDaoFactory().getIndividualDao();
VClassGroupDao grpDao = vreq.getWebappDaoFactory().getVClassGroupDao();
VClassDao vclassDao = vreq.getWebappDaoFactory().getVClassDao();
String alphaFilter = vreq.getParameter("alpha");
int startIndex = 0;
try{
startIndex = Integer.parseInt(request.getParameter("startIndex"));
}catch (Throwable e) {
startIndex = 0;
}
log.debug("startIndex is " + startIndex);
int hitsPerPage = defaultHitsPerPage;
try{
hitsPerPage = Integer.parseInt(request.getParameter("hitsPerPage"));
} catch (Throwable e) {
hitsPerPage = defaultHitsPerPage;
}
log.debug("hitsPerPage is " + hitsPerPage);
int maxHitSize = defaultMaxSearchSize;
if( startIndex >= defaultMaxSearchSize - hitsPerPage )
maxHitSize = startIndex + defaultMaxSearchSize;
if( alphaFilter != null ){
maxHitSize = maxHitSize * 2;
hitsPerPage = maxHitSize;
}
log.debug("maxHitSize is " + maxHitSize);
String qtxt = vreq.getParameter(VitroQuery.QUERY_PARAMETER_NAME);
Analyzer analyzer = getAnalyzer(getServletContext());
Query query = null;
try {
query = getQuery(vreq, portalFlag, analyzer, qtxt);
} catch (ParseException e) {
log.warn("Query parse exception: " + e);
doBadQuery(qtxt, request, response);
return;
}
log.debug("query for '" + qtxt +"' is " + query.toString());
IndexSearcher searcherForRequest = LuceneIndexFactory.getIndexSearcher(getServletContext());
TopDocs topDocs = null;
try{
topDocs = searcherForRequest.search(query,null,maxHitSize);
}catch(Throwable t){
log.error("in first pass at search: " + t);
// this is a hack to deal with odd cases where search and index threads interact
try{
wait(150);
topDocs = searcherForRequest.search(query,null,maxHitSize);
}catch (Exception ex){
log.error(ex);
String msg = makeBadSearchMessage(qtxt,ex.getMessage());
if(msg == null ) msg = "<p>The search request contained errors.</p>";
doFailedSearch(request, response, msg, qtxt);
return;
}
}
if( topDocs == null || topDocs.scoreDocs == null){
log.error("topDocs for a search was null");
String msg = "<p>The search request contained errors.</p>";
doFailedSearch(request, response, msg, qtxt);
return;
}
int hitsLength = topDocs.scoreDocs.length;
if ( hitsLength < 1 ){
doFailedSearch(request, response, NORESULT_MSG, qtxt);
return;
}
log.debug("found "+hitsLength+" hits");
int lastHitToShow = 0;
if((startIndex + hitsPerPage) > hitsLength )
lastHitToShow = hitsLength;
else
lastHitToShow = startIndex + hitsPerPage - 1;
List<Individual> beans = new LinkedList<Individual>();
for(int i=startIndex; i<topDocs.scoreDocs.length ;i++){
try{
if( (i >= startIndex) && (i <= lastHitToShow) ){
Document doc = searcherForRequest.doc(topDocs.scoreDocs[i].doc);
String uri = doc.get(Entity2LuceneDoc.term.URI);
Individual ent = iDao.getIndividualByURI(uri);
if(ent != null ){
List<VClass>vcs = ent.getVClasses() ;
if( vcs != null && !vcs.isEmpty() ){
beans.add(ent);
log.debug("found individual for search hit in model" + uri );
}else{
log.debug("filtered out classless individual from search results" + uri);
}
}else{
log.debug("could not find individual for search hit in model " + uri);
}
}
}catch(Exception e){
log.error("problem getting usable Individuals from search " +
"hits" + e.getMessage());
}
}
//search request for no classgroup and no type so add classgroup search refinement links.
if( request.getParameter("classgroup") == null && request.getParameter("type") == null){
request.setAttribute("classgroups",
getClassGroups(grpDao, topDocs, searcherForRequest));
request.setAttribute("refinment", "");
}else{
//search request for a classgroup so add rdf:type search refinement links
//but try to filter out classes that are subclasses
if( request.getParameter("classgroup") != null && request.getParameter("type") == null ){
request.setAttribute("types",
getVClasses(vclassDao,topDocs,searcherForRequest));
request.setAttribute("refinment", "&classgroup="
+ URLEncoder.encode(request.getParameter("classgroup"),"UTF-8"));
}else{
if( alphaFilter != null && !"".equals(alphaFilter)){
request.setAttribute("alphas", getAlphas(topDocs, searcherForRequest));
alphaSortIndividuals(beans);
}else{
request.setAttribute("refinment", "&type="
+ URLEncoder.encode(request.getParameter("type"),"UTF-8"));
}
}
}
//stick the results in the requestScope and prepare to forward to JSP
request.setAttribute("beans", beans);
request.setAttribute("title", qtxt+" - "+portal.getAppName()+" Search Results" );
request.setAttribute("bodyJsp", Controllers.SEARCH_PAGED_JSP);
request.setAttribute("querytext", qtxt);
request.setAttribute("startIndex", startIndex);
request.setAttribute("hitsPerPage", hitsPerPage);
request.setAttribute("hitsLength", hitsLength);
request.setAttribute("maxHitSize", maxHitSize);
String param = request.getParameter("classgroup");
if(param != null && !"".equals(param)){
VClassGroup grp = grpDao.getGroupByURI(param);
if( grp != null && grp.getPublicName() != null )
request.setAttribute("classgroupName", grp.getPublicName());
}
param = request.getParameter("type");
if(param != null && !"".equals(param)){
VClass type = vclassDao.getVClassByURI(param);
if( type != null && type.getName() != null )
request.setAttribute("typeName", type.getName());
}
// VitroQueryWrapper queryWrapper =
// new VitroQueryWrapper(query,
// (VitroHighlighter)searcher.getHighlighter(query),
// 2, time);
// request.getSession(true).setAttribute("LastQuery", queryWrapper);
// log.debug("query wrapper created");
request.getRequestDispatcher(Controllers.BASIC_JSP).forward(request,response);
} catch (Throwable e) {
log.error("PagedSearchController.doGet(): " + e, e);
doSearchError(request, response, e.getMessage(), null);
return;
}
}
private void alphaSortIndividuals(List<Individual> beans) {
Collections.sort(beans, new Comparator< Individual >(){
public int compare(Individual o1, Individual o2) {
if( o1 == null || o1.getName() == null )
return 1;
else
return o1.getName().compareTo(o2.getName());
}});
}
private List<String> getAlphas(TopDocs topDocs, IndexSearcher searcher) {
Set<String> alphas = new HashSet<String>();
for(int i=0;i<topDocs.scoreDocs.length; i++){
Document doc;
try {
doc = searcher.doc(topDocs.scoreDocs[i].doc);
String name =doc.get(Entity2LuceneDoc.term.NAME);
if( name != null && name.length() > 0)
alphas.add( name.substring(0, 1));
} catch (CorruptIndexException e) {
log.debug("Could not get alphas for document",e);
} catch (IOException e) {
log.debug("Could not get alphas for document",e);
}
}
return new ArrayList<String>(alphas);
}
/**
* Get the class groups represented for the individuals in the topDocs.
*/
private List<VClassGroup> getClassGroups(VClassGroupDao grpDao, TopDocs topDocs,
IndexSearcher searcherForRequest) {
LinkedHashMap<String,VClassGroup> grpMap = grpDao.getClassGroupMap();
int n = grpMap.size();
HashSet<String> classGroupsInHits = new HashSet<String>(n);
int grpsFound = 0;
for(int i=0; i<topDocs.scoreDocs.length && n > grpsFound ;i++){
try{
Document doc = searcherForRequest.doc(topDocs.scoreDocs[i].doc);
Field[] grps = doc.getFields(Entity2LuceneDoc.term.CLASSGROUP_URI);
if(grps != null || grps.length > 0){
for(int j=0;j<grps.length;j++){
String groupUri = grps[j].stringValue();
if( groupUri != null && ! classGroupsInHits.contains(groupUri)){
classGroupsInHits.add(groupUri);
grpsFound++;
if( grpsFound >= n )
break;
}
}
}
}catch(Exception e){
log.error("problem getting VClassGroups from search hits "
+ e.getMessage());
}
}
List<String> classgroupURIs= Collections.list(Collections.enumeration(classGroupsInHits));
List<VClassGroup> classgroups = new ArrayList<VClassGroup>( classgroupURIs.size() );
for(String cgUri: classgroupURIs){
if( cgUri != null && ! "".equals(cgUri) ){
VClassGroup vcg = grpDao.getGroupByURI( cgUri );
if( vcg == null ){
log.debug("could not get classgroup for URI " + cgUri);
}else{
classgroups.add(vcg);
}
}
}
grpDao.sortGroupList(classgroups);
return classgroups;
}
private List<VClass> getVClasses(VClassDao vclassDao, TopDocs topDocs,
IndexSearcher searherForRequest){
HashSet<String> typesInHits = getVClassUrisForHits(topDocs,searherForRequest);
List<VClass> classes = new ArrayList<VClass>(typesInHits.size());
Iterator<String> it = typesInHits.iterator();
while(it.hasNext()){
String typeUri = it.next();
try{
if( VitroVocabulary.OWL_THING.equals(typeUri))
continue;
VClass type = vclassDao.getVClassByURI(typeUri);
if( ! type.isAnonymous() &&
type.getName() != null && !"".equals(type.getName()) &&
type.getGroupURI() != null ) //don't display classes that aren't in classgroups
classes.add(type);
}catch(Exception ex){
if( log.isDebugEnabled() )
log.debug("could not add type " + typeUri, ex);
}
}
Collections.sort(classes, new Comparator<VClass>(){
public int compare(VClass o1, VClass o2) {
return o1.compareTo(o2);
}});
return classes;
}
private HashSet<String> getVClassUrisForHits(TopDocs topDocs,
IndexSearcher searcherForRequest){
HashSet<String> typesInHits = new HashSet<String>();
for(int i=0; i<topDocs.scoreDocs.length; i++){
try{
Document doc=searcherForRequest.doc(topDocs.scoreDocs[i].doc);
Field[] types = doc.getFields(Entity2LuceneDoc.term.RDFTYPE);
if(types != null ){
for(int j=0;j<types.length;j++){
String typeUri = types[j].stringValue();
typesInHits.add(typeUri);
}
}
}catch(Exception e){
log.error("problems getting rdf:type for search hits",e);
}
}
return typesInHits;
}
private Analyzer getAnalyzer(ServletContext servletContext) throws SearchException {
Object obj = servletContext.getAttribute(LuceneSetup.ANALYZER);
if( obj == null || !(obj instanceof Analyzer) )
throw new SearchException("Could not get anlyzer");
else
return (Analyzer)obj;
}
private Query getQuery(VitroRequest request, PortalFlag portalState,
Analyzer analyzer, String querystr ) throws SearchException, ParseException {
Query query = null;
try{
//String querystr = request.getParameter(VitroQuery.QUERY_PARAMETER_NAME);
if( querystr == null){
log.error("There was no Parameter '"+VitroQuery.QUERY_PARAMETER_NAME
+"' in the request.");
return null;
}else if( querystr.length() > MAX_QUERY_LENGTH ){
log.debug("The search was too long. The maximum " +
"query length is " + MAX_QUERY_LENGTH );
return null;
}
QueryParser parser = getQueryParser(analyzer);
query = parser.parse(querystr);
String alpha = request.getParameter("alpha");
if( alpha != null && !"".equals(alpha) && alpha.length() == 1){
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add( query, BooleanClause.Occur.MUST );
boolQuery.add(
new WildcardQuery(new Term(Entity2LuceneDoc.term.NAME, alpha+'*')),
BooleanClause.Occur.MUST);
query = boolQuery;
}
//check if this is classgroup filtered
Object param = request.getParameter("classgroup");
if( param != null && !"".equals(param)){
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add( query, BooleanClause.Occur.MUST);
boolQuery.add( new TermQuery(
new Term(Entity2LuceneDoc.term.CLASSGROUP_URI,
(String)param)),
BooleanClause.Occur.MUST);
query = boolQuery;
}
//check if this is rdf:type filtered
param = request.getParameter("type");
if( param != null && !"".equals(param)){
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add( query, BooleanClause.Occur.MUST);
boolQuery.add( new TermQuery(
new Term(Entity2LuceneDoc.term.RDFTYPE,
(String)param)),
BooleanClause.Occur.MUST);
query = boolQuery;
}
//if we have a flag/portal query then we add
//it by making a BooelanQuery.
Query flagQuery = makeFlagQuery( portalState );
if( flagQuery != null ){
BooleanQuery boolQuery = new BooleanQuery();
boolQuery.add( query, BooleanClause.Occur.MUST);
boolQuery.add( flagQuery, BooleanClause.Occur.MUST);
query = boolQuery;
}
log.debug("Query: " + query);
} catch (ParseException e) {
throw new ParseException(e.getMessage());
} catch (Exception ex){
throw new SearchException(ex.getMessage());
}
return query;
}
@SuppressWarnings("static-access")
private QueryParser getQueryParser(Analyzer analyzer){
//defaultSearchField indicates which field search against when there is no term
//indicated in the query string.
//The analyzer is needed so that we use the same analyzer on the search queries as
//was used on the text that was indexed.
QueryParser qp = new QueryParser(defaultSearchField,analyzer);
//this sets the query parser to AND all of the query terms it finds.
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
//set up the map of stemmed field names -> unstemmed field names
// HashMap<String,String> map = new HashMap<String, String>();
// map.put(Entity2LuceneDoc.term.ALLTEXT,Entity2LuceneDoc.term.ALLTEXTUNSTEMMED);
// qp.setStemmedToUnstemmed(map);
return qp;
}
/**
* Makes a flag based query clause. This is where searches can filtered
* by portal.
*
* If you think that search is not working correctly with protals and
* all that kruft then this is a method you want to look at.
*
* It only takes into account "the portal flag" and flag1Exclusive must
* be set. Where does that stuff get set? Look in vitro.flags.PortalFlag
*
* One thing to keep in mind with portal filtering and search is that if
* you want to search a portal that is different then the portal the user
* is 'in' then the home parameter should be set to force the user into
* the new portal.
*
* Ex. Bob requests the search page for vivo in portal 3. You want to
* have a drop down menu so bob can search the all CALS protal, id 60.
* You need to have a home=60 on your search form. If you don't set
* home=60 with your search query, then the search will not be in the
* all portal AND the WebappDaoFactory will be filtered to only show
* things in portal 3.
*
* Notice: flag1 as a parameter is ignored. bdc34 2009-05-22.
*/
@SuppressWarnings("static-access")
private Query makeFlagQuery( PortalFlag flag){
if( flag == null || !flag.isFilteringActive()
|| flag.getFlag1DisplayStatus() == flag.SHOW_ALL_PORTALS )
return null;
// make one term for each bit in the numeric flag that is set
Collection<TermQuery> terms = new LinkedList<TermQuery>();
int portalNumericId = flag.getFlag1Numeric();
Long[] bits = FlagMathUtils.numeric2numerics(portalNumericId);
for (Long bit : bits) {
terms.add(new TermQuery(new Term(Entity2LuceneDoc.term.PORTAL, Long
.toString(bit))));
}
// make a boolean OR query for all of those terms
BooleanQuery boolQuery = new BooleanQuery();
if (terms.size() > 0) {
for (TermQuery term : terms) {
boolQuery.add(term, BooleanClause.Occur.SHOULD);
}
return boolQuery;
} else {
//we have no flags set, so no flag filtering
return null;
}
}
private void doBadQuery(String queryStr, HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
request.setAttribute("title", "Search "+portal.getAppName());
request.setAttribute("bodyJsp", Controllers.SEARCH_BAD_QUERY_JSP);
request.setAttribute("queryStr", queryStr);
RequestDispatcher rd = request
.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
private void doFailedSearch(HttpServletRequest request,
HttpServletResponse response, String message, String querytext)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
if( querytext != null ){
request.setAttribute("querytext", querytext);
request.setAttribute("title", querytext+" - "+portal.getAppName()+" Search" );
}else{
request.setAttribute("title", portal.getAppName()+" Search" );
request.setAttribute("querytext", "");
}
if( message != null && message.length() > 0)
request.setAttribute("message", message);
request.setAttribute("bodyJsp", Controllers.SEARCH_FAILED_JSP);
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
/**
* Makes a message to display to user for a bad search term.
* @param query
* @param exceptionMsg
*/
private String makeBadSearchMessage(String querytext, String exceptionMsg){
String rv = "";
try{
//try to get the column in the search term that is causing the problems
int coli = exceptionMsg.indexOf("column");
if( coli == -1) return "";
int numi = exceptionMsg.indexOf(".", coli+7);
if( numi == -1 ) return "";
String part = exceptionMsg.substring(coli+7,numi );
int i = Integer.parseInt(part) - 1;
// figure out where to cut preview and post-view
int errorWindow = 5;
int pre = i - errorWindow;
if (pre < 0)
pre = 0;
int post = i + errorWindow;
if (post > querytext.length())
post = querytext.length();
// log.warn("pre: " + pre + " post: " + post + " term len:
// " + term.length());
// get part of the search term before the error and after
String before = querytext.substring(pre, i);
String after = "";
if (post > i)
after = querytext.substring(i + 1, post);
rv = "The search term had an error near <span class='searchQuote'>"
+ before + "<span class='searchError'>" + querytext.charAt(i)
+ "</span>" + after + "</span>";
} catch (Throwable ex) {
return "";
}
return rv;
}
@SuppressWarnings("unchecked")
private HashSet<String> getDataPropertyBlacklist(){
HashSet<String>dpBlacklist = (HashSet<String>)
getServletContext().getAttribute(LuceneSetup.SEARCH_DATAPROPERTY_BLACKLIST);
return dpBlacklist;
}
@SuppressWarnings("unchecked")
private HashSet<String> getObjectPropertyBlacklist(){
HashSet<String>opBlacklist = (HashSet<String>)
getServletContext().getAttribute(LuceneSetup.SEARCH_OBJECTPROPERTY_BLACKLIST);
return opBlacklist;
}
private void doSearchError(HttpServletRequest request,
HttpServletResponse response, String message, Object object)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
request.setAttribute("bodyJsp", Controllers.SEARCH_ERROR_JSP);
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
private final String defaultSearchField = "ALLTEXT";
public static final int MAX_QUERY_LENGTH = 500;
}

View file

@ -1,648 +0,0 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
package edu.cornell.mannlib.vitro.webapp.search.controller;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import edu.cornell.mannlib.vitro.webapp.beans.Individual;
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
import edu.cornell.mannlib.vitro.webapp.beans.Tab;
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
import edu.cornell.mannlib.vitro.webapp.beans.VClassList;
import edu.cornell.mannlib.vitro.webapp.controller.Controllers;
import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet;
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
import edu.cornell.mannlib.vitro.webapp.flags.PortalFlag;
import edu.cornell.mannlib.vitro.webapp.search.SearchException;
import edu.cornell.mannlib.vitro.webapp.search.beans.Searcher;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroHighlighter;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQuery;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQueryFactory;
import edu.cornell.mannlib.vitro.webapp.search.beans.VitroQueryWrapper;
/**
* This controller will execute the search and process
* the search resutls into entites. Those entites will be stuffed
* into the request scope and the controll will be passed to a
* jsp for rendering html.
*
* -- What are the parameters that this servlet uses?
* This servlet uses the PortalFlag to represent which portal and how
* the portals will be accounted for in the search. So you should look
* at edu.cornell.mannlib.vitro.flags.PortalFlag to find out what http parameters
* cause it to be set to what states.
*
* Here is a quick run down of the interesting ones:
* filter - if set to 'false' no flag filtering will happen
* flag1 - if set to 'nofiltering' no flag filtering will happen
* querytext - query text to use for search.
*
* This controller will 1) use VitroServlet to process the httpRequest
* for parameters 2) build a query and execute it on the
* index 3) take the results of the query, which are just entity ids,
* and turn them into short entities 4) highlight the entities.
* 5) sort into ClassGroups 6) stick into the request scope.
*
*
* This controller will do the searing for any kind of search
* back end. There are two things that make this possible: 1
* interfaces, 2 stashing a pointer to the instance of the search
* that we intend to use.
*
* 1) an interface is a definition of method signatures with no
* code. This is similar to a c header file. It allows us to define
* a set of methods we can call without having to know what will
* happen for us to get the outputs of those methods.
*
* 2) Once we have this we need a way to get an instantiated object
* that implements the interface we are interested in using. There
* are different ways of doing this. We will just get an object out
* of the application scope. This object was set when the context
* started up and can be set in the web.xml. See LuceneSetup.java
* for an example.
*
* @deprecated Use PagedSearchController instead.
*/
public class SearchController extends VitroHttpServlet{
private static final Log log = LogFactory.getLog(SearchController.class.getName());
String NORESULT_MSG = "The search returned no results.";
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
/**
*
*
* @author bdc34
*/
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
try {
//this will set up the portal flag, which is where the search query
//will get ALL of the information about portal filtering.
super.doGet(request,response);
VitroRequest vreq = new VitroRequest(request);
Portal portal = vreq.getPortal();
PortalFlag portalFlag = vreq.getPortalFlag();
// ////////////////////////////////////////////////////////////////////
// FIRST: we want to get the search object
// All that we know about it is that it implements the Searcher
// interface.
ServletContext context = getServletContext();
Searcher searcher = (Searcher) context.getAttribute(Searcher.class.getName());
// ///////////////////////////////////////////////////////////////////
// NEXT: we make a query. The searcher object has a method that
// makes a
// query for us. This allows the search object to implement specific
// transformations from the request to the query.
// Possible improvement: make some kind of standard queryRequest
// object that all QueryFactory objs take.
VitroQueryFactory qFactory = searcher.getQueryFactory();
VitroQuery query = qFactory.getQuery(vreq, portalFlag);
// qFactory.getQuery() will return null when there is not enough
// information in the request to make a query.
if (query == null ) {
doNoQuery(request, response);
return;
}
// ////////////////////////////////////////////////////////////////////
// Now we want to do the search
long start = System.currentTimeMillis();
List hits = null;
try{
hits = searcher.search(query);
}catch(Throwable t){
log.error("in first pass at search: " + t);
// this is a hack to deal with odd cases where search and index threads interact
try{
Thread.currentThread().sleep(150);
hits = searcher.search(query);
}catch (SearchException ex){
log.error(ex);
String msg = makeBadSearchMessage(query,ex.getMessage());
if(msg == null ) msg = "<p>The search request contained errors.</p>";
doFailedSearch(request, response, msg, query);
return;
}
}
long end = System.currentTimeMillis();
long time=end-start;
if (hits == null || hits.size() < 1) {
doFailedSearch(request, response, NORESULT_MSG, query);
return;
}
log.debug("found "+hits+" hits");
// now we have hits which are only entity ids
// so convert the hits to usable entity beans
List beans = makeUsableBeans(hits,vreq);
log.debug("makeUsableBeans() succeeded");
//sort by ClassGroup and the sort the ClassGroups
Map collatedListOfLists = null;
if (beans != null && beans.size() > 0) { // collate entities
collatedListOfLists = collate(beans,vreq); // sort each classgroup
// list by a default
// setting if available
// sort each class group
collatedListOfLists = sortClassGroups(collatedListOfLists);
}
log.debug("sort by classgroups succeeded");
VClassGroup.removeEmptyClassGroups(collatedListOfLists);
log.debug("empty classgroups removed");
collateClassGroupsByVClass(collatedListOfLists.values());
log.debug("classgroups collated");
//Now collatedLitOfLists has Map of VCLassGroups
//and each VClassGroup has a list of VCLassList, each with a list of entities.
//attempt to do highlighting
try {
beans = highlightBeans( beans , searcher.getHighlighter(query) );
} catch (Exception e) {
log.error("Error highlighting search result beans", e);
}
log.debug("beans highlighted");
// ////////////////////////////////////////////////////////////////////
// stick the data in the requestScope and sessionScope
// stick the results in the requestScope:
request.setAttribute("collatedResultsLists", collatedListOfLists);
request.setAttribute("collatedGroupNames", collatedListOfLists
.keySet());
String terms = query.getTerms();
request.setAttribute("title", terms+" - "+portal.getAppName()+" Search Results" );
request.setAttribute("bodyJsp", Controllers.SEARCH_BASIC_JSP);
request.setAttribute("css", Controllers.TOGGLE_SCRIPT_ELEMENT);
request.setAttribute("querytext", terms);
VitroQueryWrapper queryWrapper =
new VitroQueryWrapper(query,
(VitroHighlighter)searcher.getHighlighter(query),
2, time);
request.getSession(true).setAttribute("LastQuery", queryWrapper);
log.debug("query wrapper created");
// ////////////////////////////////////////////////////////////////////
// FINALLY: send off to the BASIC_JSP to get turned into html
RequestDispatcher rd = request
.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
} catch (Throwable e) {
log.error("SearchController.doGet(): " + e);
doSearchError(request, response, e.getMessage(), null);
return;
}
}
private void doSearchError(HttpServletRequest request,
HttpServletResponse response, String message, Object object)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
request.setAttribute("bodyJsp", Controllers.SEARCH_ERROR_JSP);
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
private List highlightBeans(List beans, VitroHighlighter highlighter) {
Iterator it = beans.iterator();
while(it.hasNext()){
Object obj = it.next();
if( obj instanceof Individual){
Individual ent = (Individual)obj;
highlighter.fragmentHighlight(ent);
}
}
return beans;
}
private void doNoQuery(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
request.setAttribute("title", "Search "+portal.getAppName());
request.setAttribute("bodyJsp", Controllers.SEARCH_FORM_JSP);
RequestDispatcher rd = request
.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
private void doFailedSearch(HttpServletRequest request,
HttpServletResponse response, String message, VitroQuery query)
throws ServletException, IOException {
Portal portal = (new VitroRequest(request)).getPortal();
if( query != null ){
String terms = query.getTerms();
request.setAttribute("querytext", terms);
request.setAttribute("title", terms+" - "+portal.getAppName()+" Search" );
}else{
request.setAttribute("title", portal.getAppName()+" Search" );
request.setAttribute("querytext", "");
}
if( message != null && message.length() > 0)
request.setAttribute("message", message);
request.setAttribute("bodyJsp", Controllers.SEARCH_FAILED_JSP);
RequestDispatcher rd = request.getRequestDispatcher(Controllers.BASIC_JSP);
rd.forward(request, response);
}
/**
* Makes a message to display to user for a bad search term.
* @param query
* @param exceptionMsg
*/
private String makeBadSearchMessage(VitroQuery query, String exceptionMsg){
String term = query.getTerms();
String rv = "";
try{
//try to get the column in the search term that is causing the problems
int coli = exceptionMsg.indexOf("column");
if( coli == -1) return "";
int numi = exceptionMsg.indexOf(".", coli+7);
if( numi == -1 ) return "";
String part = exceptionMsg.substring(coli+7,numi );
int i = Integer.parseInt(part) - 1;
// figure out where to cut preview and post-view
int errorWindow = 5;
int pre = i - errorWindow;
if (pre < 0)
pre = 0;
int post = i + errorWindow;
if (post > term.length())
post = term.length();
// log.warn("pre: " + pre + " post: " + post + " term len:
// " + term.length());
// get part of the search term before the error and after
String before = term.substring(pre, i);
String after = "";
if (post > i)
after = term.substring(i + 1, post);
rv = "The search term had an error near <span class='searchQuote'>"
+ before + "<span class='searchError'>" + term.charAt(i)
+ "</span>" + after + "</span>";
} catch (Throwable ex) {
return "";
}
return rv;
}
/**
* Upgrades beans using individual entity upgrade().
*
* @param hits
* @return
*/
@SuppressWarnings("unchecked")
private List makeUsableBeans(List hits,VitroRequest vreq) {
if (hits == null || hits.size() == 0) {
return new ArrayList();
}
LinkedList beans = new LinkedList();
Iterator it = hits.iterator();
while (it.hasNext()) {
try {
Object obj = it.next();
if (obj != null) {
obj = vreq.getWebappDaoFactory().getIndividualDao().getIndividualByURI(((Individual)obj).getURI());
//null would indicate that the entity that was found in
//the search index is no longer in the system.
if( obj != null ) {
beans.add(obj);
}
}
} catch (Exception e) {
log.error(e.getStackTrace());
}
}
return beans;
}
public static final String NO_GRP_FOUND = "others";
public static final String TABS = "tabs";
/**
* Make a map of VClassGroup objs to Lists of entites. There will also be a
* map from TABS -> a List of tabs and NO_CLASSGRP_FOUND -> a list of
* Entities where the class or classgroup could not be found.
*
* @param beans
* @return
*/
private Map /* of List */collate(List beans, VitroRequest vreq) {
if (beans == null || beans.size() == 0) {
return new HashMap();
}
/* make a hash map of VClassGroup -> List[ ent, ent , ent ... ] */
Map groups = vreq.getWebappDaoFactory().getVClassGroupDao().getClassGroupMap();
Map groupsByURI = makeGroupURIBasedMap(groups);
VClass vclass = null;
VClassGroup tabs = null, other = null;
Iterator it = beans.iterator();
while (it.hasNext()) {
Object obj = it.next();
if (obj instanceof Individual){
vclass = (VClass)((Individual) obj).getVClass();
if( vclass != null && vclass.getGroupURI() != null ){
putInGroupsList(groupsByURI, vclass.getGroupURI(), obj);
} else { /* didn't find a group */
if( !groupsByURI.containsKey("vitro://NullClassGroup") ){
other = new VClassGroup("vitro://NullClassGroup",NO_GRP_FOUND);
groupsByURI.put("vitro://NullClassGroup", other);
groups.put(NO_GRP_FOUND,other);
}
putInGroupsList(groupsByURI, "vitro://NullClassGroup", obj);
}
} else if (obj instanceof Tab) {
if( !groupsByURI.containsKey("vitro://NullTabGroup") ){
tabs = new VClassGroup("vitro://NullTabGroup",TABS);
groupsByURI.put(0, tabs );
groups.put(TABS,tabs);
}
putInGroupsList(groupsByURI, null, obj);
}
}
return groups;
}
private void putInGroupsList(Map groupsById, String key, Object obj) {
List classList = (List) groupsById.get(key);
if (classList == null) {/* make new list if this is a new grp */
classList = new LinkedList();
groupsById.put(key, classList);
}
classList.add(obj);
}
/**
* Make a new map from the Integer() -> VClassGroup.
* @param groups
* @return
*/
private Map makeGroupURIBasedMap( Map groups){
LinkedHashMap <String,VClassGroup> map=
new LinkedHashMap<String, VClassGroup>();
for( Object obj: groups.values() ){
if( !(obj instanceof VClassGroup) )
throw new Error("VitroRequest.getWebappDaoFactory().getVClassGroupDao().getClassGroupMap() returned something other than a VClassGroup");
VClassGroup grp = (VClassGroup)obj;
map.put(grp.getURI() , grp );
}
return map;
}
/**
* Collate a Collection of Entities into VClassLists.
* Sort the vclasses.
*
* @param ents
* @return
*/
@SuppressWarnings({ "unused", "unchecked" })
private LinkedList /*VClassList*/ collateVClasses(Collection ents){
log.debug("in collateVClasses ");
if( ents == null ) return null;
Map <String, VClassList> vclasses = new HashMap<String, VClassList>( );
Iterator it = ents.iterator();
while( it.hasNext()){
Individual ent = (Individual) it.next();
if(vclasses.containsKey(ent.getVClassURI()+"")){
vclasses.get(ent.getVClassURI()+"").getEntities().add(ent);
}else{
List <Individual> a = new LinkedList<Individual>();
a.add(ent);
VClass waVClass = (VClass)ent.getVClass();
VClassList vcl = null;
if (waVClass==null) {
VClass vcw = new VClass();
vcw.setURI("vitro://UnknownClass");
vcw.setName("Unknown Class");
vcl = new VClassList(vcw,a);
} else {
vcl = new VClassList(waVClass,a);
}
vclasses.put(ent.getVClassURI()+"", vcl);
}
}
LinkedList vclassList = new LinkedList(vclasses.values());
if( log.isDebugEnabled() ){
it = vclassList.iterator();
while(it.hasNext()){
log.debug(((VClass)it.next()).getName());
}
}
//This is the object that will compare vclasses for
//sort order in the search results
Comparator vclassComparator = new Comparator<Object>(){
public int compare(Object o1, Object o2) {
if( o1 == null && o2 == null) return 0;
if( o1 == null ) return 1;
if( o2 == null ) return -1;
if( o1 instanceof VClass && o2 instanceof VClass)
return compare((VClass) o1, (VClass) o2);
//what to do when we don't know what we have:
return o2.hashCode() - o1.hashCode();
}
private int compare(VClass v1, VClass v2){
if( v1== null && v2 == null ) return 0;
if( v1 == null ) return -1;
if( v2 == null ) return 1;
if( v1.getURI().equals(v2.getURI()) )return 0;
//check if display ranks are different
int v1rank=v1.getDisplayRank();
int v2rank=v2.getDisplayRank();
if( v1rank == v2rank )
//same rank, sort by vclass name
return v1.getName().compareToIgnoreCase( v2.getName());
//bdc34: this is not working as I expect it to
// This is what I think:
// comparators should return 0 same; -1 2nd object is first;
// +1 1st object should be first
//
// vclass rank should work such that display Rank 1 get to go first,
// 99 gets to go last. All vclasses with the same rank should get
// alpha sorting.
//
// So I would guess that returning +1 when v1.disRank < v2.disRank
// would make sense but that seems to be worng.
//
// I tried the other way and things seem to work correctly.
// I might just be confused about the values that Comparator
// object should return
if( v1rank > v2rank )
return 1;
else
return -1;
}
};
Collections.sort(vclassList,vclassComparator);
if( log.isDebugEnabled()){
it = vclassList.iterator();
while(it.hasNext()){
log.debug(((VClass)it.next()).getName());
}
}
return vclassList;
}
private void collateClassGroupsByVClass( Collection cGrps ){
if( cGrps == null ) return;
Iterator it = cGrps.iterator();
while(it.hasNext()){
VClassGroup grp = (VClassGroup) it.next();
List vclassLists = collateVClasses( grp );
grp.clear();
grp.addAll(vclassLists);
}
}
/**
* Try to sort the classGroup lists. For each item in the map, check if it
* is a collection, if yes, try to sort as if things in the list are Entity
* objects.
*
* @return
*/
private Map /* of List */sortClassGroups(Map classGroups) {
if( classGroups == null || classGroups.values() == null )
return classGroups;
//first we sort the entities in each grouup.
Iterator it = classGroups.values().iterator();
//wow, I have to sit down and learn this generic stuff.
Comparator entComparator = new Comparator<Object>(){
public int compare(Object o1, Object o2) {
if( o1 == null && o2 == null) return 0;
if( o1 == null ) return 1;
if( o2 == null ) return -1;
if( o1 instanceof VClass && o2 instanceof VClass)
return compareClasses(((VClass) o1), ((VClass) o2));
if( o1 instanceof Individual && o2 instanceof Individual)
return compareEnts((Individual)o1, (Individual)o2);
if( o1 instanceof Individual && ! (o2 instanceof Individual))
return -1;
if( !(o1 instanceof Individual) && o2 instanceof Individual)
return 1;
//what to do when we don't know what we have:
return o2.hashCode() - o1.hashCode();
}
//here we sort entities
private int compareEnts(Individual o1, Individual o2){
int vclassCompare = compareClasses((VClass) o1.getVClass(),
(VClass) o2.getVClass() );
//sort by vclass first, then by entity name
if( vclassCompare != 0 )
return vclassCompare;
else
return ((o1.getName()==null)?"":o1.getName()).compareToIgnoreCase((o2.getName()==null)?"": o2.getName());
}
private int compareClasses(VClass v1, VClass v2){
if( v1== null && v2 == null ) return 0;
if( v1 == null ) return -1;
if( v2 == null ) return 1;
if( v1.getURI().equals(v2.getURI()) )return 0;
//check if display ranks are different
int v1DisplayRank=v1.getDisplayRank(),
v2DisplayRank=v2.getDisplayRank();
int displayRankDiff = v2DisplayRank - v1DisplayRank;
if( displayRankDiff != 0 ) return displayRankDiff;
//same rank, sort by vclass name
return v1.getName().compareToIgnoreCase( v2.getName());
}
};
while(it.hasNext()){
Object obj = it.next();
if(!( obj instanceof Collection))
continue; //skip this one if it is not a collection
List <List<Object>>entList = (List<List<Object>>)obj;
Collections.sort(entList, entComparator);
}
// //now we sort the classgroups
// Comparator cgComparator = new Comparator<Object>(){
// public int compare(Object o1, Object o2){
// if( o1 == null && o2 == null) return 0;
// if( o1 == null ) return 1;
// if( o2 == null ) return -1;
//
// if( o1 instanceof ClassGroup && o2 instanceof ClassGroup)
// return compare((ClassGroup)o1, (ClassGroup)o2);
// if( o1 instanceof ClassGroup && ! (o2 instanceof ClassGroup))
// return -1;
// if( !(o1 instanceof ClassGroup) && o2 instanceof ClassGroup)
// return 1;
// //what to do when we don't know what we have:
// return o2.hashCode() - o1.hashCode();
// }
// private int compare(ClassGroup c1, ClassGroup c2){
// return 0;
// }
// };
return classGroups;
}
}