NIHVIVO-1554 Removed controllers and jsps that have been superceded by Freemarker controllers and templates
This commit is contained in:
parent
4db82c0585
commit
47b5e4ae52
38 changed files with 183 additions and 6101 deletions
|
@ -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
|
||||
*
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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.";
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
|
||||
|
|
|
@ -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{}
|
||||
}
|
|
@ -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()/* + " ("+vclass.getEntityCount()+")"*/);
|
||||
} else {
|
||||
request.setAttribute("title",classGroup.getPublicName());
|
||||
request.setAttribute("subTitle",vclass.getName()/* + " ("+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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}}
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue