diff --git a/doc/install.html b/doc/install.html index 101ae54b8..6f5091d39 100644 --- a/doc/install.html +++ b/doc/install.html @@ -774,6 +774,39 @@

to build Vitro and deploy to Tomcat's webapps directory.

+

+ The build script may run for as much as five minutes, + and creates more than 100 lines of output. + The process comprises several steps: +

+

+

+ The output of the build may include a variety of warning messages. + The Java compiler may warn of code that is outdated. + Unit tests may produce warning messages, + and some tests may be ignored if they do not produce consistent results. +

+
+ BUILD SUCCESSFUL
Total time: 1 minute 49 seconds +
+

+ If the output ends with a success message, the build was successful. + Proceed to the next step. +

+
+ BUILD FAILED
Total time: 35 seconds +
+

+ If the output ends with a failure message, the build has failed. + Find the cause of the failure, fix the problem, and run the script again. +

+

VII. Configure Tomcat

Set JVM parameters

diff --git a/webapp/build.xml b/webapp/build.xml index e168a2dda..3f3f89a40 100644 --- a/webapp/build.xml +++ b/webapp/build.xml @@ -188,13 +188,6 @@ - - - - - - - diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java index f3e9b2618..80b32b478 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/auth/permissions/SimplePermission.java @@ -74,6 +74,15 @@ public class SimplePermission extends Permission { "SeeVerbosePropertyInformation"); public static final SimplePermission USE_ADVANCED_DATA_TOOLS_PAGES = new SimplePermission( "UseAdvancedDataToolsPages"); + public static final SimplePermission USE_SPARQL_QUERY_PAGE = new SimplePermission( + "UseSparqlQueryPage"); + + // ---------------------------------------------------------------------- + // These instances are "catch all" permissions to cover poorly defined + // groups of actions until better definitions were found. Don't add usages + // of these, and remove existing usages where possible. + // ---------------------------------------------------------------------- + public static final SimplePermission USE_BASIC_AJAX_CONTROLLERS = new SimplePermission( "UseBasicAjaxControllers"); public static final SimplePermission USE_MISCELLANEOUS_ADMIN_PAGES = new SimplePermission( @@ -84,8 +93,6 @@ public class SimplePermission extends Permission { "UseMiscellaneousEditorPages"); public static final SimplePermission USE_MISCELLANEOUS_PAGES = new SimplePermission( "UseMiscellaneousPages"); - public static final SimplePermission USE_SPARQL_QUERY_PAGE = new SimplePermission( - "UseSparqlQueryPage"); public static List getAllInstances() { return new ArrayList(allInstances.values()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ajax/VitroAjaxController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ajax/VitroAjaxController.java index 955a8e2a8..ab848e895 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ajax/VitroAjaxController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/ajax/VitroAjaxController.java @@ -17,7 +17,7 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.auth.policy.PolicyHelper; import edu.cornell.mannlib.vitro.webapp.auth.requestedAction.Actions; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import freemarker.template.Configuration; import freemarker.template.Template; @@ -73,8 +73,8 @@ public abstract class VitroAjaxController extends HttpServlet { * Process data through a Freemarker template and output the result. */ protected void writeTemplate(String templateName, Map map, - VitroRequest vreq, HttpServletResponse response) { - Configuration config = FreemarkerConfigurationLoader.getConfig(vreq); + HttpServletRequest req, HttpServletResponse response) { + Configuration config = FreemarkerConfiguration.getConfig(req); try { Template template = config.getTemplate(templateName); PrintWriter out = response.getWriter(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java index d71dd7366..e01b14cd9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerComponentGenerator.java @@ -61,6 +61,8 @@ public class FreemarkerComponentGenerator extends FreemarkerHttpServlet { return get(templateName, root, request); } + // JB Because this is pretending to be a servlet, but the init method has not been called, providing the context. + // Do that in the constructor, and we should be fine. VIVO-251 // RY We need the servlet context in getConfig(). For some reason using the method inherited from // GenericServlet bombs. @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java deleted file mode 100644 index c6bc10185..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfiguration.java +++ /dev/null @@ -1,322 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller.freemarker; - -import java.io.File; -import java.io.IOException; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; -import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; -import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; -import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; -import edu.cornell.mannlib.vitro.webapp.i18n.freemarker.I18nMethodModel; -import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; -import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; -import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective; -import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod; -import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod; -import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod; -import freemarker.cache.ClassTemplateLoader; -import freemarker.cache.FileTemplateLoader; -import freemarker.cache.MultiTemplateLoader; -import freemarker.cache.TemplateLoader; -import freemarker.core.Environment; -import freemarker.ext.beans.BeansWrapper; -import freemarker.template.Configuration; -import freemarker.template.DefaultObjectWrapper; -import freemarker.template.ObjectWrapper; -import freemarker.template.Template; -import freemarker.template.TemplateException; -import freemarker.template.TemplateModelException; -import freemarker.template.utility.DeepUnwrap; - -public class FreemarkerConfiguration extends Configuration { - - private static final Log log = LogFactory.getLog(FreemarkerConfiguration.class); - - private static final String PROPERTY_DEVELOPER_DEFEAT_CACHE = "developer.defeatFreemarkerCache"; - private static final String PROPERTY_DEVELOPER_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters"; - - private final String themeDir; - private final ServletContext context; - private final ApplicationBean appBean; - private final ConfigurationProperties props; - - FreemarkerConfiguration(String themeDir, ApplicationBean appBean, ServletContext context) { - - this.themeDir = themeDir; - this.context = context; - this.appBean = appBean; - this.props = ConfigurationProperties.getBean(context); - - String flag = props.getProperty(PROPERTY_DEVELOPER_DEFEAT_CACHE, "false"); - if (Boolean.valueOf(flag.trim())) { - log.debug("Disabling Freemarker template caching in development build."); - setTemplateUpdateDelay(0); // no template caching in development - } else { - int delay = 60; - log.debug("Setting Freemarker template cache update delay to " + delay + "."); - setTemplateUpdateDelay(delay); // in seconds; Freemarker default is 5 - } - - // Specify how templates will see the data model. - // The Freemarker default wrapper exposes set methods and get methods that take - // arguments. We block exposure to these methods by default. - BeansWrapper wrapper = new DefaultObjectWrapper(); - wrapper.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY); - setObjectWrapper(wrapper); - - // Set some formatting defaults. These can be overridden at the template - // or environment (template-processing) level, or for an individual - // token by using built-ins. - setLocale(java.util.Locale.US); - - String dateFormat = "M/d/yyyy"; - setDateFormat(dateFormat); - String timeFormat = "h:mm a"; - setTimeFormat(timeFormat); - setDateTimeFormat(dateFormat + " " + timeFormat); - - //config.setNumberFormat("#,##0.##"); - - try { - setSetting("url_escaping_charset", "ISO-8859-1"); - } catch (TemplateException e) { - log.error("Error setting value for url_escaping_charset."); - } - - setTemplateLoader(createTemplateLoader()); - - setSharedVariables(); - - } - - /** - * These are values that are accessible to all - * templates loaded by the Configuration's TemplateLoader. They - * should be application- rather than request-specific. - */ - private void setSharedVariables() { - - Map sharedVariables = new HashMap(); - - sharedVariables.put("siteName", appBean.getApplicationName()); - sharedVariables.put("version", getRevisionInfo()); - sharedVariables.put("urls", getSiteUrls()); - sharedVariables.put("themeDir", themeDir); - sharedVariables.put("currentTheme", themeDir.substring(themeDir.lastIndexOf('/')+1)); - - sharedVariables.putAll(getDirectives()); - sharedVariables.putAll(getMethods()); - sharedVariables.put("siteTagline", appBean.getShortHand()); - - //Put in edit configuration constants - useful for freemarker templates/editing - sharedVariables.put("editConfigurationConstants", EditConfigurationConstants.exportConstants()); - - for ( Map.Entry variable : sharedVariables.entrySet() ) { - try { - setSharedVariable(variable.getKey(), variable.getValue()); - } catch (TemplateModelException e) { - log.error("Could not set shared variable '" + variable.getKey() + "' in Freemarker configuration"); - } - } - } - - private final Map getRevisionInfo() { - Map map = new HashMap(); - map.put("label", RevisionInfoBean.getBean(context) - .getReleaseLabel()); - map.put("moreInfoUrl", UrlBuilder.getUrl("/revisionInfo")); - return map; - } - - private final Map getSiteUrls() { - Map urls = new HashMap(); - - // Templates use this to construct urls. - urls.put("base", context.getContextPath()); - - urls.put("home", UrlBuilder.getHomeUrl()); - urls.put("about", UrlBuilder.getUrl(Route.ABOUT)); - urls.put("search", UrlBuilder.getUrl(Route.SEARCH)); - urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE)); - urls.put("login", UrlBuilder.getLoginUrl()); - urls.put("logout", UrlBuilder.getLogoutUrl()); - urls.put("siteAdmin", UrlBuilder.getUrl(Route.SITE_ADMIN)); - urls.put("themeImages", UrlBuilder.getUrl(themeDir + "/images")); - urls.put("images", UrlBuilder.getUrl("/images")); - urls.put("theme", UrlBuilder.getUrl(themeDir)); - urls.put("index", UrlBuilder.getUrl("/browse")); - - return urls; - } - - public static Map getDirectives() { - Map map = new HashMap(); - map.put("dump", new freemarker.ext.dump.DumpDirective()); - map.put("dumpAll", new freemarker.ext.dump.DumpAllDirective()); - map.put("help", new freemarker.ext.dump.HelpDirective()); - map.put("shortView", new IndividualShortViewDirective()); - return map; - } - - public static Map getMethods() { - Map map = new HashMap(); - map.put("profileUrl", new IndividualProfileUrlMethod()); - map.put("localName", new IndividualLocalNameMethod()); - map.put("placeholderImageUrl", new IndividualPlaceholderImageUrlMethod()); - map.put("i18n", new I18nMethodModel()); - return map; - } - - // Define template locations. Template loader will look first in the theme-specific - // location, then in the vitro location. - protected final TemplateLoader createTemplateLoader() { - - List loaders = new ArrayList(); - MultiTemplateLoader mtl = null; - try { - // Theme template loader - String themeTemplatePath = context.getRealPath(themeDir) + "/templates"; - File themeTemplateDir = new File(themeTemplatePath); - // Handle the case where there's no theme template directory gracefully - if (themeTemplateDir.exists()) { - FileTemplateLoader themeFtl = new FileTemplateLoader(themeTemplateDir); - loaders.add(themeFtl); - } - - // Vitro template loader - String vitroTemplatePath = context.getRealPath("/templates/freemarker"); - loaders.add(new FlatteningTemplateLoader(new File(vitroTemplatePath))); - - loaders.add(new ClassTemplateLoader(getClass(), "")); - - TemplateLoader[] loaderArray = loaders.toArray(new TemplateLoader[loaders.size()]); - mtl = new MultiTemplateLoader(loaderArray); - - } catch (IOException e) { - log.error("Error creating template loaders"); - } - - // Add the ability to add delimiters to the templates, based on - // settings. - if (Boolean.valueOf(props.getProperty(PROPERTY_DEVELOPER_INSERT_DELIMITERS))) { - return new DelimitingTemplateLoader(mtl); - } else { - return mtl; - } - } - - /** - * Override getTemplate(), so we can apply DataGetters to all included - * templates. - * - * This won't work for top-level Templates, since the Environment hasn't - * been created yet. When TemplateProcessingHelper creates the Environment, - * it must call retrieveAndRunDataGetters() for the top-level Template. - */ - @Override - public Template getTemplate(String name, Locale locale, String encoding, - boolean parse) throws IOException { - Template template = super.getTemplate(name, locale, encoding, parse); - - if (template == null) { - log.debug("Template '" + name + "' not found for locale '" + locale + "'."); - return template; - } - - Environment env = getEnvironment(); - if (env == null) { - log.debug("Not fetching data getters for template '" + template.getName() + "'. No environment."); - return template; - } - - retrieveAndRunDataGetters(env, template.getName()); - return template; - } - - - /** - * Find the DataGetters for this template, and apply them to the Freemarker - * environment. - */ - public static void retrieveAndRunDataGetters(Environment env, String templateName) { - HttpServletRequest req = (HttpServletRequest) env.getCustomAttribute("request"); - VitroRequest vreq = new VitroRequest(req); - - if (dataGettersAlreadyApplied(env, templateName)) { - log.debug("DataGetters for '" + templateName+"' have already been applied"); - return; - } - - try { - List dgList = DataGetterUtils.getDataGettersForTemplate( - vreq, vreq.getDisplayModel(), templateName); - log.debug("Retrieved " + dgList.size() + " data getters for template '" + templateName + "'"); - - @SuppressWarnings("unchecked") - Map dataMap = (Map) DeepUnwrap.permissiveUnwrap(env.getDataModel()); - for (DataGetter dg : dgList) { - applyDataGetter(dg, env, dataMap); - } - } catch (Exception e) { - log.warn(e, e); - } - } - - /** - * Have the DataGetters for this template already been applied to this environment? - * If not, record that they are being applied now. - */ - @SuppressWarnings("unchecked") - private static boolean dataGettersAlreadyApplied(Environment env, String templateName) { - Set names; - Object o = env.getCustomAttribute("dataGettersApplied"); - if (o instanceof Set) { - names = (Set) o; - } else { - names = new HashSet(); - } - - boolean added = names.add(templateName); - if (added) { - env.setCustomAttribute("dataGettersApplied", names); - return false; - } else { - return true; - } - } - - /** - * Get the data from a DataGetter, and store it in global variables in the - * Freemarker environment. - */ - private static void applyDataGetter(DataGetter dg, Environment env, - Map dataMap) throws TemplateModelException { - Map moreData = dg.getData(dataMap); - ObjectWrapper wrapper = env.getObjectWrapper(); - if (moreData != null) { - for (String key : moreData.keySet()) { - Object value = moreData.get(key); - env.setGlobalVariable(key, wrapper.wrap(value)); - log.debug("Stored in environment: '" + key + "' = '" + value + "'"); - } - } - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfigurationLoader.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfigurationLoader.java deleted file mode 100644 index b4e206181..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerConfigurationLoader.java +++ /dev/null @@ -1,64 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller.freemarker; - -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.ServletContext; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; - -public class FreemarkerConfigurationLoader { - private static final Log log = LogFactory - .getLog(FreemarkerConfigurationLoader.class); - - private static final Map themeToConfigMap = new HashMap(); - - public static FreemarkerConfiguration getConfig(VitroRequest vreq) { - String themeDir = getThemeDir(vreq.getAppBean()); - return getConfigForTheme(themeDir, vreq.getAppBean(), vreq.getSession().getServletContext()); - } - - private static String getThemeDir(ApplicationBean appBean) { - if (appBean == null) { - log.error("Cannot get themeDir from null application bean"); - return null; - } - - String themeDir = appBean.getThemeDir(); - if (themeDir == null) { - log.error("themeDir is null"); - return null; - } - - return themeDir.replaceAll("/$", ""); - } - - /** - * The Configuration is theme-specific because: - * - * 1. The template loader is theme-specific, since it specifies a theme - * directory to load templates from. - * - * 2. Some shared variables are theme-specific. - */ - private static FreemarkerConfiguration getConfigForTheme(String themeDir, - ApplicationBean appBean, ServletContext context) { - synchronized (themeToConfigMap) { - if (themeToConfigMap.containsKey(themeDir)) { - return themeToConfigMap.get(themeDir); - } else { - FreemarkerConfiguration config = new FreemarkerConfiguration( - themeDir, appBean, context); - themeToConfigMap.put(themeDir, config); - return config; - } - } - } - -} \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java index 552846a98..135cf29b2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/FreemarkerHttpServlet.java @@ -37,10 +37,12 @@ import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.Res import edu.cornell.mannlib.vitro.webapp.controller.freemarker.responsevalues.TemplateResponseValues; import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailFactory; import edu.cornell.mannlib.vitro.webapp.email.FreemarkerEmailMessage; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.Tags; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.User; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.menu.MainMenu; import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; import freemarker.template.DefaultObjectWrapper; import freemarker.template.TemplateModel; import freemarker.template.TemplateModelException; @@ -336,7 +338,7 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { private Map buildRequestUrls(VitroRequest vreq) { Map requestUrls = new HashMap(); - FreemarkerConfiguration config = FreemarkerConfigurationLoader.getConfig(vreq); + Configuration config = FreemarkerConfiguration.getConfig(vreq); TemplateModel urlModel = config.getSharedVariable("urls"); try { @@ -427,10 +429,6 @@ public class FreemarkerHttpServlet extends VitroHttpServlet { // the copyright text can be viewed with having to restart Tomcat map.put("copyright", getCopyrightInfo(appBean)); - map.put("url", new edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective()); - map.put("widget", new edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective()); - map.putAll( FreemarkerConfiguration.getDirectives() ); - // Add these accumulator objects. They will collect tags so the template can write them // at the appropriate location. map.put("stylesheets", new Tags().wrap()); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java index c1fd229f3..08b89c33c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/freemarker/TemplateProcessingHelper.java @@ -13,7 +13,8 @@ import javax.servlet.http.HttpServletRequest; 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.freemarker.config.FreemarkerConfiguration; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfigurationImpl; import freemarker.core.Environment; import freemarker.template.Configuration; import freemarker.template.Template; @@ -24,13 +25,9 @@ public class TemplateProcessingHelper { private static final Log log = LogFactory.getLog(TemplateProcessingHelper.class); private Configuration config = null; - private HttpServletRequest request = null; - private ServletContext context = null; public TemplateProcessingHelper(HttpServletRequest request, ServletContext context) { - this.config = FreemarkerConfigurationLoader.getConfig(new VitroRequest(request)); - this.request = request; - this.context = context; + this.config = FreemarkerConfiguration.getConfig(request); } public StringWriter processTemplate(String templateName, Map map) @@ -46,14 +43,6 @@ public class TemplateProcessingHelper { try { Environment env = template.createProcessingEnvironment(map, writer); - // Add request and servlet context as custom attributes of the environment, so they - // can be used in directives. - env.setCustomAttribute("request", request); - env.setCustomAttribute("context", context); - - // Set the Locale from the request into the environment, so date builtins will be - // Locale-dependent - env.setLocale(request.getLocale()); // Define a setup template to be included by every page template String templateType = (String) map.get("templateType"); @@ -62,7 +51,8 @@ public class TemplateProcessingHelper { } // Apply any data-getters that are associated with this template. - FreemarkerConfiguration.retrieveAndRunDataGetters(env, template.getName()); + // TODO clean this up VIVO-249 + FreemarkerConfigurationImpl.retrieveAndRunDataGetters(env, template.getName()); // Now process it. env.process(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetDataForPage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetDataForPage.java deleted file mode 100644 index 632a0a611..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/GetDataForPage.java +++ /dev/null @@ -1,39 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.controller.json; - -import java.util.Map; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONObject; - -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetterUtils; - -/** - * Gets data based on data getter for page uri and returns in the form of Json objects - */ -public class GetDataForPage extends JsonObjectProducer { - private static final Log log = LogFactory.getLog(GetDataForPage.class); - - protected GetDataForPage(VitroRequest vreq) { - super(vreq); - } - - @Override - protected JSONObject process() throws Exception { - JSONObject rObj = null; - String pageUri = vreq.getParameter("pageUri"); - if(pageUri != null && !pageUri.isEmpty()) { - Map data = PageDataGetterUtils.getDataForPage(pageUri, vreq, ctx); - //Convert to json version based on type of page - if(data != null) { - //Convert to json version based on type of page - rObj = PageDataGetterUtils.covertDataToJSONForPage(pageUri, data, vreq, ctx); - } - } - return rObj; - } - -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java index 2fbd9d09f..3f516e109 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServlet.java @@ -3,8 +3,11 @@ package edu.cornell.mannlib.vitro.webapp.controller.json; import java.io.IOException; +import java.net.URLEncoder; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.Enumeration; import java.util.List; import java.util.Map; @@ -15,17 +18,21 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.json.JSONArray; import org.json.JSONObject; import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.Individual; +import edu.cornell.mannlib.vitro.webapp.beans.VClass; +import edu.cornell.mannlib.vitro.webapp.controller.Controllers; import edu.cornell.mannlib.vitro.webapp.controller.VitroHttpServlet; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.utils.log.LogUtils; -import edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter.PageDataGetterUtils; /** * This servlet is for servicing requests for JSON objects/data. @@ -69,7 +76,9 @@ public class JsonServlet extends VitroHttpServlet { log.debug("AJAX request to retrieve individuals by vclasses"); new GetSolrIndividualsByVClasses(vreq).process(resp); } else if( vreq.getParameter("getDataForPage") != null ){ - new GetDataForPage(vreq).process(resp); + throw new IllegalArgumentException("The call invoked deprecated classes " + + "and the parameter for this call appeared nowhere in the code base, " + + "so it was removed in Aug 5th 2013."); }else if( vreq.getParameter("getRenderedSolrIndividualsByVClass") != null ){ new GetRenderedSolrIndividualsByVClass(vreq).process(resp); }else if( vreq.getParameter("getRandomSolrIndividualsByVClass") != null ){ @@ -85,7 +94,7 @@ public class JsonServlet extends VitroHttpServlet { Map map = getSolrVClassIntersectionResults(vclassURIs, vreq, context); //last parameter indicates single vclass instead of multiple vclasses - return processVClassResults(map, vreq, context, false); + return processVclassResultsJSON(map, vreq, false); } public static JSONObject getSolrIndividualsByVClasses(List vclassURIs, HttpServletRequest req, ServletContext context) throws Exception { @@ -93,8 +102,8 @@ public class JsonServlet extends VitroHttpServlet { log.debug("Retrieve solr results for vclasses" + vclassURIs.toString()); Map map = getSolrVClassIntersectionResults(vclassURIs, vreq, context); log.debug("Results returned from Solr for " + vclassURIs.toString() + " are of size " + map.size()); - JSONObject rObj = processVClassResults(map, vreq, context, true); - return rObj; + + return processVclassResultsJSON(map, vreq, true); } //Including version for Solr query for Vclass Intersections @@ -119,10 +128,10 @@ public class JsonServlet extends VitroHttpServlet { } // Map given to process method includes the actual individuals returned from the search - public static JSONObject processVClassResults(Map map, VitroRequest vreq, ServletContext context, boolean multipleVclasses) throws Exception{ - JSONObject rObj = PageDataGetterUtils.processVclassResultsJSON(map, vreq, multipleVclasses); - return rObj; - } +// public static JSONObject processVClassResults(Map map, VitroRequest vreq, ServletContext context, boolean multipleVclasses) throws Exception{ +// JSONObject rObj = processVclassResultsJSON(map, vreq, multipleVclasses); +// return rObj; +// } public static Collection getMostSpecificTypes(Individual individual, WebappDaoFactory wdf) { ObjectPropertyStatementDao opsDao = wdf.getObjectPropertyStatementDao(); @@ -143,7 +152,7 @@ public class JsonServlet extends VitroHttpServlet { Map map = getRandomSolrVClassResults(vclassURI, vreq, context); //last parameter indicates single vclass instead of multiple vclasses - return processVClassResults(map, vreq, context, false); + return processVclassResultsJSON(map, vreq, false); } //Including version for Random Solr query for Vclass Intersections @@ -169,4 +178,120 @@ public class JsonServlet extends VitroHttpServlet { } + /** + * Process results related to VClass or vclasses. Handles both single and multiple vclasses being sent. + */ + public static JSONObject processVclassResultsJSON(Map map, VitroRequest vreq, boolean multipleVclasses) { + JSONObject rObj = new JSONObject(); + VClass vclass=null; + + try { + + // Properties from ontologies used by VIVO - should not be in vitro + DataProperty fNameDp = (new DataProperty()); + fNameDp.setURI("http://xmlns.com/foaf/0.1/firstName"); + DataProperty lNameDp = (new DataProperty()); + lNameDp.setURI("http://xmlns.com/foaf/0.1/lastName"); + DataProperty preferredTitleDp = (new DataProperty()); + preferredTitleDp.setURI("http://vivoweb.org/ontology/core#preferredTitle"); + + if( log.isDebugEnabled() ){ + @SuppressWarnings("unchecked") + Enumeration e = vreq.getParameterNames(); + while(e.hasMoreElements()){ + String name = e.nextElement(); + log.debug("parameter: " + name); + for( String value : vreq.getParameterValues(name) ){ + log.debug("value for " + name + ": '" + value + "'"); + } + } + } + + //need an unfiltered dao to get firstnames and lastnames + WebappDaoFactory fullWdf = vreq.getUnfilteredWebappDaoFactory(); + + String[] vitroClassIdStr = vreq.getParameterValues("vclassId"); + if ( vitroClassIdStr != null && vitroClassIdStr.length > 0){ + for(String vclassId: vitroClassIdStr) { + vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassId); + if (vclass == null) { + log.error("Couldn't retrieve vclass "); + throw new Exception ("Class " + vclassId + " not found"); + } + } + }else{ + log.error("parameter vclassId URI parameter expected "); + throw new Exception("parameter vclassId URI parameter expected "); + } + List vclassIds = Arrays.asList(vitroClassIdStr); + //if single vclass expected, then include vclass. This relates to what the expected behavior is, not size of list + if(!multipleVclasses) { + //currently used for ClassGroupPage + rObj.put("vclass", + new JSONObject().put("URI",vclass.getURI()) + .put("name",vclass.getName())); + } else { + //For now, utilize very last VClass (assume that that is the one to be employed) + //TODO: Find more general way of dealing with this + //put multiple ones in? + if(vclassIds.size() > 0) { + int numberVClasses = vclassIds.size(); + vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassIds.get(numberVClasses - 1)); + rObj.put("vclass", new JSONObject().put("URI",vclass.getURI()) + .put("name",vclass.getName())); + } + // rObj.put("vclasses", new JSONObject().put("URIs",vitroClassIdStr) + // .put("name",vclass.getName())); + } + if (vclass != null) { + + rObj.put("totalCount", map.get("totalCount")); + rObj.put("alpha", map.get("alpha")); + + List inds = (List)map.get("entities"); + log.debug("Number of individuals returned from request: " + inds.size()); + JSONArray jInds = new JSONArray(); + for(Individual ind : inds ){ + JSONObject jo = new JSONObject(); + jo.put("URI", ind.getURI()); + jo.put("label",ind.getRdfsLabel()); + jo.put("name",ind.getName()); + jo.put("thumbUrl", ind.getThumbUrl()); + jo.put("imageUrl", ind.getImageUrl()); + jo.put("profileUrl", UrlBuilder.getIndividualProfileUrl(ind, vreq)); + + jo.put("mostSpecificTypes", JsonServlet.getMostSpecificTypes(ind,fullWdf)); + jo.put("preferredTitle", JsonServlet.getDataPropertyValue(ind, preferredTitleDp, fullWdf)); + + jInds.put(jo); + } + rObj.put("individuals", jInds); + + JSONArray wpages = new JSONArray(); + //Made sure that PageRecord here is SolrIndividualListController not IndividualListController + List pages = (List)map.get("pages"); + for( PageRecord pr: pages ){ + JSONObject p = new JSONObject(); + p.put("text", pr.text); + p.put("param", pr.param); + p.put("index", pr.index); + wpages.put( p ); + } + rObj.put("pages",wpages); + + JSONArray jletters = new JSONArray(); + List letters = Controllers.getLetters(); + for( String s : letters){ + JSONObject jo = new JSONObject(); + jo.put("text", s); + jo.put("param", "alpha=" + URLEncoder.encode(s, "UTF-8")); + jletters.put( jo ); + } + rObj.put("letters", jletters); + } + } catch(Exception ex) { + log.error("Error occurred in processing JSON object", ex); + } + return rObj; + } } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java index 5068e2b1b..a214814f7 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/edit/n3editing/VTwo/EditConfigurationUtils.java @@ -23,11 +23,11 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.VClass; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.edit.n3editing.VTwo.fields.FieldVTwo; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import freemarker.template.Configuration; public class EditConfigurationUtils { @@ -272,7 +272,7 @@ public class EditConfigurationUtils { //Generate HTML for a specific field name given public static String generateHTMLForElement(VitroRequest vreq, String fieldName, EditConfigurationVTwo editConfig) { String html = ""; - Configuration fmConfig = FreemarkerConfigurationLoader.getConfig(vreq); + Configuration fmConfig = FreemarkerConfiguration.getConfig(vreq); FieldVTwo field = editConfig == null ? null : editConfig.getField(fieldName); MultiValueEditSubmission editSub = EditSubmissionUtils.getEditSubmissionFromSession(vreq.getSession(), editConfig); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java index 84f0c1fcd..3f9d3d852 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailFactory.java @@ -25,9 +25,9 @@ import org.apache.commons.logging.LogFactory; import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfiguration; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +import freemarker.template.Configuration; /** * A factory that creates Freemarker-based email messages. @@ -59,8 +59,7 @@ public class FreemarkerEmailFactory { } FreemarkerEmailFactory factory = getFactory(vreq); - FreemarkerConfiguration fConfig = FreemarkerConfigurationLoader - .getConfig(vreq); + Configuration fConfig = FreemarkerConfiguration.getConfig(vreq); return new FreemarkerEmailMessage(vreq, fConfig, factory.getEmailSession(), factory.getReplyToAddress()); } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java index 0dd14a2f3..710242dd9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/email/FreemarkerEmailMessage.java @@ -28,10 +28,8 @@ 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.controller.freemarker.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.web.directives.EmailDirective; -import freemarker.core.Environment; -import freemarker.template.Template; +import freemarker.template.Configuration; import freemarker.template.TemplateException; /** @@ -51,7 +49,7 @@ public class FreemarkerEmailMessage { private final VitroRequest vreq; private final Session mailSession; - private final FreemarkerConfiguration config; + private final Configuration config; private final List recipients = new ArrayList(); private final InternetAddress replyToAddress; @@ -66,7 +64,7 @@ public class FreemarkerEmailMessage { /** * Package access - should only be created by the factory. */ - FreemarkerEmailMessage(VitroRequest vreq, FreemarkerConfiguration fConfig, + FreemarkerEmailMessage(VitroRequest vreq, Configuration fConfig, Session mailSession, InternetAddress replyToAddress) { this.vreq = vreq; this.mailSession = mailSession; @@ -144,14 +142,8 @@ public class FreemarkerEmailMessage { bodyMap.put("email", new EmailDirective(this)); try { - Template template = config.getTemplate(templateName); - - Environment env = template.createProcessingEnvironment(bodyMap, + config.getTemplate(templateName).process(bodyMap, new StringWriter()); - env.setCustomAttribute("request", vreq); - env.setCustomAttribute("context", vreq.getSession() - .getServletContext()); - env.process(); } catch (TemplateException e) { log.error(e, e); } catch (IOException e) { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/uploadrequest/StreamingMultipartHttpServletRequest.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/uploadrequest/StreamingMultipartHttpServletRequest.java index 7b74a2041..e5e32c5c9 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/uploadrequest/StreamingMultipartHttpServletRequest.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/filestorage/uploadrequest/StreamingMultipartHttpServletRequest.java @@ -1,13 +1,9 @@ -package edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest; +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ -import java.io.IOException; -import java.util.List; -import java.util.Map; +package edu.cornell.mannlib.vitro.webapp.filestorage.uploadrequest; import javax.servlet.http.HttpServletRequest; -import org.apache.commons.fileupload.FileItem; -import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; /** @@ -26,8 +22,7 @@ public class StreamingMultipartHttpServletRequest extends * to deal with inputs of very large sizes. * */ - public StreamingMultipartHttpServletRequest(HttpServletRequest request) - throws IOException{ + public StreamingMultipartHttpServletRequest(HttpServletRequest request) { super(request); //use a file uploader that does not save the files to a temporary directory. diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java new file mode 100644 index 000000000..fe7555d35 --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfiguration.java @@ -0,0 +1,293 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.freemarker.config; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties; +import edu.cornell.mannlib.vitro.webapp.config.RevisionInfoBean; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.DelimitingTemplateLoader; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FlatteningTemplateLoader; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.edit.n3editing.configuration.EditConfigurationConstants; +import edu.cornell.mannlib.vitro.webapp.i18n.freemarker.I18nMethodModel; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; +import edu.cornell.mannlib.vitro.webapp.web.directives.IndividualShortViewDirective; +import edu.cornell.mannlib.vitro.webapp.web.directives.UrlDirective; +import edu.cornell.mannlib.vitro.webapp.web.directives.WidgetDirective; +import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualLocalNameMethod; +import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualPlaceholderImageUrlMethod; +import edu.cornell.mannlib.vitro.webapp.web.methods.IndividualProfileUrlMethod; +import freemarker.cache.ClassTemplateLoader; +import freemarker.cache.FileTemplateLoader; +import freemarker.cache.MultiTemplateLoader; +import freemarker.cache.TemplateLoader; +import freemarker.ext.beans.BeansWrapper; +import freemarker.template.Configuration; +import freemarker.template.DefaultObjectWrapper; +import freemarker.template.TemplateException; +import freemarker.template.TemplateModelException; + +/** + * Access point for a singleton Configuration instance. + * + * The instance is created at system startup, so we can fail early if there are + * any problems. + * + * The Configuration is slightly extended to hold request-based information in a + * ThreadLocal. The net result is although there is only one configuration (and + * hence only one template cache), each request gets a customization with its + * own locale, etc. + * + * Each time a request asks for the configuration, check to see whether the + * cache is still valid, and whether the theme has changed (needs a new + * TemplateLoader). Store the request info to the ThreadLocal. + */ +public abstract class FreemarkerConfiguration { + private static final Log log = LogFactory + .getLog(FreemarkerConfiguration.class); + + private static final String PROPERTY_DEFEAT_CACHE = "developer.defeatFreemarkerCache"; + private static final String PROPERTY_INSERT_DELIMITERS = "developer.insertFreemarkerDelimiters"; + + private static volatile FreemarkerConfigurationImpl instance; + private static volatile String previousThemeDir; + + public static Configuration getConfig(HttpServletRequest req) { + confirmInstanceIsSet(); + + synchronized (instance) { + clearTemplateCacheIfRequested(req); + keepTemplateLoaderCurrentWithThemeDirectory(req); + setThreadLocalsForRequest(req); + return instance; + } + } + + private static void confirmInstanceIsSet() { + if (instance == null) { + throw new IllegalStateException( + "VitroFreemarkerConfiguration has not been set."); + } + } + + private static void clearTemplateCacheIfRequested(HttpServletRequest req) { + if (isTemplateCacheInvalid(req)) { + instance.clearTemplateCache(); + } + } + + private static boolean isTemplateCacheInvalid(HttpServletRequest req) { + ConfigurationProperties props = ConfigurationProperties.getBean(req); + + // If the developer doesn't want the cache, it's invalid. + if (Boolean.valueOf(props.getProperty(PROPERTY_DEFEAT_CACHE))) { + return true; + } + + return false; + } + + /** + * Keep track of the theme directory. If it changes, create an appropriate + * new TemplateLoader. + * + * Note that setting a new TemplateLoader on the context Configuration also + * creates a new, empty TemplateCache. + */ + private static void keepTemplateLoaderCurrentWithThemeDirectory( + HttpServletRequest req) { + String themeDir = getThemeDirectory(req); + if (hasThemeDirectoryChanged(themeDir)) { + TemplateLoader tl = createTemplateLoader(req, themeDir); + instance.setTemplateLoader(tl); + } + } + + private static String getThemeDirectory(HttpServletRequest req) { + return new VitroRequest(req).getAppBean().getThemeDir(); + } + + private static boolean hasThemeDirectoryChanged(String themeDir) { + synchronized (instance) { + if (StringUtils.equals(themeDir, previousThemeDir)) { + return false; + } else { + previousThemeDir = themeDir; + return true; + } + } + } + + private static TemplateLoader createTemplateLoader(HttpServletRequest req, + String themeDir) { + ServletContext ctx = req.getSession().getServletContext(); + ConfigurationProperties props = ConfigurationProperties.getBean(ctx); + + List loaders = new ArrayList(); + + // Theme template loader + String themeTemplatePath = ctx.getRealPath(themeDir) + "/templates"; + File themeTemplateDir = new File(themeTemplatePath); + // A theme need not contain a template directory. + if (themeTemplateDir.exists()) { + try { + FileTemplateLoader themeFtl = new FileTemplateLoader( + themeTemplateDir); + loaders.add(themeFtl); + } catch (IOException e) { + log.error("Error creating theme template loader", e); + } + } + + // Vitro template loader + String vitroTemplatePath = ctx.getRealPath("/templates/freemarker"); + loaders.add(new FlatteningTemplateLoader(new File(vitroTemplatePath))); + + // TODO VIVO-243 Why is this here? + loaders.add(new ClassTemplateLoader(FreemarkerConfiguration.class, "")); + + TemplateLoader[] loaderArray = loaders + .toArray(new TemplateLoader[loaders.size()]); + MultiTemplateLoader mtl = new MultiTemplateLoader(loaderArray); + + // If requested, add delimiters to the templates. + if (Boolean.valueOf(props.getProperty(PROPERTY_INSERT_DELIMITERS))) { + return new DelimitingTemplateLoader(mtl); + } else { + return mtl; + } + } + + private static void setThreadLocalsForRequest(HttpServletRequest req) { + instance.setRequestInfo(req); + } + + // ---------------------------------------------------------------------- + // Setup class + // ---------------------------------------------------------------------- + + public static class Setup implements ServletContextListener { + @Override + public void contextInitialized(ServletContextEvent sce) { + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); + try { + instance = createConfiguration(ctx); + ss.info(this, "Initialized the Freemarker configuration."); + } catch (Exception e) { + ss.fatal(this, + "Failed to initialize the Freemarker configuration.", e); + } + } + + private FreemarkerConfigurationImpl createConfiguration( + ServletContext ctx) throws TemplateModelException { + FreemarkerConfigurationImpl c = new FreemarkerConfigurationImpl(); + + setMiscellaneousProperties(c); + setSharedVariables(c, ctx); + addDirectives(c); + addMethods(c); + + return c; + } + + private void setMiscellaneousProperties(FreemarkerConfigurationImpl c) { + /* + * Lengthen the cache time. + */ + c.setTemplateUpdateDelay(60); // increase from the 5-second default + + /* + * On most template models, hide the getters and setters that take + * arguments. + */ + BeansWrapper wrapper = new DefaultObjectWrapper(); + wrapper.setExposureLevel(BeansWrapper.EXPOSE_PROPERTIES_ONLY); + c.setObjectWrapper(wrapper); + + /* + * Set a default Locale, but expect it to be overridden by the + * request. + */ + c.setLocale(java.util.Locale.US); + + /* + * This is how we like our date and time strings to look. + */ + String dateFormat = "M/d/yyyy"; + c.setDateFormat(dateFormat); + String timeFormat = "h:mm a"; + c.setTimeFormat(timeFormat); + c.setDateTimeFormat(dateFormat + " " + timeFormat); + + /* + * What character set is used when escaping special characters in a + * URL? + */ + try { + c.setSetting("url_escaping_charset", "ISO-8859-1"); + } catch (TemplateException e) { + log.error("Error setting value for url_escaping_charset."); + } + } + + private void setSharedVariables(FreemarkerConfigurationImpl c, + ServletContext ctx) throws TemplateModelException { + c.setSharedVariable("version", getRevisionInfo(ctx)); + + /* + * Put in edit configuration constants - useful for freemarker + * templates/editing + */ + c.setSharedVariable("editConfigurationConstants", + EditConfigurationConstants.exportConstants()); + } + + private void addDirectives(FreemarkerConfigurationImpl c) { + c.setSharedVariable("dump", new freemarker.ext.dump.DumpDirective()); + c.setSharedVariable("dumpAll", + new freemarker.ext.dump.DumpAllDirective()); + c.setSharedVariable("help", new freemarker.ext.dump.HelpDirective()); + c.setSharedVariable("shortView", new IndividualShortViewDirective()); + c.setSharedVariable("url", new UrlDirective()); + c.setSharedVariable("widget", new WidgetDirective()); + } + + private void addMethods(FreemarkerConfigurationImpl c) { + c.setSharedVariable("profileUrl", new IndividualProfileUrlMethod()); + c.setSharedVariable("localName", new IndividualLocalNameMethod()); + c.setSharedVariable("placeholderImageUrl", + new IndividualPlaceholderImageUrlMethod()); + c.setSharedVariable("i18n", new I18nMethodModel()); + } + + private Map getRevisionInfo(ServletContext ctx) { + Map map = new HashMap(); + map.put("label", RevisionInfoBean.getBean(ctx).getReleaseLabel()); + map.put("moreInfoUrl", UrlBuilder.getUrl("/revisionInfo")); + return map; + } + + @Override + public void contextDestroyed(ServletContextEvent sce) { + instance = null; + } + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java new file mode 100644 index 000000000..b4318c97f --- /dev/null +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/freemarker/config/FreemarkerConfigurationImpl.java @@ -0,0 +1,309 @@ +/* $This file is distributed under the terms of the license in /doc/license.txt$ */ + +package edu.cornell.mannlib.vitro.webapp.freemarker.config; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import edu.cornell.mannlib.vitro.webapp.beans.ApplicationBean; +import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; +import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetter; +import edu.cornell.mannlib.vitro.webapp.utils.dataGetter.DataGetterUtils; +import freemarker.core.Environment; +import freemarker.template.Configuration; +import freemarker.template.ObjectWrapper; +import freemarker.template.SimpleScalar; +import freemarker.template.Template; +import freemarker.template.TemplateModel; +import freemarker.template.TemplateModelException; +import freemarker.template.utility.DeepUnwrap; + +/** + * Extend the Freemarker Configuration class to include some information that is + * particular to the current request. + * + * Takes advantage of the fact that each servlet request runs in a separate + * thread. Stores the request-based information in a ThreadLocal. Override any + * methods that should return that information instead of (or in addition to) + * the common info. + * + * Only the getters are overridden, not the setters. So if you call + * setAllSharedVariables(), for example, it will have no effect on the + * request-based information. + */ +public class FreemarkerConfigurationImpl extends Configuration { + private static final Log log = LogFactory + .getLog(FreemarkerConfigurationImpl.class); + + private final ThreadLocal rbiRef = new ThreadLocal<>(); + + void setRequestInfo(HttpServletRequest req) { + rbiRef.set(new RequestBasedInformation(req, this)); + } + + @Override + public Object getCustomAttribute(String name) { + Map attribs = rbiRef.get().getCustomAttributes(); + if (attribs.containsKey(name)) { + return attribs.get(name); + } else { + return super.getCustomAttribute(name); + } + } + + @Override + public String[] getCustomAttributeNames() { + Set rbiNames = rbiRef.get().getCustomAttributes().keySet(); + return joinNames(rbiNames, super.getCustomAttributeNames()); + } + + @Override + public TemplateModel getSharedVariable(String name) { + Map vars = rbiRef.get().getSharedVariables(); + if (vars.containsKey(name)) { + return vars.get(name); + } else { + return super.getSharedVariable(name); + } + } + + @Override + public Set getSharedVariableNames() { + Set rbiNames = rbiRef.get().getSharedVariables().keySet(); + + @SuppressWarnings("unchecked") + Set superNames = super.getSharedVariableNames(); + + Set allNames = new HashSet<>(superNames); + allNames.addAll(rbiNames); + return allNames; + } + + @Override + public Locale getLocale() { + return rbiRef.get().getReq().getLocale(); + } + + private String[] joinNames(Set nameSet, String[] nameArray) { + Set allNames = new HashSet<>(nameSet); + for (String n : nameArray) { + allNames.add(n); + } + return (String[]) allNames.toArray(); + } + + // ---------------------------------------------------------------------- + // Apply DataGetters to templates when loading. + // + // TODO Clean this up VIVO-249 + // ---------------------------------------------------------------------- + + /** + * Override getTemplate(), so we can apply DataGetters to all included + * templates. + * + * This won't work for top-level Templates, since the Environment hasn't + * been created yet. When TemplateProcessingHelper creates the Environment, + * it must call retrieveAndRunDataGetters() for the top-level Template. + */ + @Override + public Template getTemplate(String name, Locale locale, String encoding, + boolean parse) throws IOException { + Template template = super.getTemplate(name, locale, encoding, parse); + + if (template == null) { + log.debug("Template '" + name + "' not found for locale '" + locale + + "'."); + return template; + } + + Environment env = getEnvironment(); + if (env == null) { + log.debug("Not fetching data getters for template '" + + template.getName() + "'. No environment."); + return template; + } + + retrieveAndRunDataGetters(env, template.getName()); + return template; + } + + /** + * Find the DataGetters for this template, and apply them to the Freemarker + * environment. + */ + public static void retrieveAndRunDataGetters(Environment env, + String templateName) { + HttpServletRequest req = (HttpServletRequest) env + .getCustomAttribute("request"); + VitroRequest vreq = new VitroRequest(req); + + if (dataGettersAlreadyApplied(env, templateName)) { + log.debug("DataGetters for '" + templateName + + "' have already been applied"); + return; + } + + try { + List dgList = DataGetterUtils + .getDataGettersForTemplate(vreq, vreq.getDisplayModel(), + templateName); + log.debug("Retrieved " + dgList.size() + + " data getters for template '" + templateName + "'"); + + @SuppressWarnings("unchecked") + Map dataMap = (Map) DeepUnwrap + .permissiveUnwrap(env.getDataModel()); + for (DataGetter dg : dgList) { + applyDataGetter(dg, env, dataMap); + } + } catch (Exception e) { + log.warn(e, e); + } + } + + /** + * Have the DataGetters for this template already been applied to this + * environment? If not, record that they are being applied now. + */ + @SuppressWarnings("unchecked") + private static boolean dataGettersAlreadyApplied(Environment env, + String templateName) { + Set names; + Object o = env.getCustomAttribute("dataGettersApplied"); + if (o instanceof Set) { + names = (Set) o; + } else { + names = new HashSet(); + } + + boolean added = names.add(templateName); + if (added) { + env.setCustomAttribute("dataGettersApplied", names); + return false; + } else { + return true; + } + } + + /** + * Get the data from a DataGetter, and store it in global variables in the + * Freemarker environment. + */ + private static void applyDataGetter(DataGetter dg, Environment env, + Map dataMap) throws TemplateModelException { + Map moreData = dg.getData(dataMap); + ObjectWrapper wrapper = env.getObjectWrapper(); + if (moreData != null) { + for (String key : moreData.keySet()) { + Object value = moreData.get(key); + env.setGlobalVariable(key, wrapper.wrap(value)); + log.debug("Stored in environment: '" + key + "' = '" + value + + "'"); + } + } + } + + // ---------------------------------------------------------------------- + // Helper class + // ---------------------------------------------------------------------- + + /** + * Holds the request-based information. Currently, it's shared variables, a + * custom attribute, and the locale. In the future, it could be more. + */ + private static class RequestBasedInformation { + private final HttpServletRequest req; + private final Configuration c; + private final Map customAttributes = new HashMap<>(); + private final Map sharedVariables = new HashMap<>(); + + public RequestBasedInformation(HttpServletRequest req, Configuration c) { + this.req = req; + this.c = c; + + setSharedVariables(req); + setCustomAttributes(req); + } + + public HttpServletRequest getReq() { + return req; + } + + public Map getCustomAttributes() { + return customAttributes; + } + + public Map getSharedVariables() { + return sharedVariables; + } + + private void setSharedVariables(HttpServletRequest req) { + ServletContext ctx = req.getSession().getServletContext(); + VitroRequest vreq = new VitroRequest(req); + ApplicationBean appBean = vreq.getAppBean(); + String siteName = appBean.getApplicationName(); + String tagLine = appBean.getShortHand(); + String themeDir = appBean.getThemeDir().replaceAll("/$", ""); + String currentTheme = themeDir + .substring(themeDir.lastIndexOf('/') + 1); + Map siteUrls = getSiteUrls(ctx, themeDir); + + sharedVariables.put("siteName", wrap(siteName)); + sharedVariables.put("themeDir", wrap(themeDir)); + sharedVariables.put("currentTheme", wrap(currentTheme)); + sharedVariables.put("siteTagline", wrap(tagLine)); + sharedVariables.put("urls", wrap(siteUrls)); + } + + private Map getSiteUrls(ServletContext ctx, + String themeDir) { + Map urls = new HashMap(); + + // Templates use this to construct urls. + urls.put("base", ctx.getContextPath()); + urls.put("home", UrlBuilder.getHomeUrl()); + urls.put("about", UrlBuilder.getUrl(Route.ABOUT)); + urls.put("search", UrlBuilder.getUrl(Route.SEARCH)); + urls.put("termsOfUse", UrlBuilder.getUrl(Route.TERMS_OF_USE)); + urls.put("login", UrlBuilder.getLoginUrl()); + urls.put("logout", UrlBuilder.getLogoutUrl()); + urls.put("siteAdmin", UrlBuilder.getUrl(Route.SITE_ADMIN)); + + urls.put("themeImages", UrlBuilder.getUrl(themeDir + "/images")); + urls.put("images", UrlBuilder.getUrl("/images")); + urls.put("theme", UrlBuilder.getUrl(themeDir)); + urls.put("index", UrlBuilder.getUrl("/browse")); + + return urls; + } + + private TemplateModel wrap(Object o) { + try { + return c.getObjectWrapper().wrap(o); + } catch (TemplateModelException e) { + log.error("Failed to wrap this " + + "for the Freemarker configuration: " + o, e); + return new SimpleScalar(String.valueOf(o)); + } + } + + private void setCustomAttributes(HttpServletRequest req) { + customAttributes.put("request", req); + } + + } +} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java index 359a53529..51958ba45 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/search/controller/AutocompleteController.java @@ -33,7 +33,7 @@ import edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup; /** * AutocompleteController generates autocomplete content - * via the search index. + * via the search index. */ public class AutocompleteController extends VitroAjaxController { @@ -49,7 +49,7 @@ public class AutocompleteController extends VitroAjaxController { String NORESULT_MSG = ""; - private static final int DEFAULT_MAX_HIT_COUNT = 1000; + private static final int DEFAULT_MAX_HIT_COUNT = 1000; public static final int MAX_QUERY_LENGTH = 500; @@ -57,50 +57,50 @@ public class AutocompleteController extends VitroAjaxController { protected Actions requiredActions(VitroRequest vreq) { return SimplePermission.USE_BASIC_AJAX_CONTROLLERS.ACTIONS; } - + @Override protected void doRequest(VitroRequest vreq, HttpServletResponse response) throws IOException, ServletException { - + try { - + String qtxt = vreq.getParameter(PARAM_QUERY); - - SolrQuery query = getQuery(qtxt, vreq); + + SolrQuery query = getQuery(qtxt, vreq); if (query == null ) { log.debug("query for '" + qtxt +"' is null."); doNoQuery(response); return; } log.debug("query for '" + qtxt +"' is " + query.toString()); - + SolrServer solr = SolrSetup.getSolrServer(getServletContext()); QueryResponse queryResponse = solr.query(query); if ( queryResponse == null) { - log.error("Query response for a search was null"); + log.error("Query response for a search was null"); doNoSearchResults(response); return; } - + SolrDocumentList docs = queryResponse.getResults(); if ( docs == null) { - log.error("Docs for a search was null"); + log.error("Docs for a search was null"); doNoSearchResults(response); return; } - + long hitCount = docs.getNumFound(); log.debug("Total number of hits = " + hitCount); - if ( hitCount < 1 ) { + if ( hitCount < 1 ) { doNoSearchResults(response); return; - } + } List results = new ArrayList(); for (SolrDocument doc : docs) { - try { + try { String uri = doc.get(VitroSearchTermNames.URI).toString(); // RY 7/1/2011 // Comment was: VitroSearchTermNames.NAME_RAW is a multivalued field, so doc.get() returns a list. @@ -116,61 +116,71 @@ public class AutocompleteController extends VitroAjaxController { } else { name = (String) nameRaw; } - SearchResult result = new SearchResult(name, uri); + + Object mostSpecificType = doc.get(VitroSearchTermNames.MOST_SPECIFIC_TYPE_URIS); + String mst = null; + if (mostSpecificType instanceof List) { + @SuppressWarnings("unchecked") + List mstList = (List) mostSpecificType; + mst = mstList.get(0); + } else { + mst = (String) mostSpecificType; + } + + SearchResult result = new SearchResult(name, uri, mst); results.add(result); + log.debug("results = " + results.toString()); } catch(Exception e){ log.error("problem getting usable individuals from search " + "hits" + e.getMessage()); } - } + } Collections.sort(results); - + JSONArray jsonArray = new JSONArray(); for (SearchResult result : results) { jsonArray.put(result.toMap()); } response.getWriter().write(jsonArray.toString()); - + } catch (Throwable e) { - log.error(e, e); + log.error(e, e); doSearchError(response); } } private SolrQuery getQuery(String queryStr, VitroRequest vreq) { - + if ( queryStr == null) { - log.error("There was no parameter '"+ PARAM_QUERY - +"' in the request."); + log.error("There was no parameter '"+ PARAM_QUERY + +"' in the request."); return null; } else if( queryStr.length() > MAX_QUERY_LENGTH ) { log.debug("The search was too long. The maximum " + "query length is " + MAX_QUERY_LENGTH ); return null; } - + SolrQuery query = new SolrQuery(); query.setStart(0) - .setRows(DEFAULT_MAX_HIT_COUNT); - + .setRows(DEFAULT_MAX_HIT_COUNT); setNameQuery(query, queryStr, vreq); - // Filter by type String typeParam = (String) vreq.getParameter(PARAM_RDFTYPE); String multipleTypesParam = (String) vreq.getParameter(PARAM_MULTIPLE_RDFTYPE); if (typeParam != null) { addFilterQuery(query, typeParam, multipleTypesParam); - } - - query.setFields(VitroSearchTermNames.NAME_RAW, VitroSearchTermNames.URI); // fields to retrieve - + } + + query.setFields(VitroSearchTermNames.NAME_RAW, VitroSearchTermNames.URI, VitroSearchTermNames.MOST_SPECIFIC_TYPE_URIS); // fields to retrieve + // Can't sort on multivalued field, so we sort the results in Java when we get them. // query.setSortField(VitroSearchTermNames.NAME_LOWERCASE, SolrQuery.ORDER.asc); - + return query; } - + private void addFilterQuery(SolrQuery query, String typeParam, String multipleTypesParam) { if(multipleTypesParam == null || multipleTypesParam.equals("null") || multipleTypesParam.isEmpty()) { //Single type parameter, process as usual @@ -181,15 +191,13 @@ public class AutocompleteController extends VitroAjaxController { int len = typeParams.length; int i; List filterQueries = new ArrayList(); - + for(i = 0; i < len; i++) { filterQueries.add(VitroSearchTermNames.RDFTYPE + ":\"" + typeParams[i] + "\" "); } String filterQuery = StringUtils.join(filterQueries, " OR "); query.addFilterQuery(filterQuery); } - - } private void setNameQuery(SolrQuery query, String queryStr, HttpServletRequest request) { @@ -197,10 +205,9 @@ public class AutocompleteController extends VitroAjaxController { if (StringUtils.isBlank(queryStr)) { log.error("No query string"); } - - String tokenizeParam = (String) request.getParameter("tokenize"); + String tokenizeParam = (String) request.getParameter("tokenize"); boolean tokenize = "true".equals(tokenizeParam); - + // Note: Stemming is only relevant if we are tokenizing: an untokenized name // query will not be stemmed. So we don't look at the stem parameter until we get to // setTokenizedNameQuery(). @@ -210,43 +217,43 @@ public class AutocompleteController extends VitroAjaxController { setUntokenizedNameQuery(query, queryStr); } } - + private void setTokenizedNameQuery(SolrQuery query, String queryStr, HttpServletRequest request) { /* We currently have no use case for a tokenized, unstemmed autocomplete search field, so the option * has been disabled. If needed in the future, will need to add a new field and field type which * is like AC_NAME_STEMMED but doesn't include the stemmer. - String stemParam = (String) request.getParameter("stem"); + String stemParam = (String) request.getParameter("stem"); boolean stem = "true".equals(stemParam); if (stem) { String acTermName = VitroSearchTermNames.AC_NAME_STEMMED; String nonAcTermName = VitroSearchTermNames.NAME_STEMMED; } else { String acTermName = VitroSearchTermNames.AC_NAME_UNSTEMMED; - String nonAcTermName = VitroSearchTermNames.NAME_UNSTEMMED; + String nonAcTermName = VitroSearchTermNames.NAME_UNSTEMMED; } */ - + String acTermName = VitroSearchTermNames.AC_NAME_STEMMED; String nonAcTermName = VitroSearchTermNames.NAME_STEMMED; String acQueryStr; - + if (queryStr.endsWith(" ")) { - acQueryStr = makeTermQuery(nonAcTermName, queryStr, true); + acQueryStr = makeTermQuery(nonAcTermName, queryStr, true); } else { int indexOfLastWord = queryStr.lastIndexOf(" ") + 1; List terms = new ArrayList(2); - + String allButLastWord = queryStr.substring(0, indexOfLastWord); if (StringUtils.isNotBlank(allButLastWord)) { terms.add(makeTermQuery(nonAcTermName, allButLastWord, true)); } - + String lastWord = queryStr.substring(indexOfLastWord); if (StringUtils.isNotBlank(lastWord)) { terms.add(makeTermQuery(acTermName, lastWord, false)); } - + acQueryStr = StringUtils.join(terms, " AND "); } @@ -255,26 +262,26 @@ public class AutocompleteController extends VitroAjaxController { } - private void setUntokenizedNameQuery(SolrQuery query, String queryStr) { - queryStr = queryStr.trim(); + private void setUntokenizedNameQuery(SolrQuery query, String queryStr) { + queryStr = queryStr.trim(); queryStr = makeTermQuery(VitroSearchTermNames.AC_NAME_UNTOKENIZED, queryStr, true); query.setQuery(queryStr); } - + private String makeTermQuery(String term, String queryStr, boolean mayContainWhitespace) { if (mayContainWhitespace) { queryStr = "\"" + escapeWhitespaceInQueryString(queryStr) + "\""; } return term + ":" + queryStr; } - + private String escapeWhitespaceInQueryString(String queryStr) { // Solr wants whitespace to be escaped with a backslash return queryStr.replaceAll("\\s+", "\\\\ "); } - + private void doNoQuery(HttpServletResponse response) throws IOException { - // For now, we are not sending an error message back to the client because + // For now, we are not sending an error message back to the client because // with the default autocomplete configuration it chokes. doNoSearchResults(response); } @@ -288,36 +295,46 @@ public class AutocompleteController extends VitroAjaxController { private void doNoSearchResults(HttpServletResponse response) throws IOException { response.getWriter().write("[]"); } - + public class SearchResult implements Comparable { private String label; private String uri; - - SearchResult(String label, String uri) { + private String msType; + + SearchResult(String label, String uri, String msType) { this.label = label; this.uri = uri; + this.msType = msType; } - + public String getLabel() { return label; } - + public String getJsonLabel() { return JSONObject.quote(label); } - + public String getUri() { return uri; } - + public String getJsonUri() { return JSONObject.quote(uri); } + public String getMsType() { + return msType; + } + + public String getJsonMsType() { + return JSONObject.quote(msType); + } Map toMap() { Map map = new HashMap(); map.put("label", label); map.put("uri", uri); + map.put("msType", msType); return map; } diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java index dfcc0156b..b6ccfd536 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/services/freemarker/FreemarkerProcessingServiceImpl.java @@ -12,11 +12,8 @@ import javax.servlet.http.HttpServletRequest; 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.controller.freemarker.FreemarkerConfiguration; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.utils.log.LogUtils; -import freemarker.core.Environment; import freemarker.core.ParseException; import freemarker.template.Configuration; import freemarker.template.Template; @@ -53,8 +50,7 @@ public class FreemarkerProcessingServiceImpl implements throws TemplateProcessingException { Template template = null; try { - Configuration config = FreemarkerConfigurationLoader - .getConfig(new VitroRequest(req)); + Configuration config = FreemarkerConfiguration.getConfig(req); template = config.getTemplate(templateName); } catch (ParseException e) { log.warn("Failed to parse the template at '" + templateName + "'" @@ -75,18 +71,7 @@ public class FreemarkerProcessingServiceImpl implements StringWriter writer = new StringWriter(); try { - // Add directives to the map. For some reason, having them in the - // configuration is not enough. - map.putAll(FreemarkerConfiguration.getDirectives()); - - // Add request and servlet context as custom attributes of the - // environment, so they - // can be used in directives. - Environment env = template.createProcessingEnvironment(map, writer); - env.setCustomAttribute("request", req); - env.setCustomAttribute("context", req.getSession() - .getServletContext()); - env.process(); + template.process(map, writer); return writer.toString(); } catch (TemplateException e) { throw new TemplateProcessingException( diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java index 28fa02f5e..6dda504f2 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdateKnowledgeBase.java @@ -5,7 +5,11 @@ package edu.cornell.mannlib.vitro.webapp.servlet.setup; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.IOException; import java.io.StringWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; @@ -31,11 +35,13 @@ 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.config.ConfigurationProperties; import edu.cornell.mannlib.vitro.webapp.dao.DisplayVocabulary; import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess; import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; import edu.cornell.mannlib.vitro.webapp.ontology.update.KnowledgeBaseUpdater; import edu.cornell.mannlib.vitro.webapp.ontology.update.UpdateSettings; +import edu.cornell.mannlib.vitro.webapp.startup.StartupStatus; /** * Invokes process to test whether the knowledge base needs any updating @@ -44,21 +50,10 @@ import edu.cornell.mannlib.vitro.webapp.ontology.update.UpdateSettings; * */ public class UpdateKnowledgeBase implements ServletContextListener { - public static final String KBM_REQURIED_AT_STARTUP = "KNOWLEDGE_BASE_MIGRATION_REQUIRED_AT_STARTUP"; private final static Log log = LogFactory.getLog(UpdateKnowledgeBase.class); private static final String DATA_DIR = "/WEB-INF/ontologies/update/"; - private static final String LOG_DIR = "logs/"; - private static final String CHANGED_DATA_DIR = "changedData/"; - private static final String ASK_QUERY_FILE = DATA_DIR + "askUpdated.sparql"; - private static final String SUCCESS_ASSERTIONS_FILE = DATA_DIR + "success.n3"; - private static final String SUCCESS_RDF_FORMAT = "N3"; - private static final String DIFF_FILE = DATA_DIR + "diff.tab.txt"; - private static final String REMOVED_DATA_FILE = DATA_DIR + CHANGED_DATA_DIR + "removedData.n3"; - private static final String ADDED_DATA_FILE = DATA_DIR + CHANGED_DATA_DIR + "addedData.n3"; - private static final String SPARQL_CONSTRUCT_ADDITIONS_DIR = DATA_DIR + "sparqlConstructs/additions/"; - private static final String SPARQL_CONSTRUCT_DELETIONS_DIR = DATA_DIR + "sparqlConstructs/deletions/"; private static final String OLD_TBOX_MODEL_DIR = DATA_DIR + "oldVersion/"; private static final String NEW_TBOX_MODEL_DIR = "/WEB-INF/filegraph/tbox/"; private static final String OLD_TBOX_ANNOTATIONS_DIR = DATA_DIR + "oldAnnotations/"; @@ -72,33 +67,15 @@ public class UpdateKnowledgeBase implements ServletContextListener { private static final String LOADED_STARTUPT_DISPLAYMODEL_DIR = "/WEB-INF/ontologies/app/loadedAtStartup/"; private static final String OLD_DISPLAYMODEL_VIVOLISTVIEW_PATH = DATA_DIR + "oldDisplayModel/vivoListViewConfig.rdf"; + @Override public void contextInitialized(ServletContextEvent sce) { - try { - ServletContext ctx = sce.getServletContext(); - - // If the DATA_DIR directory doesn't exist no migration check will be done. - // This is a normal situation for Vitro. - File updateDirectory = new File(ctx.getRealPath(DATA_DIR)); - if (!updateDirectory.exists()) { - log.debug("Directory " + ctx.getRealPath(DATA_DIR) + " does not exist, no migration check will be attempted."); - return; - } + ServletContext ctx = sce.getServletContext(); + StartupStatus ss = StartupStatus.getBean(ctx); - String logFileName = DATA_DIR + LOG_DIR + timestampedFileName("knowledgeBaseUpdate", "log"); - String errorLogFileName = DATA_DIR + LOG_DIR + timestampedFileName("knowledgeBaseUpdate.error", "log"); - + try { UpdateSettings settings = new UpdateSettings(); - settings.setAskUpdatedQueryFile(getAskUpdatedQueryPath(ctx)); - settings.setDataDir(ctx.getRealPath(DATA_DIR)); - settings.setSparqlConstructAdditionsDir(ctx.getRealPath(SPARQL_CONSTRUCT_ADDITIONS_DIR)); - settings.setSparqlConstructDeletionsDir(ctx.getRealPath(SPARQL_CONSTRUCT_DELETIONS_DIR)); - settings.setDiffFile(ctx.getRealPath(DIFF_FILE)); - settings.setSuccessAssertionsFile(ctx.getRealPath(SUCCESS_ASSERTIONS_FILE)); - settings.setSuccessRDFFormat(SUCCESS_RDF_FORMAT); - settings.setLogFile(ctx.getRealPath(logFileName)); - settings.setErrorLogFile(ctx.getRealPath(errorLogFileName)); - settings.setAddedDataFile(ctx.getRealPath(ADDED_DATA_FILE)); - settings.setRemovedDataFile(ctx.getRealPath(REMOVED_DATA_FILE)); + putReportingPathsIntoSettings(ctx, settings); + WebappDaoFactory wadf = ModelAccess.on(ctx).getWebappDaoFactory(); settings.setDefaultNamespace(wadf.getDefaultNamespace()); settings.setAssertionOntModelSelector(ModelAccess.on(ctx).getBaseOntModelSelector()); @@ -157,21 +134,54 @@ public class UpdateKnowledgeBase implements ServletContextListener { } } } catch (Exception ioe) { - String errMsg = "Exception updating knowledge base " + - "for ontology changes: "; - // Tomcat doesn't always seem to print exceptions thrown from - // context listeners - System.out.println(errMsg); - ioe.printStackTrace(); - throw new RuntimeException(errMsg, ioe); + ss.fatal(this, "Exception updating knowledge base for ontology changes: ", ioe); } } catch (Throwable t){ - log.warn("warning", t); + ss.fatal(this, "Exception updating knowledge base for ontology changes: ", t); } } catch (Throwable t) { - t.printStackTrace(); + ss.fatal(this, "Exception updating knowledge base for ontology changes: ", t); } } + + /** + * Create the directories where we will report on the update. + * Put the paths for the directories and files into the settings object. + */ + private void putReportingPathsIntoSettings(ServletContext ctx, UpdateSettings settings) throws IOException { + ConfigurationProperties props = ConfigurationProperties.getBean(ctx); + Path homeDir = Paths.get(props.getProperty("vitro.home")); + + Path dataDir = createDirectory(homeDir, "upgrade", "knowledgeBase"); + settings.setDataDir(dataDir.toString()); + StartupStatus.getBean(ctx).info(this, "Updating knowledge base: reports are in '" + dataDir + "'"); + + settings.setAskUpdatedQueryFile(dataDir.resolve("askUpdated.sparql").toString()); + settings.setDiffFile(dataDir.resolve("diff.tab.txt").toString()); + settings.setSuccessAssertionsFile(dataDir.resolve("success.n3").toString()); + settings.setSuccessRDFFormat("N3"); + + settings.setSparqlConstructAdditionsDir(createDirectory(dataDir, "sparqlConstructs", "additions").toString()); + settings.setSparqlConstructDeletionsDir(createDirectory(dataDir, "sparqlConstructs", "deletions").toString()); + + Path changedDir = createDirectory(dataDir, "changedData"); + settings.setAddedDataFile(changedDir.resolve("addedData.n3").toString()); + settings.setRemovedDataFile(changedDir.resolve("removedData.n3").toString()); + + Path logDir = createDirectory(dataDir, "logs"); + settings.setLogFile(logDir.resolve(timestampedFileName("knowledgeBaseUpdate", "log")).toString()); + settings.setErrorLogFile(logDir.resolve(timestampedFileName("knowledgeBaseUpdate.error", "log")).toString()); + } + + private Path createDirectory(Path parent, String... children) throws IOException { + Path dir = parent; + for (String child : children) { + dir = dir.resolve(child); + } + Files.createDirectories(dir); + return dir; + } + //Multiple changes from 1.4 to 1.5 will occur //update migration model @@ -473,15 +483,11 @@ public class UpdateKnowledgeBase implements ServletContextListener { } } + @Override public void contextDestroyed(ServletContextEvent arg0) { // nothing to do } - public static String getAskUpdatedQueryPath(ServletContext ctx) { - return ctx.getRealPath(ASK_QUERY_FILE); - - } - private static String timestampedFileName(String prefix, String suffix) { SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH-mm-sss"); return prefix + "." + sdf.format(new Date()) + "." + suffix; diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdatePermissionSetUris.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdatePermissionSetUris.java index ec03f70ff..e8a66561e 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdatePermissionSetUris.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/servlet/setup/UpdatePermissionSetUris.java @@ -190,7 +190,7 @@ public class UpdatePermissionSetUris implements ServletContextListener { File homeDirectory = new File(homeDirectoryPath); confirmIsDirectory(homeDirectory); - File upgradeDirectory = createDirectory(homeDirectory, "upgrade"); + File upgradeDirectory = createDirectory(homeDirectory, "upgrade/permissions"); String filename = timestampedFilename("UpgradePermissionSetUris", ".txt"); this.file = new File(upgradeDirectory, filename); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/ClassGroupPageData.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/ClassGroupPageData.java deleted file mode 100644 index 0e68dd4b9..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/ClassGroupPageData.java +++ /dev/null @@ -1,155 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletContext; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONObject; - -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; -import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel; - -/** - * This will pass these variables to the template: - * classGroupUri: uri of the classgroup associated with this page. - * vClassGroup: a data structure that is the classgroup associated with this page. - */ -public class ClassGroupPageData implements PageDataGetter{ - private static final Log log = LogFactory.getLog(ClassGroupPageData.class); - - @Override - public Map getData(ServletContext context, VitroRequest vreq, String pageUri, Map page ){ - HashMap data = new HashMap(); - String classGroupUri = vreq.getWebappDaoFactory().getPageDao().getClassGroupPage(pageUri); - data.put("classGroupUri", classGroupUri); - - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); - List vcgList = vcgc.getGroups(); - VClassGroup group = null; - for( VClassGroup vcg : vcgList){ - if( vcg.getURI() != null && vcg.getURI().equals(classGroupUri)){ - group = vcg; - break; - } - } - if( classGroupUri != null && !classGroupUri.isEmpty() && group == null ){ - /*This could be for two reasons: one is that the classgroup doesn't exist - * The other is that there are no individuals in any of the classgroup's classes */ - group = vreq.getWebappDaoFactory().getVClassGroupDao().getGroupByURI(classGroupUri); - if( group != null ){ - List vcgFullList = vreq.getWebappDaoFactory().getVClassGroupDao() - .getPublicGroupsWithVClasses(false, true, false); - for( VClassGroup vcg : vcgFullList ){ - if( classGroupUri.equals(vcg.getURI()) ){ - group = vcg; - break; - } - } - if( group == null ){ - log.error("Cannot get classgroup '" + classGroupUri + "' for page '" + pageUri + "'"); - }else{ - setAllClassCountsToZero(group); - } - }else{ - log.error("classgroup " + classGroupUri + " does not exist in the system"); - } - - } - log.debug("Retrieved class group " + group.getURI() + " and returning to template"); - //if debug enabled, print out the number of entities within each class in the class gorup - if(log.isDebugEnabled()){ - List groupClasses = group.getVitroClassList(); - for(VClass v: groupClasses) { - log.debug("Class " + v.getName() + " - " + v.getURI() + " has " + v.getEntityCount() + " entities"); - } - } - data.put("vClassGroup", group); //may put null - - //This page level data getters tries to set its own template, - // not all of the data getters need to do this. - data.put("bodyTemplate", "page-classgroup.ftl"); - - //Also add data service url - //Hardcoding for now, need a more dynamic way of doing this - data.put("dataServiceUrlIndividualsByVClass", this.getDataServiceUrl()); - return data; - } - - public static VClassGroupTemplateModel getClassGroup(String classGroupUri, ServletContext context, VitroRequest vreq){ - - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); - List vcgList = vcgc.getGroups(); - VClassGroup group = null; - for( VClassGroup vcg : vcgList){ - if( vcg.getURI() != null && vcg.getURI().equals(classGroupUri)){ - group = vcg; - break; - } - } - - if( classGroupUri != null && !classGroupUri.isEmpty() && group == null ){ - /*This could be for two reasons: one is that the classgroup doesn't exist - * The other is that there are no individuals in any of the classgroup's classes */ - group = vreq.getWebappDaoFactory().getVClassGroupDao().getGroupByURI(classGroupUri); - if( group != null ){ - List vcgFullList = vreq.getWebappDaoFactory().getVClassGroupDao() - .getPublicGroupsWithVClasses(false, true, false); - for( VClassGroup vcg : vcgFullList ){ - if( classGroupUri.equals(vcg.getURI()) ){ - group = vcg; - break; - } - } - if( group == null ){ - log.error("Cannot get classgroup '" + classGroupUri + "'"); - return null; - }else{ - setAllClassCountsToZero(group); - } - }else{ - log.error("classgroup " + classGroupUri + " does not exist in the system"); - return null; - } - } - - return new VClassGroupTemplateModel(group); - } - - @Override - public String getType(){ - return PageDataGetterUtils.generateDataGetterTypeURI(ClassGroupPageData.class.getName()); - } - - //Get data servuice - @Override - public String getDataServiceUrl() { - return UrlBuilder.getUrl("/dataservice?getSolrIndividualsByVClass=1&vclassId="); - } - - - /** - * For processing of JSONObject - */ - //Currently empty, TODO: Review requirements - @Override - public JSONObject convertToJSON(Map dataMap, VitroRequest vreq) { - JSONObject rObj = null; - return rObj; - } - protected static void setAllClassCountsToZero(VClassGroup vcg){ - for(VClass vc : vcg){ - vc.setEntityCount(0); - } - } -} \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/IndividualsForClassesDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/IndividualsForClassesDataGetter.java deleted file mode 100644 index 902f8ca9d..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/IndividualsForClassesDataGetter.java +++ /dev/null @@ -1,316 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter; - -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletContext; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONObject; - -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.dao.PageDao; -import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; -import edu.cornell.mannlib.vitro.webapp.web.templatemodels.VClassGroupTemplateModel; - -/** - * This will pass these variables to the template: - * classGroupUri: uri of the classgroup associated with this page. - * vClassGroup: a data structure that is the classgroup associated with this page. - */ -public class IndividualsForClassesDataGetter implements PageDataGetter{ - private static final Log log = LogFactory.getLog(IndividualsForClassesDataGetter.class); - protected static String restrictClassesTemplateName = null; - @Override - public Map getData(ServletContext context, VitroRequest vreq, String pageUri, Map page ){ - this.setTemplateName(); - HashMap data = new HashMap(); - //This is the old technique of getting class intersections - PageDao pageDao = vreq.getWebappDaoFactory().getPageDao(); - Map classIntersectionsMap = getClassIntersectionsMap(pageDao, pageUri); - - try{ - List classes = retrieveClasses(context, classIntersectionsMap); - List restrictClasses = retrieveRestrictClasses(context, classIntersectionsMap); - log.debug("Retrieving classes for " + classes.toString() + " and restricting by " + restrictClasses.toString()); - processClassesAndRestrictions(vreq, context, data, classes, restrictClasses); - //Also add data service url - //Hardcoding for now, need a more dynamic way of doing this - data.put("dataServiceUrlIndividualsByVClass", this.getDataServiceUrl()); - //this is the class group associated with the data getter utilized for display on menu editing, not the custom one created - data.put("classGroupUri", pageDao.getClassGroupPage(pageUri)); - } catch(Exception ex) { - log.error("An error occurred retrieving Vclass Intersection individuals", ex); - } - - return data; - } - - protected void setTemplateName() { - this.restrictClassesTemplateName = "restricted"; - } - - protected Map getClassIntersectionsMap(PageDao pageDao, - String pageUri) { - // TODO Auto-generated method stub - return pageDao.getClassesAndRestrictionsForPage(pageUri); - } - - protected List retrieveClasses( - ServletContext context, Map classIntersectionsMap) { - List restrictClasses = (List) classIntersectionsMap.get("classes"); - return restrictClasses; - } - - protected List retrieveRestrictClasses( - ServletContext context, Map classIntersectionsMap) { - List restrictClasses = (List) classIntersectionsMap.get("restrictClasses"); - return restrictClasses; - } - - protected void processClassesAndRestrictions(VitroRequest vreq, ServletContext context, - HashMap data, List classes, List restrictClasses ) { - processClassesForDisplay(vreq, context, data, classes); - processRestrictionClasses(vreq, context, data, restrictClasses); - processIntersections(vreq, context, data); - - } - - - - //At this point, data specifices whether or not intersections included - private void processIntersections(VitroRequest vreq, - ServletContext context, HashMap data) { - VClassGroup classesGroup = (VClassGroup) data.get("vClassGroup"); - List vclassList = classesGroup.getVitroClassList(); - List restrictClasses = (List) data.get("restrictVClasses"); - //if there are restrict classes, then update counts - if(restrictClasses.size() > 0) { - log.debug("Restriction classes exist"); - List newVClassList = new ArrayList(); - //Iterate through vclasses and get updated counts, iterated and saved in same order as initially included - for(VClass v: vclassList) { - int oldCount = v.getEntityCount(); - //Making a copy so as to ensure we don't touch the values in the cache - VClass copyVClass = makeCopyVClass(v); - int count = retrieveCount(vreq, context, v, restrictClasses); - if(oldCount != count) { - log.debug("Old count was " + v.getEntityCount() + " and New count for " + v.getURI() + " is " + count); - copyVClass.setEntityCount(count); - } - newVClassList.add(copyVClass); - } - classesGroup.setVitroClassList(newVClassList); - //TODO: Do we need to do this again or will this already be reset? - data.put("vClassGroup", classesGroup); - } - } - - private VClass makeCopyVClass(VClass v) { - VClass copyVClass = new VClass(v.getURI()); - copyVClass.setLocalName(copyVClass.getLocalName()); - copyVClass.setDisplayRank(v.getDisplayRank()); - copyVClass.setName(v.getName()); - copyVClass.setNamespace(v.getNamespace()); - copyVClass.setEntityCount(v.getEntityCount()); - return copyVClass; - } - - //update class count based on restrict classes - private int retrieveCount(VitroRequest vreq, ServletContext context, VClass v, List restrictClasses) { - //Execute solr query that returns only count of individuals - log.debug("Entity count is " + v.getEntityCount()); - List classUris = new ArrayList(); - classUris.add(v.getURI()); - for(VClass r: restrictClasses) { - classUris.add(r.getURI()); - } - long count = PageDataGetterUtils.getIndividualCountForIntersection(vreq, context, classUris); - return new Long(count).intValue(); - - } - - private void processClassesForDisplay(VitroRequest vreq, ServletContext context, HashMap data, List classes) { - VClassGroup classesGroup = new VClassGroup(); - classesGroup.setURI("displayClasses"); - log.debug("Processing classes that will be displayed"); - List vClasses = new ArrayList(); - - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); - for(String classUri: classes) { - //Retrieve vclass from cache to get the count - VClass vclass = vcgc.getCachedVClass(classUri); - //if not found in cache, possibly due to not being in any class group - if(vclass == null) { - vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(classUri); - } - if(vclass != null) { - log.debug("VClass does exist for " + classUri + " and entity count is " + vclass.getEntityCount()); - vClasses.add(vclass); - } else { - log.debug("Vclass " + classUri + " does not exist in the cache"); - log.error("Error occurred, vclass does not exist for this uri " + classUri); - //Throw exception here - } - } - //Sort these classes - Collections.sort(vClasses); - log.debug("Sorting complete for V Classes"); - classesGroup.setVitroClassList(vClasses); - log.debug("Returning vitro class list in data for template"); - //Set vclass group - data.put("vClassGroup", classesGroup); - } - - private void processRestrictionClasses(VitroRequest vreq, ServletContext context, - HashMap data, List restrictClasses) { - try { - VClassGroup restrictClassesGroup = new VClassGroup(); - restrictClassesGroup.setURI("restrictClasses"); - - List restrictVClasses = new ArrayList(); - - List urlEncodedRestrictClasses = new ArrayList(); - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); - - if(restrictClasses.size() > 0) { - //classes for restriction are not displayed so don't need to include their class individual counts - for(String restrictClassUri: restrictClasses) { - //Also uses cache to remain consistent with process classes and also allow - //vclasses to be returned even if switched to display model, although - //uris used within display model editing and not vclass objects - VClass vclass = vcgc.getCachedVClass(restrictClassUri); - //if not found in cache, possibly due to not being in any class group - if(vclass == null) { - vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(restrictClassUri); - } - if(vclass != null) { - log.debug("Found restrict class and adding to list " + restrictClassUri); - restrictVClasses.add(vclass); - } else { - log.error("Error occurred, vclass does not exist for this uri " + restrictClassUri); - } - //Assuming utf-8? - urlEncodedRestrictClasses.add(URLEncoder.encode(restrictClassUri, "UTF-8")); - } - - restrictClassesGroup.setVitroClassList(restrictVClasses); - restrictClassesGroup.setIndividualCount(restrictVClasses.size()); - } else { - - } - String[] restrictClassesArray = new String[urlEncodedRestrictClasses.size()]; - restrictClassesArray = urlEncodedRestrictClasses.toArray(restrictClassesArray); - - //In case just want uris - log.debug("Variable name for including restriction classes " + getRestrictClassesTemplateName()); - data.put(getRestrictClassesTemplateName(), StringUtils.join(restrictClassesArray, ",")); - data.put("restrictVClasses", restrictVClasses); - //not sure if this is useful - data.put("restrictVClassGroup", restrictClassesGroup); - } catch(Exception ex) { - log.error("An error occurred in processing restriction classes ", ex); - } - } - - public static VClassGroupTemplateModel getClassGroup(String classGroupUri, ServletContext context, VitroRequest vreq){ - - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(vreq); - List vcgList = vcgc.getGroups(); - VClassGroup group = null; - for( VClassGroup vcg : vcgList){ - if( vcg.getURI() != null && vcg.getURI().equals(classGroupUri)){ - group = vcg; - break; - } - } - - if( classGroupUri != null && !classGroupUri.isEmpty() && group == null ){ - /*This could be for two reasons: one is that the classgroup doesn't exist - * The other is that there are no individuals in any of the classgroup's classes */ - group = vreq.getWebappDaoFactory().getVClassGroupDao().getGroupByURI(classGroupUri); - if( group != null ){ - List vcgFullList = vreq.getWebappDaoFactory().getVClassGroupDao() - .getPublicGroupsWithVClasses(false, true, false); - for( VClassGroup vcg : vcgFullList ){ - if( classGroupUri.equals(vcg.getURI()) ){ - group = vcg; - break; - } - } - if( group == null ){ - log.error("Cannot get classgroup '" + classGroupUri + "'"); - return null; - }else{ - setAllClassCountsToZero(group); - } - }else{ - log.error("classgroup " + classGroupUri + " does not exist in the system"); - return null; - } - } - - return new VClassGroupTemplateModel(group); - } - - @Override - public String getType(){ - return PageDataGetterUtils.generateDataGetterTypeURI(IndividualsForClassesDataGetter.class.getName()); - } - - //Get data servuice - @Override - public String getDataServiceUrl() { - return UrlBuilder.getUrl("/dataservice?getSolrIndividualsByVClasses=1&vclassId="); - } - /** - * For processig of JSONObject - */ - @Override - public JSONObject convertToJSON(Map map, VitroRequest vreq) { - JSONObject rObj = PageDataGetterUtils.processVclassResultsJSON(map, vreq, true); - return rObj; - } - - protected static void setAllClassCountsToZero(VClassGroup vcg){ - for(VClass vc : vcg){ - vc.setEntityCount(0); - } - } - - protected static String getAlphaParameter(VitroRequest request){ - return request.getParameter("alpha"); - } - - protected static int getPageParameter(VitroRequest request) { - String pageStr = request.getParameter("page"); - if( pageStr != null ){ - try{ - return Integer.parseInt(pageStr); - }catch(NumberFormatException nfe){ - log.debug("could not parse page parameter"); - return 1; - } - }else{ - return 1; - } - } - - //Get template parameter - private static String getRestrictClassesTemplateName() { - return restrictClassesTemplateName; - - } -} \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetter.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetter.java deleted file mode 100644 index 724ed0353..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetter.java +++ /dev/null @@ -1,27 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter; - -import java.util.Map; - -import javax.servlet.ServletContext; - -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; - -import org.json.JSONObject; - -public interface PageDataGetter{ - Map getData(ServletContext contect, VitroRequest vreq, String pageUri, Map page ); - - /** Gets the type that this class applies to */ - //This has been changed to return the class name for data getter used in menu management - String getType(); - - //get data service url based on data getter requirements - //Get data servuice - String getDataServiceUrl(); - - /**Convert data to JSONObject based on what's required for the data processing**/ - JSONObject convertToJSON(Map map, VitroRequest vreq); -} diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java deleted file mode 100644 index 94dd8d378..000000000 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtils.java +++ /dev/null @@ -1,339 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ - -package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter; - -import java.net.URLEncoder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; - -import org.apache.commons.lang.StringUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.json.JSONArray; -import org.json.JSONObject; - -import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; -import edu.cornell.mannlib.vitro.webapp.beans.Individual; -import edu.cornell.mannlib.vitro.webapp.beans.VClass; -import edu.cornell.mannlib.vitro.webapp.beans.VClassGroup; -import edu.cornell.mannlib.vitro.webapp.controller.Controllers; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.IndividualListController.PageRecord; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; -import edu.cornell.mannlib.vitro.webapp.controller.json.JsonServlet; -import edu.cornell.mannlib.vitro.webapp.dao.VClassGroupsForRequest; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.VClassGroupCache; - -public class PageDataGetterUtils { - protected static final String DATA_GETTER_MAP = "pageTypeToDataGetterMap"; - private static final Log log = LogFactory.getLog(PageDataGetterUtils.class); - - public static Map getDataForPage(String pageUri, VitroRequest vreq, ServletContext context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - //Based on page type get the appropriate data getter - Map page = vreq.getWebappDaoFactory().getPageDao().getPage(pageUri); - - Map data = new HashMap(); - List dataGetters = getPageDataGetterObjects(vreq, pageUri); - for(PageDataGetter getter: dataGetters) { - try{ - Map moreData = null; - moreData = getAdditionalData(pageUri, getter.getType(), page, vreq, getter, context); - if( moreData != null) - data.putAll(moreData); - }catch(Throwable th){ - log.error(th,th); - } - } - return data; - } - - /** - * - * Convert data to JSON for page uri based on type and related datagetters - * TODO: How to handle different data getters? Will this replace json fields or add to them? - * @throws ClassNotFoundException - * @throws IllegalAccessException - * @throws InstantiationException - */ - public static JSONObject covertDataToJSONForPage(String pageUri, Map data, VitroRequest vreq, ServletContext context) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - //Get PageDataGetter types associated with pageUri - JSONObject rObj = null; - List dataGetters = getPageDataGetterObjects(vreq, pageUri); - for(PageDataGetter getter: dataGetters) { - JSONObject typeObj = null; - try{ - typeObj = getter.convertToJSON(data, vreq); - if( typeObj != null) { - //Copy over everything from this type Obj to - //TODO: Review how to handle duplicate keys, etc. - if(rObj != null) { - //For now, just nests as separate entry - rObj.put(getter.getType(), typeObj); - } else { - rObj = typeObj; - } - } - - } catch(Throwable th){ - log.error(th,th); - } - } - return rObj; - } - - public static Map getAdditionalData( - String pageUri, String dataGetterName, Map page, VitroRequest vreq, PageDataGetter getter, ServletContext context) { - if(dataGetterName == null || dataGetterName.isEmpty()) - return Collections.emptyMap(); - - - if( getter != null ){ - try{ - log.debug("Retrieve data for this data getter for " + pageUri); - return getter.getData(context, vreq, pageUri, page); - }catch(Throwable th){ - log.error(th,th); - return Collections.emptyMap(); - } - } else { - return Collections.emptyMap(); - } - } - - /*** - * For the page, get the actual Data Getters to be employed. - * @throws ClassNotFoundException - * @throws IllegalAccessException - * @throws InstantiationException - */ - public static List getPageDataGetterObjects(VitroRequest vreq, String pageUri) throws InstantiationException, IllegalAccessException, ClassNotFoundException { - List dataGetterObjects = new ArrayList(); - - List dataGetterClassNames = vreq.getWebappDaoFactory().getPageDao().getDataGetterClass(pageUri); - if( dataGetterClassNames == null ) - return Collections.emptyList(); - - for(String dgClassName: dataGetterClassNames) { - String className = getClassNameFromUri(dgClassName); - Class clz = Class.forName(className); - - if( PageDataGetter.class.isAssignableFrom(clz)){ - PageDataGetter pg = (PageDataGetter) clz.newInstance(); - dataGetterObjects.add(pg); - }// else skip if class does not implement PageDataGetter - } - - return dataGetterObjects; - } - - //Class URIs returned include "java:" and to instantiate object need to remove java: portion - public static String getClassNameFromUri(String dataGetterClassUri) { - if( !StringUtils.isEmpty(dataGetterClassUri) && dataGetterClassUri.contains("java:")) { - String[] splitArray = dataGetterClassUri.split("java:"); - if(splitArray.length > 1) { - return splitArray[1]; - } - } - return dataGetterClassUri; - } - - /** - * Get Individual count for Solr query for intersection of multiple classes - */ - public static long getIndividualCountForIntersection(VitroRequest vreq, ServletContext context, List classUris) { - return IndividualListController.getIndividualCount(classUris, vreq.getWebappDaoFactory().getIndividualDao(), context); - } - - - /** - * Process results related to VClass or vclasses. Handles both single and multiple vclasses being sent. - */ - public static JSONObject processVclassResultsJSON(Map map, VitroRequest vreq, boolean multipleVclasses) { - JSONObject rObj = new JSONObject(); - VClass vclass=null; - - try { - - // Properties from ontologies used by VIVO - should not be in vitro - DataProperty fNameDp = (new DataProperty()); - fNameDp.setURI("http://xmlns.com/foaf/0.1/firstName"); - DataProperty lNameDp = (new DataProperty()); - lNameDp.setURI("http://xmlns.com/foaf/0.1/lastName"); - DataProperty preferredTitleDp = (new DataProperty()); - preferredTitleDp.setURI("http://vivoweb.org/ontology/core#preferredTitle"); - - if( log.isDebugEnabled() ){ - @SuppressWarnings("unchecked") - Enumeration e = vreq.getParameterNames(); - while(e.hasMoreElements()){ - String name = e.nextElement(); - log.debug("parameter: " + name); - for( String value : vreq.getParameterValues(name) ){ - log.debug("value for " + name + ": '" + value + "'"); - } - } - } - - //need an unfiltered dao to get firstnames and lastnames - WebappDaoFactory fullWdf = vreq.getUnfilteredWebappDaoFactory(); - - String[] vitroClassIdStr = vreq.getParameterValues("vclassId"); - if ( vitroClassIdStr != null && vitroClassIdStr.length > 0){ - for(String vclassId: vitroClassIdStr) { - vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassId); - if (vclass == null) { - log.error("Couldn't retrieve vclass "); - throw new Exception ("Class " + vclassId + " not found"); - } - } - }else{ - log.error("parameter vclassId URI parameter expected "); - throw new Exception("parameter vclassId URI parameter expected "); - } - List vclassIds = Arrays.asList(vitroClassIdStr); - //if single vclass expected, then include vclass. This relates to what the expected behavior is, not size of list - if(!multipleVclasses) { - //currently used for ClassGroupPage - rObj.put("vclass", - new JSONObject().put("URI",vclass.getURI()) - .put("name",vclass.getName())); - } else { - //For now, utilize very last VClass (assume that that is the one to be employed) - //TODO: Find more general way of dealing with this - //put multiple ones in? - if(vclassIds.size() > 0) { - int numberVClasses = vclassIds.size(); - vclass = vreq.getWebappDaoFactory().getVClassDao().getVClassByURI(vclassIds.get(numberVClasses - 1)); - rObj.put("vclass", new JSONObject().put("URI",vclass.getURI()) - .put("name",vclass.getName())); - } - // rObj.put("vclasses", new JSONObject().put("URIs",vitroClassIdStr) - // .put("name",vclass.getName())); - } - if (vclass != null) { - - rObj.put("totalCount", map.get("totalCount")); - rObj.put("alpha", map.get("alpha")); - - List inds = (List)map.get("entities"); - log.debug("Number of individuals returned from request: " + inds.size()); - JSONArray jInds = new JSONArray(); - for(Individual ind : inds ){ - JSONObject jo = new JSONObject(); - jo.put("URI", ind.getURI()); - jo.put("label",ind.getRdfsLabel()); - jo.put("name",ind.getName()); - jo.put("thumbUrl", ind.getThumbUrl()); - jo.put("imageUrl", ind.getImageUrl()); - jo.put("profileUrl", UrlBuilder.getIndividualProfileUrl(ind, vreq)); - - jo.put("mostSpecificTypes", JsonServlet.getMostSpecificTypes(ind,fullWdf)); - jo.put("preferredTitle", JsonServlet.getDataPropertyValue(ind, preferredTitleDp, fullWdf)); - - jInds.put(jo); - } - rObj.put("individuals", jInds); - - JSONArray wpages = new JSONArray(); - //Made sure that PageRecord here is SolrIndividualListController not IndividualListController - List pages = (List)map.get("pages"); - for( PageRecord pr: pages ){ - JSONObject p = new JSONObject(); - p.put("text", pr.text); - p.put("param", pr.param); - p.put("index", pr.index); - wpages.put( p ); - } - rObj.put("pages",wpages); - - JSONArray jletters = new JSONArray(); - List letters = Controllers.getLetters(); - for( String s : letters){ - JSONObject jo = new JSONObject(); - jo.put("text", s); - jo.put("param", "alpha=" + URLEncoder.encode(s, "UTF-8")); - jletters.put( jo ); - } - rObj.put("letters", jletters); - } - } catch(Exception ex) { - log.error("Error occurred in processing JSON object", ex); - } - return rObj; - } - - /* - * Copied from JSONServlet as expect this to be related to VitroClassGroup - */ - public static JSONObject processVClassGroupJSON(VitroRequest vreq, ServletContext context, VClassGroup vcg) { - JSONObject map = new JSONObject(); - try { - ArrayList classes = new ArrayList(vcg.size()); - for( VClass vc : vcg){ - JSONObject vcObj = new JSONObject(); - vcObj.put("name", vc.getName()); - vcObj.put("URI", vc.getURI()); - vcObj.put("entityCount", vc.getEntityCount()); - classes.add(vcObj); - } - map.put("classes", classes); - map.put("classGroupName", vcg.getPublicName()); - map.put("classGroupUri", vcg.getURI()); - - } catch(Exception ex) { - log.error("Error occurred in processing VClass group ", ex); - } - return map; - } - - - //Get All VClass Groups information - //Used within menu management and processing - //TODO: Check if more appropriate location possible - public static List> getClassGroups(HttpServletRequest req) { - //Wanted this to be - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(req); - List vcgList = vcgc.getGroups(); - //For now encoding as hashmap with label and URI as trying to retrieve class group - //results in errors for some reason - List> classGroups = new ArrayList>(); - for(VClassGroup vcg: vcgList) { - HashMap hs = new HashMap(); - hs.put("publicName", vcg.getPublicName()); - hs.put("URI", vcg.getURI()); - classGroups.add(hs); - } - return classGroups; - } - - //Return data getter type to be employed in display model - public static String generateDataGetterTypeURI(String dataGetterClassName) { - return "java:" + dataGetterClassName; - } - - //TODO: Check whether this needs to be put here or elsewhere, as this is data getter specific - //with respect to class groups - //Need to use VClassGroupCache to retrieve class group information - this is the information returned from "for class group" - public static void getClassGroupForDataGetter(HttpServletRequest req, Map pageData, Map templateData) { - //Get the class group from VClassGroup, this is the same as the class group for the class group page data getter - //and the associated class group (not custom) for individuals datagetter - String classGroupUri = (String) pageData.get("classGroupUri"); - VClassGroupsForRequest vcgc = VClassGroupCache.getVClassGroups(req); - VClassGroup group = vcgc.getGroup(classGroupUri); - - templateData.put("classGroup", group); - templateData.put("associatedPage", group.getPublicName()); - templateData.put("associatedPageURI", group.getURI()); - } - -} \ No newline at end of file diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java index d12f5c0b7..fac33222c 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/directives/IndividualShortViewDirective.java @@ -77,10 +77,10 @@ public class IndividualShortViewDirective extends BaseTemplateDirectiveModel { private void renderShortView(Individual individual, ShortViewContext svContext) { Environment env = Environment.getCurrentEnvironment(); + HttpServletRequest request = (HttpServletRequest) env + .getCustomAttribute("request"); + ServletContext ctx = request.getSession().getServletContext(); - ServletContext ctx = (ServletContext) env.getCustomAttribute("context"); - VitroRequest vreq = new VitroRequest( - (HttpServletRequest) env.getCustomAttribute("request")); ShortViewService svs = ShortViewServiceSetup.getService(ctx); if (svs == null) { log.warn("ShortViewService was not initialized properly."); @@ -88,7 +88,7 @@ public class IndividualShortViewDirective extends BaseTemplateDirectiveModel { } TemplateAndSupplementalData svInfo = svs.getShortViewInfo(individual, - svContext, vreq); + svContext, new VitroRequest(request)); ObjectWrapper objectWrapper = env.getConfiguration().getObjectWrapper(); diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java index f5036463c..b70c24818 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/DataPropertyTemplateModel.java @@ -5,8 +5,6 @@ package edu.cornell.mannlib.vitro.webapp.web.templatemodels.individual; import java.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; @@ -21,13 +19,12 @@ import edu.cornell.mannlib.vitro.webapp.beans.DataProperty; import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; import edu.cornell.mannlib.vitro.webapp.dao.DataPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; -import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.DataPropertyListConfig; import freemarker.cache.TemplateLoader; @@ -136,7 +133,7 @@ public class DataPropertyTemplateModel extends PropertyTemplateModel { } protected TemplateLoader getFreemarkerTemplateLoader() { - return FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader(); + return FreemarkerConfiguration.getConfig(vreq).getTemplateLoader(); } @Override diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java index 49e36d284..701ad0320 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/templatemodels/individual/ObjectPropertyTemplateModel.java @@ -22,12 +22,12 @@ import edu.cornell.mannlib.vitro.webapp.beans.Individual; import edu.cornell.mannlib.vitro.webapp.beans.ObjectProperty; import edu.cornell.mannlib.vitro.webapp.beans.Property; import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerConfigurationLoader; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.ParamMap; import edu.cornell.mannlib.vitro.webapp.controller.freemarker.UrlBuilder.Route; import edu.cornell.mannlib.vitro.webapp.dao.ObjectPropertyStatementDao; import edu.cornell.mannlib.vitro.webapp.dao.VitroVocabulary; +import edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.InvalidConfigurationException; import edu.cornell.mannlib.vitro.webapp.web.templatemodels.customlistview.PropertyListConfig; import freemarker.cache.TemplateLoader; @@ -152,7 +152,7 @@ public abstract class ObjectPropertyTemplateModel extends PropertyTemplateModel * This will do for now. */ protected TemplateLoader getFreemarkerTemplateLoader() { - return FreemarkerConfigurationLoader.getConfig(vreq).getTemplateLoader(); + return FreemarkerConfiguration.getConfig(vreq).getTemplateLoader(); } protected List> getStatementData() { diff --git a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java index e7e2741d5..9f82c1910 100644 --- a/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java +++ b/webapp/src/edu/cornell/mannlib/vitro/webapp/web/widgets/Widget.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.Map; import javax.servlet.ServletContext; -import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import org.apache.commons.logging.Log; @@ -57,7 +56,7 @@ public abstract class Widget { public String doMarkup(Environment env, Map params) { HttpServletRequest request = (HttpServletRequest) env.getCustomAttribute("request"); - ServletContext context = (ServletContext) env.getCustomAttribute("context"); + ServletContext context = request.getSession().getServletContext(); WidgetTemplateValues values = null; @@ -120,15 +119,7 @@ public abstract class Widget { // We need to give each widget macro template a unique key in the StringTemplateLoader, and check // if it's already there or else add it. Leave this for later. Template template = new Template("widget", new StringReader(templateString), env.getConfiguration()); - - // JB KLUGE The widget is processed in its own environment, which doesn't include these custom attributes. - // JB KLUGE Put them in. - Environment widgetEnv = template.createProcessingEnvironment(map, out); - ServletRequest request = (ServletRequest) env.getCustomAttribute("request"); - widgetEnv.setCustomAttribute("request", request); - widgetEnv.setCustomAttribute("context", env.getCustomAttribute("context")); - widgetEnv.setLocale(request.getLocale()); - widgetEnv.process(); + template.process(map, out); } catch (Exception e) { log.error("Could not process widget " + widgetName, e); } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java index 2a2314999..aef00d0ac 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/freemarker/ImageUploaderThumbnailerTester_2.java @@ -23,7 +23,6 @@ import java.util.Set; import javax.media.jai.JAI; import javax.media.jai.RenderedOp; import javax.media.jai.operator.StreamDescriptor; -import javax.media.jai.widget.ImageCanvas; import javax.swing.BorderFactory; import javax.swing.JPanel; @@ -107,7 +106,7 @@ public class ImageUploaderThumbnailerTester_2 extends Frame { JPanel p = new JPanel(); p.setLayout(new BorderLayout()); p.add("South", l); - p.add("Center", new ImageCanvas(image)); + p.add("Center", new javax.media.jai.widget.ImageCanvas(image)); p.setBackground(new Color(0xFFFFFF)); p.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java index 3b6e103be..9128b6f0e 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/controller/json/JsonServletTest.java @@ -192,6 +192,7 @@ public class JsonServletTest extends AbstractTestClass { public void individualsByClassNoIndividuals() throws ServletException, IOException { setLoggerLevel(JsonServlet.class, Level.FATAL); + setLoggerLevel(ModelAccess.class, Level.ERROR); String vclassId = "http://myVclass"; vcDao.setVClass(vclassId, new VClass(vclassId)); req.addParameter(GET_SOLR_INDIVIDUALS_BY_VCLASS, "true"); diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java index 3c03fd856..a788e179e 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/DataGetterUtilsTest.java @@ -67,15 +67,6 @@ public class DataGetterUtilsTest extends AbstractTestClass{ } - @Test - public void testNonPageDataGetter() throws IllegalArgumentException, SecurityException, InstantiationException, IllegalAccessException, ClassNotFoundException, InvocationTargetException, NoSuchMethodException{ - DataGetter dg = DataGetterUtils.dataGetterForURI(vreq, displayModel,dataGetterX); - Assert.assertNull(dg); - - List dgList = - DataGetterUtils.getDataGettersForPage(vreq, displayModel, pageX); - Assert.assertNotNull(dgList); - Assert.assertTrue("List should be, it was not", dgList.size() == 0); - } + } diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/resources/dataGetterTest.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/resources/dataGetterTest.n3 index 4e1f95ad0..4c9ecc56c 100644 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/resources/dataGetterTest.n3 +++ b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/dataGetter/resources/dataGetterTest.n3 @@ -20,14 +20,5 @@ display:query1data display:saveToVar "people" . -### test of what happens with a PageDataGetter instead of a DataGetter ### - -display:pageX - a display:Page ; - display:title "A PageDataGetter, not a DataGetter" ; - display:urlMapping "/query2" ; - display:hasDataGetter display:pageDataGetterX . - -display:pageDataGetterX - a . + \ No newline at end of file diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtilsTest.java b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtilsTest.java deleted file mode 100644 index a6745102c..000000000 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/PageDataGetterUtilsTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* $This file is distributed under the terms of the license in /doc/license.txt$ */ -package edu.cornell.mannlib.vitro.webapp.utils.pageDataGetter; - -import java.io.InputStream; -import java.util.List; - -import org.apache.log4j.Level; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; - -import stubs.javax.servlet.http.HttpServletRequestStub; - -import com.hp.hpl.jena.ontology.OntModel; -import com.hp.hpl.jena.ontology.OntModelSpec; -import com.hp.hpl.jena.rdf.model.ModelFactory; -import com.hp.hpl.jena.rdf.model.impl.RDFDefaultErrorHandler; - -import edu.cornell.mannlib.vitro.testing.AbstractTestClass; -import edu.cornell.mannlib.vitro.webapp.controller.VitroRequest; -import edu.cornell.mannlib.vitro.webapp.dao.ModelAccess; -import edu.cornell.mannlib.vitro.webapp.dao.WebappDaoFactory; -import edu.cornell.mannlib.vitro.webapp.dao.jena.SimpleOntModelSelector; -import edu.cornell.mannlib.vitro.webapp.dao.jena.WebappDaoFactoryJena; - -public class PageDataGetterUtilsTest extends AbstractTestClass{ - OntModel displayModel; - WebappDaoFactory wdf; - - String pageURI = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#pageX"; - String pageURI_2 = "http://vitro.mannlib.cornell.edu/ontologies/display/1.1#SPARQLPage"; - - @Before - public void setUp() throws Exception { - // Suppress error logging. - setLoggerLevel(RDFDefaultErrorHandler.class, Level.OFF); - - OntModel model = ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM); - InputStream in = PageDataGetterUtilsTest.class.getResourceAsStream("resources/pageDataGetter.n3"); - model.read(in,"","N3"); - displayModel = ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM,model); - - SimpleOntModelSelector sos = new SimpleOntModelSelector( ModelFactory.createOntologyModel(OntModelSpec.OWL_DL_MEM)); - sos.setDisplayModel(displayModel); - - wdf = new WebappDaoFactoryJena(sos); - } - - @Test - public void testGetPageDataGetterObjects() throws Exception{ - VitroRequest vreq = new VitroRequest( new HttpServletRequestStub() ); - ModelAccess.on(vreq).setWebappDaoFactory(wdf); - - List pdgList = PageDataGetterUtils.getPageDataGetterObjects(vreq, pageURI); - Assert.assertNotNull(pdgList); - Assert.assertTrue("should have one PageDataGetter", pdgList.size() == 1); - } - - @Test - public void testGetNonPageDataGetterObjects() throws Exception{ - VitroRequest vreq = new VitroRequest( new HttpServletRequestStub() ); - ModelAccess.on(vreq).setWebappDaoFactory(wdf); - - List pdgList = PageDataGetterUtils.getPageDataGetterObjects(vreq, pageURI_2); - Assert.assertNotNull(pdgList); - Assert.assertTrue("should have no PageDataGetters", pdgList.size() == 0); - } -} diff --git a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/resources/pageDataGetter.n3 b/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/resources/pageDataGetter.n3 deleted file mode 100644 index f3ec2f4c0..000000000 --- a/webapp/test/edu/cornell/mannlib/vitro/webapp/utils/pageDataGetter/resources/pageDataGetter.n3 +++ /dev/null @@ -1,30 +0,0 @@ -# $This file is distributed under the terms of the license in /doc/license.txt$ - -@prefix owl: . -@prefix display: . -@prefix rdf: . -@prefix core: . -@prefix xsd: . - -### This file is for the test PageDataGetterUtilsTest.java - -display:SPARQLPage - a display:Page ; - display:title "TestQuery" ; - display:urlMapping "/query1" ; - display:hasDataGetter display:query1data . - -display:query1data - a ; - display:query "SELECT * WHERE { ?uri a } " ; - display:saveToVar "people" . - -display:pageX - a display:Page ; - display:title "A PageDataGetter, not a DataGetter" ; - display:urlMapping "/query2" ; - display:hasDataGetter display:pageDataGetterX . - -display:pageDataGetterX - a . - \ No newline at end of file diff --git a/webapp/test/stubs/javax/servlet/ServletContextStub.java b/webapp/test/stubs/javax/servlet/ServletContextStub.java index cc4e9ca32..46e592d60 100644 --- a/webapp/test/stubs/javax/servlet/ServletContextStub.java +++ b/webapp/test/stubs/javax/servlet/ServletContextStub.java @@ -200,6 +200,7 @@ public class ServletContextStub implements ServletContext { } @Override + @Deprecated public Servlet getServlet(String arg0) throws ServletException { throw new RuntimeException( "ServletContextStub.getServlet() not implemented."); @@ -213,6 +214,7 @@ public class ServletContextStub implements ServletContext { @Override @SuppressWarnings("rawtypes") + @Deprecated public Enumeration getServletNames() { throw new RuntimeException( "ServletContextStub.getServletNames() not implemented."); @@ -220,6 +222,7 @@ public class ServletContextStub implements ServletContext { @Override @SuppressWarnings("rawtypes") + @Deprecated public Enumeration getServlets() { throw new RuntimeException( "ServletContextStub.getServlets() not implemented."); @@ -231,6 +234,7 @@ public class ServletContextStub implements ServletContext { } @Override + @Deprecated public void log(Exception arg0, String arg1) { throw new RuntimeException("ServletContextStub.log() not implemented."); } diff --git a/webapp/test/stubs/javax/servlet/http/HttpServletRequestStub.java b/webapp/test/stubs/javax/servlet/http/HttpServletRequestStub.java index a35924ddf..d1b2c4dd0 100644 --- a/webapp/test/stubs/javax/servlet/http/HttpServletRequestStub.java +++ b/webapp/test/stubs/javax/servlet/http/HttpServletRequestStub.java @@ -60,8 +60,8 @@ public class HttpServletRequestStub implements HttpServletRequest { /** * Supply the request URL as a single URL. We will parse it on the - * assumption that the contextPath and the pathInfo are empty. - * Don't include a query string. Instead, set parameters. + * assumption that the contextPath and the pathInfo are empty. Don't include + * a query string. Instead, set parameters. */ public void setRequestUrl(URL url) { this.contextPath = ""; @@ -81,8 +81,7 @@ public class HttpServletRequestStub implements HttpServletRequest { /** * Supply the pieces of the request URL, so we can respond correctly when - * asked for a piece. - * Don't include a query string. Instead, set parameters. + * asked for a piece. Don't include a query string. Instead, set parameters. */ public void setRequestUrlByParts(String shemeHostPort, String contextPath, String servletPath, String pathInfo) { @@ -102,8 +101,9 @@ public class HttpServletRequestStub implements HttpServletRequest { } this.servletPath = servletPath; - this.requestUri = contextPath + servletPath + ((pathInfo == null) ? "" : pathInfo); - + this.requestUri = contextPath + servletPath + + ((pathInfo == null) ? "" : pathInfo); + if (shemeHostPort == null) { throw new NullPointerException("shemeHostPort may not be null."); } @@ -183,21 +183,21 @@ public class HttpServletRequestStub implements HttpServletRequest { public String getServletPath() { return servletPath; } - + @Override public String getPathInfo() { return pathInfo; } - + @Override public String getQueryString() { if (parameters.isEmpty()) { return null; } - + String qs = ""; - for (String key:parameters.keySet()) { - for (String value: parameters.get(key)) { + for (String key : parameters.keySet()) { + for (String value : parameters.get(key)) { qs += "&" + key + "=" + URLEncoder.encode(value); } } @@ -302,167 +302,202 @@ public class HttpServletRequestStub implements HttpServletRequest { // Un-implemented methods // ---------------------------------------------------------------------- + @Override public String getAuthType() { throw new RuntimeException( "HttpServletRequestStub.getAuthType() not implemented."); } + @Override public Cookie[] getCookies() { throw new RuntimeException( "HttpServletRequestStub.getCookies() not implemented."); } + @Override public long getDateHeader(String arg0) { throw new RuntimeException( "HttpServletRequestStub.getDateHeader() not implemented."); } + @Override public int getIntHeader(String arg0) { throw new RuntimeException( "HttpServletRequestStub.getIntHeader() not implemented."); } + @Override public String getPathTranslated() { throw new RuntimeException( "HttpServletRequestStub.getPathTranslated() not implemented."); } + @Override public String getRemoteUser() { throw new RuntimeException( "HttpServletRequestStub.getRemoteUser() not implemented."); } + @Override public String getRequestedSessionId() { throw new RuntimeException( "HttpServletRequestStub.getRequestedSessionId() not implemented."); } + @Override public Principal getUserPrincipal() { throw new RuntimeException( "HttpServletRequestStub.getUserPrincipal() not implemented."); } + @Override public boolean isRequestedSessionIdFromCookie() { throw new RuntimeException( "HttpServletRequestStub.isRequestedSessionIdFromCookie() not implemented."); } + @Override public boolean isRequestedSessionIdFromURL() { throw new RuntimeException( "HttpServletRequestStub.isRequestedSessionIdFromURL() not implemented."); } + @Override + @Deprecated public boolean isRequestedSessionIdFromUrl() { throw new RuntimeException( "HttpServletRequestStub.isRequestedSessionIdFromUrl() not implemented."); } + @Override public boolean isRequestedSessionIdValid() { throw new RuntimeException( "HttpServletRequestStub.isRequestedSessionIdValid() not implemented."); } + @Override public boolean isUserInRole(String arg0) { throw new RuntimeException( "HttpServletRequestStub.isUserInRole() not implemented."); } + @Override public String getCharacterEncoding() { throw new RuntimeException( "HttpServletRequestStub.getCharacterEncoding() not implemented."); } + @Override public int getContentLength() { throw new RuntimeException( "HttpServletRequestStub.getContentLength() not implemented."); } + @Override public String getContentType() { throw new RuntimeException( "HttpServletRequestStub.getContentType() not implemented."); } + @Override public ServletInputStream getInputStream() throws IOException { throw new RuntimeException( "HttpServletRequestStub.getInputStream() not implemented."); } + @Override public String getLocalAddr() { throw new RuntimeException( "HttpServletRequestStub.getLocalAddr() not implemented."); } + @Override public String getLocalName() { throw new RuntimeException( "HttpServletRequestStub.getLocalName() not implemented."); } + @Override public int getLocalPort() { throw new RuntimeException( "HttpServletRequestStub.getLocalPort() not implemented."); } + @Override public Locale getLocale() { throw new RuntimeException( "HttpServletRequestStub.getLocale() not implemented."); } + @Override @SuppressWarnings("rawtypes") public Enumeration getLocales() { throw new RuntimeException( "HttpServletRequestStub.getLocales() not implemented."); } + @Override public String getProtocol() { throw new RuntimeException( "HttpServletRequestStub.getProtocol() not implemented."); } + @Override public BufferedReader getReader() throws IOException { throw new RuntimeException( "HttpServletRequestStub.getReader() not implemented."); } + @Override + @Deprecated public String getRealPath(String arg0) { throw new RuntimeException( "HttpServletRequestStub.getRealPath() not implemented."); } + @Override public String getRemoteHost() { throw new RuntimeException( "HttpServletRequestStub.getRemoteHost() not implemented."); } + @Override public int getRemotePort() { throw new RuntimeException( "HttpServletRequestStub.getRemotePort() not implemented."); } + @Override public RequestDispatcher getRequestDispatcher(String arg0) { throw new RuntimeException( "HttpServletRequestStub.getRequestDispatcher() not implemented."); } + @Override public String getScheme() { throw new RuntimeException( "HttpServletRequestStub.getScheme() not implemented."); } + @Override public String getServerName() { throw new RuntimeException( "HttpServletRequestStub.getServerName() not implemented."); } + @Override public int getServerPort() { throw new RuntimeException( "HttpServletRequestStub.getServerPort() not implemented."); } + @Override public boolean isSecure() { throw new RuntimeException( "HttpServletRequestStub.isSecure() not implemented."); } + @Override public void setCharacterEncoding(String arg0) throws UnsupportedEncodingException { throw new RuntimeException( diff --git a/webapp/test/stubs/javax/servlet/http/HttpSessionStub.java b/webapp/test/stubs/javax/servlet/http/HttpSessionStub.java index cd71d4cef..7cc87b26b 100644 --- a/webapp/test/stubs/javax/servlet/http/HttpSessionStub.java +++ b/webapp/test/stubs/javax/servlet/http/HttpSessionStub.java @@ -126,12 +126,14 @@ public class HttpSessionStub implements HttpSession { } @Override + @Deprecated public Object getValue(String arg0) { throw new RuntimeException( "HttpSessionStub.getValue() not implemented."); } @Override + @Deprecated public String[] getValueNames() { throw new RuntimeException( "HttpSessionStub.getValueNames() not implemented."); @@ -149,12 +151,14 @@ public class HttpSessionStub implements HttpSession { } @Override + @Deprecated public void putValue(String arg0, Object arg1) { throw new RuntimeException( "HttpSessionStub.putValue() not implemented."); } @Override + @Deprecated public void removeValue(String arg0) { throw new RuntimeException( "HttpSessionStub.removeValue() not implemented."); diff --git a/webapp/web/WEB-INF/resources/shortview_config.n3 b/webapp/web/WEB-INF/resources/shortview_config.n3 index ace0ff7ad..c4c2abfe4 100644 --- a/webapp/web/WEB-INF/resources/shortview_config.n3 +++ b/webapp/web/WEB-INF/resources/shortview_config.n3 @@ -9,5 +9,5 @@ # Ontology is complete. # # Find out how to use this file at -# https://sourceforge.net/apps/mediawiki/vivo/index.php?title=Using_Short_Views_in_Release_1.5 +# https://wiki.duraspace.org/display/VIVO/Using+Short+Views+in+Release+1.5 # diff --git a/webapp/web/WEB-INF/resources/startup_listeners.txt b/webapp/web/WEB-INF/resources/startup_listeners.txt index d7e47e9d9..7f83a702a 100644 --- a/webapp/web/WEB-INF/resources/startup_listeners.txt +++ b/webapp/web/WEB-INF/resources/startup_listeners.txt @@ -65,6 +65,7 @@ edu.cornell.mannlib.vitro.webapp.i18n.selection.LocaleSelectionSetup edu.cornell.mannlib.vitro.webapp.search.solr.SolrSetup edu.cornell.mannlib.vitro.webapp.controller.freemarker.FreemarkerSetup +edu.cornell.mannlib.vitro.webapp.freemarker.config.FreemarkerConfiguration$Setup # On shutdown, this will kill the background thread started by Apache Commons File Upload org.apache.commons.fileupload.servlet.FileCleanerCleanup diff --git a/webapp/web/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js b/webapp/web/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js index 1489a0038..d02e8e8d0 100644 --- a/webapp/web/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js +++ b/webapp/web/templates/freemarker/edit/forms/js/customFormWithAutocomplete.js @@ -55,7 +55,12 @@ var customForm = { // the verify popup window. Although there could be multiple verifyMatch objects // selecting one and binding the event works for all of them this.verifyMatch = this.form.find('.verifyMatch'); - + this.defaultAcType = ""; // will be set in setType() first time through + this.templateDefinedAcTypes = false; + if ( this.acTypes != undefined ) { + this.templateDefinedAcTypes = true; + } + // find all the acSelector input elements this.acSelectors = [] ; @@ -86,7 +91,7 @@ var customForm = { // Used with the cancel link. If the user cancels after a type selection, this check // ensures that any a/c fields (besides the one associated with the type) will be reset this.clearAcSelections = false; - + }, // Set up the form on page load @@ -126,6 +131,10 @@ var customForm = { this.initFormView(); + // Set the initial autocomplete help text in the acSelector fields. + $.each(this.acSelectors, function() { + customForm.addAcHelpText($(this)); + }); }, initFormView: function() { @@ -288,7 +297,7 @@ var customForm = { //to the filtering list this.getAcFilterForIndividuals(); this.acCache = {}; - + $(selectedObj).autocomplete({ minLength: 3, source: function(request, response) { @@ -312,8 +321,9 @@ var customForm = { }, complete: function(xhr, status) { // Not sure why, but we need an explicit json parse here. - var results = $.parseJSON(xhr.responseText), + var results = $.parseJSON(xhr.responseText), filteredResults = customForm.filterAcResults(results); + customForm.acCache[request.term] = filteredResults; response(filteredResults); } @@ -321,6 +331,9 @@ var customForm = { }, select: function(event, ui) { customForm.showAutocompleteSelection(ui.item.label, ui.item.uri, $(selectedObj)); + if ( $(selectedObj).attr('acGroupName') == customForm.typeSelector.attr('acGroupName') ) { + customForm.typeSelector.val(ui.item.msType); + } } }); }, @@ -420,17 +433,24 @@ var customForm = { // provides a way to monitor selection in other js files, e.g. to hide fields upon selection $acDiv.addClass("userSelected"); - // If the form has a type selector, add type name to label in add mode. In edit mode, use typeSelectorSpan - // html. The second case is an "else if" and not an else because the template may not be passing the label - // to the acSelection macro or it may not be using the macro at all and the label is hard-coded in the html. - if ( this.typeSelector.length && ($acDiv.attr('acGroupName') == this.typeSelector.attr('acGroupName')) ) { - $acDiv.find('label').html('Selected ' + this.typeName + ':'); - } - else if ( this.typeSelectorSpan.html() && ($acDiv.attr('acGroupName') == this.typeSelectorInput.attr('acGroupName')) ) { - $acDiv.find('label').html('Selected ' + this.typeSelectorSpan.html() + ':'); - } - else if ( $acDiv.find('label').html() == '' ) { - $acDiv.find('label').html('Selected ' + this.multipleTypeNames[$(selectedObj).attr('acGroupName')] + ':'); + // If the form has a type selector, add type name to label in add mode. In edit mode, + // use typeSelectorSpan html. The second case is an "else if" and not an else because + // the template may not be passing the label to the acSelection macro or it may not be + // using the macro at all and the label is hard-coded in the html. + // ** With release 1.6 and display of all fields, more labels are hard-coded in html. + // ** So check if there's a label before doing anything else. + + if ( $acDiv.find('label').html().length === 0 ) { + + if ( this.typeSelector.length && ($acDiv.attr('acGroupName') == this.typeSelector.attr('acGroupName')) ) { + $acDiv.find('label').html('Selected ' + this.typeName + ':'); + } + else if ( this.typeSelectorSpan.html() && ($acDiv.attr('acGroupName') == this.typeSelectorInput.attr('acGroupName')) ) { + $acDiv.find('label').html('Selected ' + this.typeSelectorSpan.html() + ':'); + } + else if ( $acDiv.find('label').html() == '' ) { + $acDiv.find('label').html('Selected ' + this.multipleTypeNames[$(selectedObj).attr('acGroupName')] + ':'); + } } $acDiv.show(); @@ -447,7 +467,6 @@ var customForm = { //On initialization in this mode, submit button is disabled this.enableSubmit(); } - }, undoAutocompleteSelection: function(selectedObj) { @@ -482,11 +501,12 @@ var customForm = { $acSelector = customForm.getAcSelector($checkSelection); $acSelector.parent('p').show(); } - }); - } + }); + } } else { $acSelectionObj = $(selectedObj); + customForm.typeSelector.val(''); } $acSelector = this.getAcSelector($acSelectionObj); @@ -530,10 +550,9 @@ var customForm = { // Note: we still need this in edit mode, to set the text values. setType: function() { var selectedType; - // If there's no type selector, these values have been specified in customFormData, // and will not change over the life of the form. - if (!this.typeSelector.length) { + if (!this.typeSelector.length) { if ( this.editMode == 'edit' && (this.typeSelectorSpan.html() != null && this.typeSelectorInput.val() != null) ) { this.typeName = this.typeSelectorSpan.html(); this.acTypes[this.typeSelectorInput.attr('acGroupName')] = this.typeSelectorInput.val(); @@ -542,7 +561,11 @@ var customForm = { } selectedType = this.typeSelector.find(':selected'); - var acTypeKey = this.typeSelector.attr('acGroupName'); + var acTypeKey = this.typeSelector.attr('acGroupName'); + + if ( this.templateDefinedAcTypes && !this.defaultAcType.length ) { + this.defaultAcType = this.acTypes[acTypeKey]; + } if (selectedType.val().length) { this.acTypes[acTypeKey] = selectedType.val(); this.typeName = selectedType.html(); @@ -551,15 +574,20 @@ var customForm = { $acSelect.find('label').html( customForm.selectedString + ' ' + this.typeName + ':'); } } - // reset to empty values; may not need + // reset to empty values; else { - delete this.acTypes[acTypeKey]; - this.typeName = ''; + if ( this.templateDefinedAcTypes ) { + this.acTypes[acTypeKey] = this.defaultAcType; + } + else { + this.acTypes = new Object(); + } + this.typeName = this.defaultTypeName; } }, // Set field labels based on type selection. Although these won't change in edit - // mode, it's easier to specify the text here than in the jsp. + // mode, it's easier to specify the text here than in the ftl. setLabels: function() { var typeName = this.getTypeNameForLabels(); @@ -575,10 +603,20 @@ var customForm = { // or in repair mode in a two-step form with no type selected. Use the default type // name specified in the form data. if ( !selectedObj || !this.hasMultipleTypeNames ) { - return this.acTypes ? this.typeName : this.capitalize(this.defaultTypeName); + if ( this.acTypes && this.typeName ) { + return this.typeName; + } + else { + return this.capitalize(this.defaultTypeName); + } } else if ( selectedObj && ( $(selectedObj).attr('acGroupName') == this.typeSelector.attr('acGroupName') ) ) { - return this.acTypes ? this.typeName : this.capitalize(this.defaultTypeName); + if ( this.acTypes && this.typeName ) { + return this.typeName; + } + else { + return this.capitalize(this.defaultTypeName); + } } else { var name = customForm.multipleTypeNames[$(selectedObj).attr('id')];