Move FreeMarker templates, controllers, setup, and library upgrades into trunk. Not used to generate any pages or templates yet (except a couple of hidden pages that are only available through the url).
This commit is contained in:
parent
72ee86f0a7
commit
a0c93fda6d
44 changed files with 2256 additions and 7 deletions
|
@ -138,6 +138,12 @@
|
|||
</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>
|
||||
edu.cornell.mannlib.vitro.webapp.servlet.setup.FreeMarkerSetup
|
||||
</listener-class>
|
||||
</listener>
|
||||
|
||||
<!--
|
||||
<listener>
|
||||
<listener-class>
|
||||
|
@ -267,6 +273,15 @@
|
|||
<url-pattern>/about</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>AboutControllerFM</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.AboutControllerFM</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>AboutControllerFM</servlet-name>
|
||||
<url-pattern>/about-fm</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>FakeSelfEditController</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.FakeSelfEditController</servlet-class>
|
||||
|
@ -781,6 +796,15 @@
|
|||
<url-pattern>/entitylist</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>IndividualListControllerFM</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.IndividualListControllerFM</servlet-class>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>IndividualListControllerFM</servlet-name>
|
||||
<url-pattern>/individuallistFM</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>SearchController</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.search.controller.PagedSearchController</servlet-class>
|
||||
|
@ -948,6 +972,12 @@
|
|||
<load-on-startup>5</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>browsecontrollerFM</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.BrowseControllerFM</servlet-class>
|
||||
<load-on-startup>5</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>pubsbyorg</servlet-name>
|
||||
<servlet-class>edu.cornell.mannlib.vitro.webapp.controller.vclass.PubsByDepartmentServlet</servlet-class>
|
||||
|
@ -1064,6 +1094,10 @@
|
|||
<servlet-name>browsecontroller</servlet-name>
|
||||
<url-pattern>/browsecontroller</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>browsecontrollerFM</servlet-name>
|
||||
<url-pattern>/browse</url-pattern>
|
||||
</servlet-mapping>
|
||||
<servlet-mapping>
|
||||
<servlet-name>pubsbyorg</servlet-name>
|
||||
<url-pattern>/pubsbyorg</url-pattern>
|
||||
|
|
Binary file not shown.
Binary file not shown.
BIN
webapp/lib/commons-collections-3.2.1.jar
Normal file
BIN
webapp/lib/commons-collections-3.2.1.jar
Normal file
Binary file not shown.
Binary file not shown.
BIN
webapp/lib/commons-lang-2.4.jar
Normal file
BIN
webapp/lib/commons-lang-2.4.jar
Normal file
Binary file not shown.
BIN
webapp/lib/freemarker.jar
Normal file
BIN
webapp/lib/freemarker.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -45,7 +45,8 @@ public class VClass extends BaseResourceBean implements Comparable<VClass>
|
|||
// [bjl23 2007-08-12] Yep. A count of individuals in the class.
|
||||
private int myEntityCount = -1;
|
||||
|
||||
@Deprecated
|
||||
// rjy7 Removing deprecation since currently we have no other means to get this value.
|
||||
// @Deprecated
|
||||
public int getEntityCount() { return myEntityCount; }
|
||||
|
||||
public void setEntityCount( int ec ) { myEntityCount = ec; }
|
||||
|
@ -107,8 +108,8 @@ public class VClass extends BaseResourceBean implements Comparable<VClass>
|
|||
public VClass( String namespace, String localName, String vclassName )
|
||||
{
|
||||
myName = vclassName;
|
||||
namespace = namespace;
|
||||
localName = localName;
|
||||
this.namespace = namespace;
|
||||
this.localName = localName;
|
||||
URI = namespace + localName;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.controller;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
||||
|
||||
import freemarker.template.SimpleDate;
|
||||
import freemarker.template.TemplateDateModel;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
public class AboutControllerFM extends FreeMarkerHttpServlet {
|
||||
|
||||
private static final Log log = LogFactory.getLog(AboutControllerFM.class.getName());
|
||||
|
||||
protected String getTitle() {
|
||||
return "About " + portal.getAppName();
|
||||
}
|
||||
|
||||
protected String getBody() {
|
||||
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
|
||||
body.put("aboutText", portal.getAboutText());
|
||||
body.put("acknowledgeText", portal.getAcknowledgeText());
|
||||
|
||||
String templateName = "body/about.ftl";
|
||||
return mergeBodyToTemplate(templateName, body);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,322 @@
|
|||
/* $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.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 edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
||||
import edu.cornell.mannlib.vitro.webapp.view.VClassGroupView;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import freemarker.template.*;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class BrowseControllerFM extends FreeMarkerHttpServlet {
|
||||
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(BrowseControllerFM.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();
|
||||
}
|
||||
|
||||
protected String getTitle() {
|
||||
return "Index to " + portal.getAppName() + " Contents";
|
||||
}
|
||||
|
||||
protected String getBody() {
|
||||
|
||||
Map body = new HashMap();
|
||||
|
||||
// Set main page template attributes specific to this page
|
||||
root.put("contentClass", "siteMap");
|
||||
|
||||
if( vreq.getParameter("clearcache") != null ) //mainly for debugging
|
||||
clearGroupCache();
|
||||
|
||||
//PortalFlag portalState= vreq.getPortalFlag();
|
||||
|
||||
String message = "";
|
||||
List<VClassGroup> groups = getGroups(vreq.getWebappDaoFactory().getVClassGroupDao(), vreq.getPortal().getPortalId());
|
||||
|
||||
if (groups == null || groups.isEmpty()) {
|
||||
message = "There are not yet any items in the system.";
|
||||
body.put("message", message);
|
||||
}
|
||||
else {
|
||||
List<VClassGroupView> vcgroups = new ArrayList<VClassGroupView>();
|
||||
Iterator<VClassGroup> i = groups.iterator();
|
||||
VClassGroup group;
|
||||
VClassGroupView displayGroup;
|
||||
while (i.hasNext()) {
|
||||
group = (VClassGroup) i.next();
|
||||
displayGroup = new VClassGroupView(group);
|
||||
vcgroups.add(displayGroup);
|
||||
}
|
||||
body.put("classGroups", vcgroups);
|
||||
}
|
||||
|
||||
String templateName = "body/browseGroups.ftl";
|
||||
return mergeBodyToTemplate(templateName, body);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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 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 BrowseControllerFM controller = null;
|
||||
public BrowseControllerChangeListener(BrowseControllerFM 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 {
|
||||
BrowseControllerFM controller;
|
||||
boolean die = false;
|
||||
boolean queueChange = false;
|
||||
long queueChangeMills = 0;
|
||||
private boolean awareOfQueueChange = false;
|
||||
|
||||
RebuildGroupCacheThread(BrowseControllerFM controller) {
|
||||
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.";
|
||||
}
|
|
@ -67,6 +67,7 @@ public class Controllers {
|
|||
|
||||
public static final String ALPHA_INDEX_JSP = "/templates/alpha/alphaIndex.jsp";
|
||||
|
||||
public static final String SEARCH_URL = "/search";
|
||||
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";
|
||||
|
@ -87,6 +88,8 @@ public class Controllers {
|
|||
|
||||
public static final Object SEARCH_ERROR_JSP = "/search_error.jsp";
|
||||
|
||||
public static final String CONTACT_URL = "/comments";
|
||||
|
||||
//public static final String TAB_ENTITIES_LIST_JSP = "templates/tab/tabEntities.jsp";
|
||||
|
||||
private static List letters = null;
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/* $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.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
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 edu.cornell.mannlib.vedit.beans.LoginFormBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Portal;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
|
||||
import edu.cornell.mannlib.vitro.webapp.view.menu.TabMenu;
|
||||
import edu.cornell.mannlib.vitro.webapp.web.PortalWebUtil;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateModelException;
|
||||
|
||||
public class FreeMarkerHttpServlet extends VitroHttpServlet {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FreeMarkerHttpServlet.class.getName());
|
||||
private static final int FILTER_SECURITY_LEVEL = LoginFormBean.EDITOR;
|
||||
|
||||
public static Configuration config = null;
|
||||
public static String contextPath = null; // RY or do we need to store the entire ServletContext?
|
||||
|
||||
protected VitroRequest vreq;
|
||||
protected HttpServletResponse response;
|
||||
protected Portal portal;
|
||||
protected Map<String, Object> root = new HashMap<String, Object>();
|
||||
|
||||
// Some servlets have their own doGet() method, in which case they need to call
|
||||
// doSetup(), setTitle(), setBody(), and write() themselves. Other servlets define only
|
||||
// a getBody() and getTitle() method and use the parent doGet() method.
|
||||
public void doGet( HttpServletRequest request, HttpServletResponse response )
|
||||
throws IOException, ServletException {
|
||||
try {
|
||||
doSetup(request, response);
|
||||
setTitle();
|
||||
setBody();
|
||||
write(response);
|
||||
|
||||
} catch (Throwable e) {
|
||||
log.error("FreeMarkerHttpServlet 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);
|
||||
}
|
||||
|
||||
protected void setBody() {
|
||||
root.put("body", getBody());
|
||||
}
|
||||
|
||||
protected void setSharedVariable(String key, String value) {
|
||||
try {
|
||||
config.setSharedVariable(key, value);
|
||||
} catch (TemplateModelException e) {
|
||||
log.error("Can't set shared variable '" + key + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
protected void setTitle() {
|
||||
setSharedVariable("title", getTitle());
|
||||
}
|
||||
|
||||
protected String getTitle() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getBody() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected StringWriter mergeToTemplate(String templateName, Map<String, Object> map) {
|
||||
|
||||
Template template = null;
|
||||
try {
|
||||
template = config.getTemplate(templateName);
|
||||
} catch (IOException e) {
|
||||
log.error("Cannot get template " + templateName);
|
||||
}
|
||||
StringWriter sw = new StringWriter();
|
||||
if (template != null) {
|
||||
try {
|
||||
template.process(map, sw);
|
||||
} catch (TemplateException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
|
||||
protected String mergeBodyToTemplate(String templateName, Map<String, Object> map) {
|
||||
String body = mergeToTemplate(templateName, map).toString();
|
||||
extractLinkTagsFromBody(body);
|
||||
return body;
|
||||
}
|
||||
|
||||
// This is the only way to do this in FreeMarker. We cannot: (1) put a sequence of stylesheets in the template
|
||||
// context which the template can add to, because the template cannot call methods on the container. The template
|
||||
// can create a container but not add to one.
|
||||
// (2) create a sequence of stylesheets or a scalar to hold the name of a stylesheet in the template, because
|
||||
// it does not get passed back to the controller. The template can create only local variables.
|
||||
|
||||
// *** RY But we can create a view object with an add method, that the templates could use to add to the
|
||||
// list. ***
|
||||
private String extractLinkTagsFromBody(String body) {
|
||||
List<String> links = new ArrayList<String>();
|
||||
|
||||
String re = "<link[^>]*>";
|
||||
Pattern pattern = Pattern.compile(re);
|
||||
Matcher matcher = pattern.matcher(body);
|
||||
while (matcher.find()) {
|
||||
links.add(matcher.group());
|
||||
}
|
||||
|
||||
root.put("stylesheets", links); // SIDE-EFFECT
|
||||
|
||||
body = matcher.replaceAll("");
|
||||
return body;
|
||||
}
|
||||
|
||||
protected void write(HttpServletResponse response) {
|
||||
|
||||
String templateName = "page/default.ftl";
|
||||
StringWriter sw = mergeToTemplate(templateName, root);
|
||||
try {
|
||||
PrintWriter out = response.getWriter();
|
||||
out.print(sw);
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void doSetup(HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
try {
|
||||
super.doGet(request,response);
|
||||
} catch (ServletException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
} catch (IOException e1) {
|
||||
// TODO Auto-generated catch block
|
||||
e1.printStackTrace();
|
||||
}
|
||||
|
||||
vreq = new VitroRequest(request);
|
||||
this.response = response;
|
||||
portal = vreq.getPortal();
|
||||
|
||||
// RY Can this be removed? Do templates need it? Ideally, they should not.
|
||||
// Only needed for some weird stuff in search box that I think is only used in old default theme.
|
||||
int portalId = portal.getPortalId();
|
||||
try {
|
||||
config.setSharedVariable("portalId", portalId);
|
||||
} catch (TemplateModelException e) {
|
||||
log.error("Can't set shared variable 'portalId'.");
|
||||
}
|
||||
|
||||
TabMenu menu = getTabMenu(portalId);
|
||||
root.put("tabMenu", menu);
|
||||
|
||||
ApplicationBean appBean = vreq.getAppBean();
|
||||
PortalWebUtil.populateSearchOptions(portal, appBean, vreq.getWebappDaoFactory().getPortalDao());
|
||||
PortalWebUtil.populateNavigationChoices(portal, vreq, appBean, vreq.getWebappDaoFactory().getPortalDao());
|
||||
|
||||
// We'll need to separate theme-general and theme-specific stylesheet
|
||||
// dirs, so we need either two attributes or a list.
|
||||
String themeDir = portal.getThemeDir();
|
||||
String stylesheetDir = getUrl(themeDir + "css/");
|
||||
try {
|
||||
config.setSharedVariable("stylesheetDir", stylesheetDir);
|
||||
} catch (TemplateModelException e) {
|
||||
log.error("Can't set shared variable 'stylesheetDir'.");
|
||||
}
|
||||
|
||||
root.put("siteName", portal.getAppName());
|
||||
root.put("tagline", portal.getShortHand());
|
||||
|
||||
setUrls(portalId, themeDir);
|
||||
setLoginInfo();
|
||||
setCopyrightInfo();
|
||||
}
|
||||
|
||||
// Define the URLs that are accessible to the templates. Note that we do not create menus here,
|
||||
// because we want the templates to be free to define the link text and where the links are displayed.
|
||||
private final void setUrls(int portalId, String themeDir) {
|
||||
// The urls that are accessible to the templates.
|
||||
// NB We are not using our menu object mechanism to build menus here, because we want the
|
||||
// view to control which links go where, and the link text and title.
|
||||
Map<String, String> urls = new HashMap<String, String>();
|
||||
|
||||
String homeUrl = (portal.getRootBreadCrumbURL()!=null && portal.getRootBreadCrumbURL().length()>0) ?
|
||||
portal.getRootBreadCrumbURL() : vreq.getContextPath()+"/";
|
||||
urls.put("home", homeUrl);
|
||||
|
||||
String bannerImage = portal.getBannerImage();
|
||||
if ( ! StringUtils.isEmpty(bannerImage)) {
|
||||
root.put("bannerImage", getUrl(themeDir + "site_icons/" + bannerImage));
|
||||
}
|
||||
|
||||
urls.put("about", getUrl(Controllers.ABOUT + "?home=" + portalId));
|
||||
urls.put("aboutFM", getUrl(Controllers.ABOUT + "-fm?home=" + portalId)); // TEMPORARY
|
||||
if (ContactMailServlet.getSmtpHostFromProperties() != null) {
|
||||
urls.put("contact", getUrl(Controllers.CONTACT_URL + "?home=" + portalId));
|
||||
}
|
||||
urls.put("search", getUrl(Controllers.SEARCH_URL));
|
||||
urls.put("termsOfUse", getUrl("/termsOfUse?home=" + portalId));
|
||||
urls.put("login", getUrl(Controllers.LOGIN));
|
||||
urls.put("logout", getUrl(Controllers.LOGOUT));
|
||||
urls.put("siteAdmin", getUrl(Controllers.SITE_ADMIN));
|
||||
|
||||
root.put("urls", urls);
|
||||
}
|
||||
|
||||
private final void setLoginInfo() {
|
||||
|
||||
String loginName = null;
|
||||
int securityLevel;
|
||||
|
||||
HttpSession session = vreq.getSession();
|
||||
LoginFormBean loginBean = (LoginFormBean) session.getAttribute("loginHandler");
|
||||
if (loginBean != null && loginBean.testSessionLevel(vreq) > -1) {
|
||||
loginName = loginBean.getLoginName();
|
||||
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
||||
}
|
||||
if (loginName != null) {
|
||||
root.put("loginName", loginName);
|
||||
|
||||
securityLevel = Integer.parseInt(loginBean.getLoginRole());
|
||||
if (securityLevel >= FILTER_SECURITY_LEVEL) {
|
||||
ApplicationBean appBean = vreq.getAppBean();
|
||||
if (appBean.isFlag1Active()) {
|
||||
root.put("showFlag1SearchField", true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final void setCopyrightInfo() {
|
||||
|
||||
String copyrightText = portal.getCopyrightAnchor();
|
||||
if ( ! StringUtils.isEmpty(copyrightText) ) {
|
||||
Map<String, Object> copyright = new HashMap<String, Object>();
|
||||
copyright.put("text", copyrightText);
|
||||
int thisYear = Calendar.getInstance().get(Calendar.YEAR); // use ${copyrightYear?c} in template
|
||||
//String thisYear = ((Integer)Calendar.getInstance().get(Calendar.YEAR)).toString(); // use ${copyrightYear} in template
|
||||
//SimpleDate thisYear = new SimpleDate(Calendar.getInstance().getTime(), TemplateDateModel.DATE); // use ${copyrightYear?string("yyyy")} in template
|
||||
copyright.put("year", thisYear);
|
||||
copyright.put("url", portal.getCopyrightURL());
|
||||
root.put("copyright", copyright);
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrl(String path) {
|
||||
if ( ! path.startsWith("/") ) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return contextPath + path;
|
||||
}
|
||||
|
||||
private TabMenu getTabMenu(int portalId) {
|
||||
return new TabMenu(vreq, portalId);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,681 @@
|
|||
/* $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.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.IndividualDao;
|
||||
import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyDao;
|
||||
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 IndividualControllerFM extends VitroHttpServlet {
|
||||
private static final Log log = LogFactory.getLog(IndividualControllerFM.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;
|
||||
}
|
||||
|
||||
doHtml( vreq, res , indiv);
|
||||
return;
|
||||
|
||||
} catch (Throwable e) {
|
||||
log.error(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 {
|
||||
log.error("Entity " + indiv.getURI() + " with vclass URI " +
|
||||
indiv.getVClassURI() + ", no vclass with that URI exists");
|
||||
}
|
||||
if (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");
|
||||
}
|
||||
|
||||
|
||||
// generate link to RDF representation for semantic web clients like Piggy Bank
|
||||
// BJL 2008-07-16: I'm temporarily commenting this out because I forgot we need to make sure it filters out the hidden properties
|
||||
// generate url for this entity
|
||||
// String individualToRDF = "http://"+vreq.getServerName()+":"+vreq.getServerPort()+vreq.getContextPath()+"/entity?home=1&uri="+forURL(entity.getURI())+"&view=rdf.rdf";
|
||||
//css += "<link rel='alternate' type='application/rdf+xml' title='"+entity.getName()+"' href='"+individualToRDF+"' />";
|
||||
|
||||
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 better way to do this
|
||||
String hn = req.getHeader("Host");
|
||||
res.setHeader("Location", res.encodeURL( "http://" + hn + req.getContextPath() + redirectURL ));
|
||||
res.setStatus(res.SC_SEE_OTHER);
|
||||
}
|
||||
|
||||
|
||||
private static Pattern LINKED_DATA_URL = Pattern.compile("^/individual/([^/]*)$");
|
||||
private static Pattern NS_PREFIX_URL = Pattern.compile("^/individual/([^/]*)/([^/]*)$");
|
||||
|
||||
/**
|
||||
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 ){
|
||||
uri = iwDao.getIndividualURIFromNetId(netIdStr);
|
||||
return iwDao.getIndividualByURI(uri);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private static Pattern URI_PATTERN = Pattern.compile("^/individual/([^/]*)$");
|
||||
//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 = "/individual/" + 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("^/individual/([^/]*)/\\1.rdf$");
|
||||
private static Pattern N3_REQUEST = Pattern.compile("^/individual/([^/]*)/\\1.n3$");
|
||||
private static Pattern TTL_REQUEST = Pattern.compile("^/individual/([^/]*)/\\1.ttl$");
|
||||
private static Pattern HTML_REQUEST = Pattern.compile("^/display/([^/]*)$");
|
||||
|
||||
/**
|
||||
* @return null if this is not a linked data request, returns content type if it is a
|
||||
* linked data request.
|
||||
*/
|
||||
private 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;
|
||||
}
|
||||
|
||||
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{}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
/* $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.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
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 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.view.IndividualView;
|
||||
|
||||
public class IndividualListControllerFM extends FreeMarkerHttpServlet {
|
||||
|
||||
long startTime = -1;
|
||||
|
||||
private static final Log log = LogFactory.getLog(IndividualListControllerFM.class.getName());
|
||||
private VClass vclass = null;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
// TODO Rewrite error cases to use FreeMarker templates. Restructure so we're always doing the body
|
||||
// and then calling writeOutput().
|
||||
public void doGet( HttpServletRequest req, HttpServletResponse res )
|
||||
throws IOException, ServletException {
|
||||
startTime = System.currentTimeMillis(); // TODO: remove
|
||||
try {
|
||||
super.doSetup(req, res);
|
||||
Object obj = vreq.getAttribute("vclass");
|
||||
vclass=null;
|
||||
if( obj == null ) { // look for vitroclass id parameter
|
||||
String vitroClassIdStr=req.getParameter("vclassId");
|
||||
if (vitroClassIdStr!=null && !vitroClassIdStr.equals("")) {
|
||||
try {
|
||||
//TODO have to change this so vclass's group and entity count are populated
|
||||
vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vitroClassIdStr);
|
||||
if (vclass == null) {
|
||||
log.error("Couldn't retrieve vclass "+vitroClassIdStr);
|
||||
response.sendRedirect(Controllers.BROWSE_CONTROLLER+"-freemarker?"+vreq.getQueryString());
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
throw new HelpException("EntityListControllerFM: request parameter 'vclassId' must be a URI string");
|
||||
}
|
||||
}
|
||||
} else if (obj instanceof VClass) {
|
||||
vclass = (VClass)obj;
|
||||
} else {
|
||||
throw new HelpException("EntityListControllerFM: attribute 'vclass' must be of type "
|
||||
+ VClass.class.getName() );
|
||||
}
|
||||
if (vclass!=null){
|
||||
setBody();
|
||||
write(response);
|
||||
}
|
||||
// RY Rewrite error cases for FreeMarker, not JSP
|
||||
} catch (HelpException help){
|
||||
doHelp(response);
|
||||
} catch (Throwable e) {
|
||||
vreq.setAttribute("javax.servlet.jsp.jspException",e);
|
||||
RequestDispatcher rd = req.getRequestDispatcher("/error.jsp");
|
||||
rd.forward(vreq, response);
|
||||
}
|
||||
}
|
||||
|
||||
public void doPost(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException,IOException {
|
||||
doGet(request, response);
|
||||
}
|
||||
|
||||
protected String getBody() {
|
||||
|
||||
Map<String, Object> body = new HashMap<String, Object>();
|
||||
|
||||
// Create list of individuals
|
||||
List<Individual> individualList = vreq.getWebappDaoFactory().getIndividualDao().getIndividualsByVClass(vclass);
|
||||
List<IndividualView> individuals = new ArrayList<IndividualView>();
|
||||
|
||||
body.put("individuals", individuals);
|
||||
|
||||
// But the JSP version includes url rewriting via URLRewritingHttpServletResponse
|
||||
body.put("individualUrl", config.getSharedVariable("contextPath") + "/entity?home=" + config.getSharedVariable("portalId") + "&uri=");
|
||||
|
||||
if (individuals == null) {
|
||||
log.error("individuals list is null");
|
||||
}
|
||||
|
||||
// Use instead of getTitle(), because we have a subtitle too
|
||||
String title = "";
|
||||
VClassGroup classGroup=vclass.getGroup();
|
||||
if (classGroup==null) {
|
||||
title = vclass.getName();
|
||||
} else {
|
||||
title = classGroup.getPublicName();
|
||||
setSharedVariable("subTitle", vclass.getName());
|
||||
}
|
||||
setSharedVariable("title", title);
|
||||
|
||||
String templateName = "entityList.ftl";
|
||||
return mergeBodyToTemplate(templateName, body);
|
||||
|
||||
}
|
||||
|
||||
// RY Rewrite as a template
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.servlet.setup;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
||||
import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.DefaultObjectWrapper;
|
||||
import freemarker.template.TemplateException;
|
||||
|
||||
public class FreeMarkerSetup implements ServletContextListener {
|
||||
|
||||
private static final Log log = LogFactory.getLog(FreeMarkerSetup.class);
|
||||
|
||||
public void contextInitialized(ServletContextEvent event) {
|
||||
|
||||
ServletContext sc = event.getServletContext();
|
||||
|
||||
// RY Change this to multi-location template scheme
|
||||
String templatePath = sc.getRealPath("/templates/freemarker");
|
||||
|
||||
Configuration cfg = new Configuration();
|
||||
|
||||
/* **** RY
|
||||
Here's what I want to do to avoid having to pass in the contextPath to every view object created (in order for them to create their URLs):
|
||||
Subclass Configuration. Add a static variable CONTEXT_PATH to it. Set that value here, and define a getter also. Then when creating
|
||||
urls in view object methods like getUrl(), we can reference that configuration value. None of this is possible unless we can use
|
||||
the method ServletContext.getContextPath(), new to Servlet API 2.5 andn therefore requiring tomcat 6 rather than 5.
|
||||
*/
|
||||
|
||||
// Specify the data source where the template files come from.
|
||||
try {
|
||||
cfg.setDirectoryForTemplateLoading(new File(templatePath));
|
||||
} catch (IOException e) {
|
||||
log.error("Error specifying template directory.");
|
||||
}
|
||||
|
||||
// RY This setting won't take effect until we use Configuration.getTemplate() to
|
||||
// create templates.
|
||||
String buildEnv = ConfigurationProperties.getProperty("Environment.build");
|
||||
if (buildEnv != null && buildEnv.equals("development")) {
|
||||
cfg.setTemplateUpdateDelay(0); // no template caching in development
|
||||
}
|
||||
|
||||
// Specify how templates will see the data-model. This is an advanced topic...
|
||||
// but just use this:
|
||||
cfg.setObjectWrapper(new DefaultObjectWrapper());
|
||||
|
||||
try {
|
||||
cfg.setSetting("url_escaping_charset", "ISO-8859-1");
|
||||
} catch (TemplateException e) {
|
||||
// TODO Auto-generated catch block
|
||||
log.error("Error setting value for url_escaping_charset.");
|
||||
}
|
||||
|
||||
FreeMarkerHttpServlet.config = cfg;
|
||||
|
||||
String contextPath = sc.getContextPath();
|
||||
FreeMarkerHttpServlet.contextPath = contextPath;
|
||||
ViewObject.contextPath = contextPath;
|
||||
}
|
||||
|
||||
public void contextDestroyed(ServletContextEvent event) {
|
||||
// nothing to do here
|
||||
}
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ package edu.cornell.mannlib.vitro.webapp.utils;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class StringUtils {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.utils.display;
|
||||
package edu.cornell.mannlib.vitro.webapp.utils.view;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
|
@ -0,0 +1,54 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view;
|
||||
|
||||
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.VClassGroup;
|
||||
|
||||
public class IndividualView extends ViewObject {
|
||||
|
||||
private static final Log log = LogFactory.getLog(IndividualView.class.getName());
|
||||
|
||||
private static final String URL = "/individual";
|
||||
|
||||
private Individual individual;
|
||||
|
||||
public IndividualView(Individual individual) {
|
||||
this.individual = individual;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return individual.getName();
|
||||
}
|
||||
|
||||
public String getMoniker() {
|
||||
return individual.getMoniker();
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return individual.getURI();
|
||||
}
|
||||
|
||||
// Or maybe getProfileUrl - there might be other kinds of urls
|
||||
// e.g., getEditUrl, getDeleteUrl - these would return the computations of PropertyEditLinks
|
||||
public String getProfileUrl() {
|
||||
return contextPath + URL + ""; // ADD IN the label from the individual's uri
|
||||
}
|
||||
|
||||
public String getCustomView() {
|
||||
// see code currently in entityList.ftl
|
||||
String customView = null;
|
||||
|
||||
return customView;
|
||||
}
|
||||
|
||||
public Object getProperty(String propertyName) {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup;
|
||||
|
||||
/*
|
||||
* A VClassGroupDisplay object is associated with a VClassGroup for display.
|
||||
* It is an object that contains a linked list, rather than a type of linked list,
|
||||
* so that JSP EL can access properties such as publicName.
|
||||
*
|
||||
* RY We may want an abstract display class as a superclass.
|
||||
* RY We may want an interface that the superclass would implement.
|
||||
* RY We may want to nest this class in the VClassGroup class.
|
||||
*/
|
||||
public class VClassGroupView extends ViewObject {
|
||||
|
||||
private static final Log log = LogFactory.getLog(VClassGroupView.class.getName());
|
||||
|
||||
private VClassGroup vClassGroup = null;
|
||||
private List<VClassView> classes = null;
|
||||
|
||||
public VClassGroupView(VClassGroup vClassGroup) {
|
||||
this.vClassGroup = vClassGroup;
|
||||
}
|
||||
|
||||
public int getDisplayRank() {
|
||||
return vClassGroup.getDisplayRank();
|
||||
}
|
||||
|
||||
public String getUri() {
|
||||
return vClassGroup.getURI();
|
||||
}
|
||||
|
||||
public String getNamespace() {
|
||||
return vClassGroup.getNamespace();
|
||||
}
|
||||
|
||||
public String getLocalName() {
|
||||
return vClassGroup.getLocalName();
|
||||
}
|
||||
|
||||
public String getPublicName() {
|
||||
return vClassGroup.getPublicName();
|
||||
}
|
||||
|
||||
public List<VClassView> getClasses() {
|
||||
// Do we need to store the classes as an instance member? Would we ever access this method more than once per template?
|
||||
if (classes == null) {
|
||||
List<VClass> classList = vClassGroup.getVitroClassList();
|
||||
classes = new ArrayList<VClassView>();
|
||||
Iterator<VClass> i = classList.iterator();
|
||||
while (i.hasNext()) {
|
||||
classes.add(new VClassView((VClass) i.next()));
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.VClass;
|
||||
|
||||
public class VClassView extends ViewObject {
|
||||
|
||||
private static final Log log = LogFactory.getLog(VClassView.class.getName());
|
||||
private static final String URL = "/individuallistFM?vclassId=";
|
||||
|
||||
private VClass vclass;
|
||||
|
||||
public VClassView(VClass vclass) {
|
||||
this.vclass = vclass;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return vclass.getName();
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return contextPath + URL + encodeUrl(vclass.getURI());
|
||||
}
|
||||
|
||||
public int getEntityCount() {
|
||||
return vclass.getEntityCount();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.FreeMarkerHttpServlet;
|
||||
import edu.cornell.mannlib.vitro.webapp.utils.StringUtils;
|
||||
|
||||
public abstract class ViewObject {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ViewObject.class.getName());
|
||||
|
||||
public static String contextPath;
|
||||
|
||||
protected static String getUrl(String path) {
|
||||
return FreeMarkerHttpServlet.getUrl(path);
|
||||
}
|
||||
|
||||
protected String encodeUrl(String url) {
|
||||
String encoding = "ISO-8859-1";
|
||||
String encodedUrl = null;
|
||||
try {
|
||||
encodedUrl = URLEncoder.encode(url, encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error("Error encoding url " + url + " with encoding " + encoding + ": Unsupported encoding.");
|
||||
}
|
||||
return encodedUrl;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view.menu;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
||||
/** A menu that can indicate the active item.
|
||||
*
|
||||
* @author rjy7
|
||||
*
|
||||
*/
|
||||
public class MainMenu extends Menu {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Log log = LogFactory.getLog(MainMenu.class.getName());
|
||||
|
||||
public MainMenu(VitroRequest vreq, int portalId) {
|
||||
super(vreq, portalId);
|
||||
}
|
||||
|
||||
public void addItem(String text, String path) {
|
||||
boolean active = vreq.getServletPath().equals(path);
|
||||
MainMenuItem i = new MainMenuItem(text, path, active);
|
||||
items.add(i);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view.menu;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
||||
/** A menu item that indicates whether it is the active item or not.
|
||||
*
|
||||
* @author rjy7
|
||||
*
|
||||
*/
|
||||
public class MainMenuItem extends MenuItem {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MainMenuItem.class.getName());
|
||||
|
||||
private boolean active;
|
||||
|
||||
public MainMenuItem(String linkText, String path, boolean active) {
|
||||
super(linkText, path);
|
||||
this.active = active;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view.menu;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
|
||||
|
||||
public class Menu extends ViewObject {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Log log = LogFactory.getLog(Menu.class.getName());
|
||||
|
||||
protected VitroRequest vreq;
|
||||
protected int portalId;
|
||||
protected List<MenuItem> items;
|
||||
|
||||
public Menu(VitroRequest vreq, int portalId) {
|
||||
this.vreq = vreq;
|
||||
this.portalId = portalId;
|
||||
items = new ArrayList<MenuItem>();
|
||||
}
|
||||
|
||||
public void addItem(String text, String path) {
|
||||
items.add(new MenuItem(text, path));
|
||||
}
|
||||
|
||||
public List<MenuItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view.menu;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.view.ViewObject;
|
||||
|
||||
public class MenuItem extends ViewObject {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MenuItem.class.getName());
|
||||
|
||||
private String text;
|
||||
private String url;
|
||||
|
||||
public MenuItem(String linkText, String path) {
|
||||
text = linkText;
|
||||
url = getUrl(path);
|
||||
}
|
||||
|
||||
public String getLinkText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.view.menu;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.beans.Tab;
|
||||
import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.web.TabWebUtil;
|
||||
|
||||
/** A main menu constructed from persisted tab data
|
||||
*
|
||||
* @author rjy7
|
||||
*
|
||||
*/
|
||||
public class TabMenu extends MainMenu {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Log log = LogFactory.getLog(TabMenu.class.getName());
|
||||
|
||||
public TabMenu(VitroRequest vreq, int portalId) {
|
||||
super(vreq, portalId);
|
||||
|
||||
//Tabs stored in database
|
||||
List<Tab> primaryTabs = vreq.getWebappDaoFactory().getTabDao().getPrimaryTabs(portalId);
|
||||
int tabId = TabWebUtil.getTabIdFromRequest(vreq);
|
||||
int rootId = TabWebUtil.getRootTabId(vreq);
|
||||
List tabLevels = vreq.getWebappDaoFactory().getTabDao().getTabHierarcy(tabId,rootId);
|
||||
vreq.setAttribute("tabLevels", tabLevels);
|
||||
Iterator<Tab> primaryTabIterator = primaryTabs.iterator();
|
||||
Iterator tabLevelIterator = tabLevels.iterator();
|
||||
Tab tab;
|
||||
while (primaryTabIterator.hasNext()) {
|
||||
tab = (Tab) primaryTabIterator.next();
|
||||
addItem(tab.getTitle(), "/index.jsp?primary=" + tab.getTabId());
|
||||
// RY Also need to loop through nested tab levels, but not doing that now.
|
||||
}
|
||||
|
||||
// Hard-coded tabs. It's not really a good idea to have these here, since any menu item that doesn't
|
||||
// come from the db should be accessible to the template to change the text. But we need them here
|
||||
// to apply the "active" mechanism.
|
||||
addItem("Index", "/browsecontroller");
|
||||
addItem("Index - FM", "/browse");
|
||||
}
|
||||
|
||||
}
|
12
webapp/web/templates/freemarker/body/about.ftl
Normal file
12
webapp/web/templates/freemarker/body/about.ftl
Normal file
|
@ -0,0 +1,12 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt -->
|
||||
|
||||
<h2>${title}</h2>
|
||||
|
||||
<#if aboutText??>
|
||||
<div class="pageGroupBody" id="aboutText">${aboutText}</div>
|
||||
</#if>
|
||||
|
||||
<#if acknowledgeText??>
|
||||
<div class="pageGroupBody" id="acknowledgementText">${acknowledgeText}</div>
|
||||
</#if>
|
||||
|
14
webapp/web/templates/freemarker/body/browseGroups.ftl
Normal file
14
webapp/web/templates/freemarker/body/browseGroups.ftl
Normal file
|
@ -0,0 +1,14 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#if message??>
|
||||
<p>${message}</p>
|
||||
<#else>
|
||||
<#list classGroups as classGroup>
|
||||
<h2>${classGroup.publicName}</h2>
|
||||
<ul>
|
||||
<#list classGroup.classes as class>
|
||||
<li><a href="${class.url}">${class.name}</a> (${class.entityCount})</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</#list>
|
||||
</#if>
|
0
webapp/web/templates/freemarker/body/individual.ftl
Normal file
0
webapp/web/templates/freemarker/body/individual.ftl
Normal file
35
webapp/web/templates/freemarker/body/individualList.ftl
Normal file
35
webapp/web/templates/freemarker/body/individualList.ftl
Normal file
|
@ -0,0 +1,35 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<div class="contents">
|
||||
|
||||
<div class="entityList">
|
||||
<h2>${title}</h2>
|
||||
<#if subtitle??>
|
||||
<h4>${subTitle}"</h4>
|
||||
</#if>
|
||||
|
||||
<ul>
|
||||
<#list entities as entity>
|
||||
<#-- Iterate through the object's class hierarchy, looking for a custom view -->
|
||||
<#-- RY This should be done in a view method -->
|
||||
<#list entity.VClasses as type>
|
||||
<#if type.customSearchView?has_content>
|
||||
<#assign altRender = type.customSearchView>
|
||||
<#-- What order are these returned in? If from specific to general, we should break if we find one -->
|
||||
</#if>
|
||||
</#list>
|
||||
<li>
|
||||
<#-- RY Create a directive to work like c:url with c:param -->
|
||||
<#-- RY The JSP version includes URL rewriting in a filter - see URLRewritingHttpServletResponse -->
|
||||
<a href="${entityUrl}${entity.URI?url}">${entity.name}</a> | <#-- add p:process to name -->
|
||||
<#if entity.moniker?has_content>
|
||||
${entity.moniker} <#-- add p:process -->
|
||||
<#else>
|
||||
${entity.VClass.name}
|
||||
</#if>
|
||||
|
||||
</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
12
webapp/web/templates/freemarker/components/copyright.ftl
Normal file
12
webapp/web/templates/freemarker/components/copyright.ftl
Normal file
|
@ -0,0 +1,12 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#if copyright??>
|
||||
<div class="copyright">
|
||||
©${copyright.year?c}
|
||||
<#if copyright.url??>
|
||||
<a href="${copyright.url}">${copyright.text}</a>
|
||||
<#else>
|
||||
${copyright.text}
|
||||
</#if>
|
||||
</div>
|
||||
</#if>
|
5
webapp/web/templates/freemarker/components/doctype.html
Normal file
5
webapp/web/templates/freemarker/components/doctype.html
Normal file
|
@ -0,0 +1,5 @@
|
|||
<!-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
28
webapp/web/templates/freemarker/components/footer.ftl
Normal file
28
webapp/web/templates/freemarker/components/footer.ftl
Normal file
|
@ -0,0 +1,28 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#import "/macros/list.ftl" as l>
|
||||
|
||||
<div id="footer">
|
||||
|
||||
<#if bannerImageUrl??>
|
||||
<img class="footerLogo" src="${urls.bannerImage}" alt="${tagline!}" />
|
||||
</#if>
|
||||
|
||||
<div class="footerLinks">
|
||||
<ul class="otherNav">
|
||||
<@l.makeList>
|
||||
<li><a href="${urls.about}" title="more about this web site">About</a></li>,
|
||||
<#if urls.contact??>
|
||||
<li><a href="${urls.contact}" title="feedback form">Contact Us</a></li>
|
||||
</#if>
|
||||
</@l.makeList>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<#include "copyright.ftl">
|
||||
|
||||
All Rights Reserved. <a href="${urls.termsOfUse}">Terms of Use</a>
|
||||
|
||||
</div>
|
||||
|
||||
<#-- SCRIPT TAGS SHOULD GO HERE -->
|
6
webapp/web/templates/freemarker/components/head.ftl
Normal file
6
webapp/web/templates/freemarker/components/head.ftl
Normal file
|
@ -0,0 +1,6 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<head>
|
||||
<#include "title.ftl">
|
||||
<#include "stylesheets.ftl">
|
||||
</head>
|
33
webapp/web/templates/freemarker/components/identity.ftl
Normal file
33
webapp/web/templates/freemarker/components/identity.ftl
Normal file
|
@ -0,0 +1,33 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#import "/macros/list.ftl" as l>
|
||||
|
||||
<div id="identity">
|
||||
|
||||
<h1><a title="Home" href="${urls.home}">${siteName}</a></h1>
|
||||
|
||||
<#-- RY We will need this in non-NIHVIVO versions
|
||||
<#if tagline.has_content>
|
||||
<em>${tagline}</em>
|
||||
</#if>
|
||||
-->
|
||||
|
||||
<ul id="otherMenu">
|
||||
<@l.makeList>
|
||||
<#if loginName??>
|
||||
<li>
|
||||
Logged in as <strong>${loginName}</strong> (<a href="${urls.logout}">Log out</a>)
|
||||
</li>,
|
||||
<li><a href="${urls.siteAdmin}">Site Admin</a></li>,
|
||||
<#else>
|
||||
<li><a title="log in to manage this site" href="${urls.login}">Log in</a></li>,
|
||||
</#if>
|
||||
|
||||
<li><a href="${urls.about}$">About</a></li>,
|
||||
<li><a href="${urls.aboutFM}">About - FM</a></li>,
|
||||
<#if urls.contact??>
|
||||
<li><a href="${urls.contact}">Contact Us</a></li>
|
||||
</#if>
|
||||
</@l.makeList>
|
||||
</ul>
|
||||
</div>
|
13
webapp/web/templates/freemarker/components/menu.ftl
Normal file
13
webapp/web/templates/freemarker/components/menu.ftl
Normal file
|
@ -0,0 +1,13 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<div id="primaryAndOther">
|
||||
<ul id="primary">
|
||||
<#list tabMenu.items as item>
|
||||
<li>
|
||||
<a href="${item.url}" <#if item.active> class="activeTab" </#if>>
|
||||
${item.linkText}
|
||||
</a>
|
||||
</li>
|
||||
</#list>
|
||||
</ul>
|
||||
</div>
|
1
webapp/web/templates/freemarker/components/scripts.ftl
Normal file
1
webapp/web/templates/freemarker/components/scripts.ftl
Normal file
|
@ -0,0 +1 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
19
webapp/web/templates/freemarker/components/search.ftl
Normal file
19
webapp/web/templates/freemarker/components/search.ftl
Normal file
|
@ -0,0 +1,19 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<div id="searchBlock">
|
||||
<form id="searchForm" action="${urls.search}" >
|
||||
<label for="search">Search </label>
|
||||
|
||||
<#if showFlag1SearchField??>
|
||||
<select id="search-form-modifier" name="flag1" class="form-item" >
|
||||
<option value="nofiltering" selected="selected">entire database (${loginName})</option>
|
||||
<option value="${portalId}">${tagline!}</option>
|
||||
</select>
|
||||
<#else>
|
||||
<input type="hidden" name="flag1" value="${portalId}" />
|
||||
</#if>
|
||||
|
||||
<input type="text" name="querytext" id="search" class="search-form-item" value="${querytext!}" size="20" />
|
||||
<input class="search-form-submit" name="submit" type="submit" value="Search" />
|
||||
</form>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="${stylesheetDir}screen.css" media="screen"/>
|
||||
<link rel="stylesheet" type="text/css" href="${stylesheetDir}print.css" media="print"/>
|
||||
|
||||
<#list stylesheets as stylesheet>
|
||||
${stylesheet}
|
||||
</#list>
|
3
webapp/web/templates/freemarker/components/title.ftl
Normal file
3
webapp/web/templates/freemarker/components/title.ftl
Normal file
|
@ -0,0 +1,3 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<title>${title}</title>
|
68
webapp/web/templates/freemarker/macros/list.ftl
Normal file
68
webapp/web/templates/freemarker/macros/list.ftl
Normal file
|
@ -0,0 +1,68 @@
|
|||
<#--
|
||||
Output a sequence of <li> elements, adding classes "first" and "last" to first and last list elements, respectively.
|
||||
It is helpful when the list elements are generated conditionally, to avoid complex tests for the presence/absence
|
||||
of other list elements in order to assign these classes.
|
||||
|
||||
Input should be a series of <li> elements separated by some delimiter. Default delimiter value is ",".
|
||||
|
||||
Tolerates a delimiter following the last <li> element.
|
||||
|
||||
Usage:
|
||||
<@makeList>
|
||||
<li>apples</li>,
|
||||
<li>bananas</li>,
|
||||
<li>oranges</li>
|
||||
<@makeList>
|
||||
|
||||
<@makeList delim="??">
|
||||
<li>apples, oranges</li>??
|
||||
<li>bananas, lemons</li>??
|
||||
<li>grapefruit, limes</li>
|
||||
<@makeList>
|
||||
|
||||
RY Consider rewriting in Java. Probably designers won't want to modify this.
|
||||
-->
|
||||
<#macro makeList delim=",">
|
||||
<#assign text>
|
||||
<#nested>
|
||||
</#assign>
|
||||
|
||||
<#-- Strip out a list-final delimiter, else (unlike most languages) it results in an empty final array item. -->
|
||||
<#assign text = text?replace("${delim}$", "", "r")>
|
||||
|
||||
<#assign items = text?split(delim)>
|
||||
|
||||
<#list items as item>
|
||||
<#-- A FreeMarker loop variable cannot have its value modified, so we use a new variable. -->
|
||||
<#assign newItem = item?trim>
|
||||
|
||||
<#assign classVal = "">
|
||||
|
||||
<#-- Keep any class value already assigned -->
|
||||
<#assign currentClass = newItem?matches("^<li [^>]*(class=[\'\"](.*?)[\'\"])")>
|
||||
<#list currentClass as m>
|
||||
<#assign classVal = m?groups[2]>
|
||||
<#assign newItem = newItem?replace(m?groups[1], "")>
|
||||
</#list>
|
||||
|
||||
<#-- Test indices, rather than comparing content, on the remote chance
|
||||
that there are two list items with the same content. -->
|
||||
<#-- <#if item == arr?first> -->
|
||||
<#if item_index == 0>
|
||||
<#assign classVal = "${classVal} first">
|
||||
</#if>
|
||||
<#-- <#if item == arr?last> -->
|
||||
<#if !item_has_next>
|
||||
<#assign classVal = "${classVal} last">
|
||||
</#if>
|
||||
|
||||
<#if classVal != "">
|
||||
<#assign classVal = classVal?replace("^ ", "", "r")>
|
||||
<#-- Replace first instance only, in case the item contains nested li tags. -->
|
||||
<#assign newItem = newItem?replace("<li", "<li class=\"${classVal}\"", "f")>
|
||||
</#if>
|
||||
${newItem}
|
||||
</#list>
|
||||
</#macro>
|
||||
|
||||
<#----------------------------------------------------------------------------->
|
32
webapp/web/templates/freemarker/page/default.ftl
Normal file
32
webapp/web/templates/freemarker/page/default.ftl
Normal file
|
@ -0,0 +1,32 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#include "/components/doctype.html">
|
||||
|
||||
<#include "/components/head.ftl">
|
||||
|
||||
<body>
|
||||
<div id="wrap" class="container">
|
||||
<div id="header">
|
||||
|
||||
<#include "/components/identity.ftl">
|
||||
|
||||
<div id="navAndSearch" class="block">
|
||||
<#include "/components/menu.ftl">
|
||||
<#include "/components/search.ftl">
|
||||
</div> <!-- navAndSearch -->
|
||||
|
||||
</div> <!-- header -->
|
||||
|
||||
<hr class="hidden" />
|
||||
|
||||
<div id="contentwrap">
|
||||
<div id="content" <#if contentClass??> class="${contentClass}" </#if>>
|
||||
${body}
|
||||
</div> <!-- content -->
|
||||
</div> <!-- contentwrap -->
|
||||
|
||||
<#include "/components/footer.ftl">
|
||||
|
||||
</div> <!-- wrap -->
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Reference in a new issue