/* * ControlledVocabularyTag.java * * Version: $Revision: 3705 $ * * Date: $Date: 2009-04-11 17:02:24 +0000 (Sat, 11 Apr 2009) $ * * Copyright (c) 2002, Hewlett-Packard Company and Massachusetts Institute of * Technology. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. - Redistributions in binary * form must reproduce the above copyright notice, this list of conditions and * the following disclaimer in the documentation and/or other materials provided * with the distribution. - Neither the name of the Hewlett-Packard Company nor * the name of the Massachusetts Institute of Technology nor the names of their * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package org.dspace.app.webui.jsptag; import java.io.File; import java.io.FilenameFilter; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import javax.servlet.http.HttpServletRequest; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import org.apache.log4j.Logger; import org.dspace.app.webui.util.XMLUtil; import org.dspace.core.ConfigurationManager; import org.w3c.dom.Document; /** * A Tag to load and display controlled vocabularies * * @author Miguel Ferreira * @version $Revision: 3705 $ * */ public class ControlledVocabularyTag extends TagSupport { // path to the jsp that outputs the results of this tag private static final String CONTROLLEDVOCABULARY_JSPTAG = "/controlledvocabulary/controlledvocabularyTag.jsp"; // the log private static Logger log = Logger.getLogger(ControlledVocabularyTag.class); // a tag attribute that contains the words used to trim the vocabulary tree private String filter; // a tag attribute that activates multiple selection of vocabulary terms private boolean allowMultipleSelection; // a tag attribute that specifies the vocabulary to be displayed private String vocabulary; // an hashtable containing all the loaded vocabularies public Hashtable controlledVocabularies; /** * Process tag */ public int doStartTag() throws JspException { HttpServletRequest request = (HttpServletRequest) pageContext .getRequest(); String vocabulariesPath = ConfigurationManager .getProperty("dspace.dir") + "/config/controlled-vocabularies/"; String addonBaseDirectory = pageContext.getServletContext() .getRealPath("") + "/controlledvocabulary/"; String vocabularyPrunningXSLT = addonBaseDirectory + "vocabularyprune.xsl"; String controlledVocabulary2HtmlXSLT = addonBaseDirectory + "vocabulary2html.xsl"; // Load vocabularies on startup controlledVocabularies = (Hashtable) pageContext.getServletContext() .getAttribute("controlledvocabulary.controlledVocabularies"); if (controlledVocabularies == null) { controlledVocabularies = loadControlledVocabularies(vocabulariesPath); pageContext.getServletContext().setAttribute( "controlledvocabulary.controlledVocabularies", controlledVocabularies); } try { Hashtable prunnedVocabularies = needsFiltering() ? filterVocabularies( controlledVocabularies, vocabularyPrunningXSLT) : controlledVocabularies; String html = ""; if (vocabulary != null && !vocabulary.equals("")) { html = renderVocabularyAsHTML((Document) prunnedVocabularies .get(vocabulary + ".xml"), controlledVocabulary2HtmlXSLT, isAllowMultipleSelection(), request.getContextPath()); } else { html = renderVocabulariesAsHTML(prunnedVocabularies, controlledVocabulary2HtmlXSLT, isAllowMultipleSelection(), request.getContextPath()); } request.getSession().setAttribute( "controlledvocabulary.vocabularyHTML", html); pageContext.include(CONTROLLEDVOCABULARY_JSPTAG); } catch (Exception e) { log.warn("Exception", e); } return SKIP_BODY; } /** * End processing tag */ public int doEndTag() { return EVAL_PAGE; } /** * Do we gave a filter to apply to the controlled vocabularies? * * @return true if a filter was provided. */ private boolean needsFiltering() { return getFilter() != null && getFilter().length() > 0; } /** * Converts a XML Vocabulary to a HTML tree * * @param vocabularies * A hashtable with all the XML taxonomies/vocabularies loaded as * values * @param xslt * the filename of the stylesheet to apply the XML taxonomies * @param allowMultipleSelection * include checkboxes next to the taxonomy terms * @param contextPath * The context path * @return the HTML that represents the vocabularies */ private String renderVocabulariesAsHTML(Hashtable vocabularies, String xslt, boolean allowMultipleSelection, String contextPath) { String result = ""; Iterator iter = vocabularies.values().iterator(); while (iter.hasNext()) { Document controlledVocabularyXML = (Document) iter.next(); result += renderVocabularyAsHTML(controlledVocabularyXML, xslt, allowMultipleSelection, contextPath); } return result; } /** * Applies a filter to the vocabularies, i.e. it prunes the trees by * removing all the branches that do not contain the words in the filter. * * @param vocabularies * A hashtable with all the XML taxonomies/vocabularies loaded as * values * @param vocabularyPrunningXSLT * the filename of the stylesheet that trimms the taxonomies * @return An hashtable with all the filtered vocabularies */ private Hashtable filterVocabularies(Hashtable vocabularies, String vocabularyPrunningXSLT) { Hashtable prunnedVocabularies = new Hashtable(); Enumeration enumeration = vocabularies.keys(); while (enumeration.hasMoreElements()) { String controlledVocabularyKey = (String) enumeration.nextElement(); Document controlledVocabulary = (Document) vocabularies .get(controlledVocabularyKey); prunnedVocabularies.put(controlledVocabularyKey, filterVocabulary( controlledVocabulary, vocabularyPrunningXSLT, getFilter())); } return prunnedVocabularies; } /** * Renders a taxonomy as HTML by applying a stylesheet. * * @param vocabulary * The XML document representing a taxonomy * @param controlledVocabulary2HtmlXSLT * The filename of the stylesheet that converts the taxonomy to * HTML * @param allowMultipleSelection * include checkboxes next to the taxonomy terms * @param contextPath * The context path * @return the provided taxonomy as HTML. */ public String renderVocabularyAsHTML(Document vocabulary, String controlledVocabulary2HtmlXSLT, boolean allowMultipleSelection, String contextPath) { if (vocabulary == null) return ""; String result = ""; try { Hashtable parameters = new Hashtable(); parameters.put("allowMultipleSelection", allowMultipleSelection ? "yes" : "no"); parameters.put("contextPath", contextPath); result = XMLUtil.transformDocumentAsString(vocabulary, parameters, controlledVocabulary2HtmlXSLT); } catch (Exception e) { e.printStackTrace(); } return result; } /** * Applies a filter to the provided vocabulary, i.e. it prunes the tree by * removing all the branches that do not contain the words in the filter. * * @param vocabulary * The vocabulary to be trimmed * @param vocabularyPrunningXSLT * The filename of the stylesheet that trims the vocabulary * @param filter * The filter to be applied * @return The trimmed vocabulary. */ public Document filterVocabulary(Document vocabulary, String vocabularyPrunningXSLT, String filter) { if (vocabulary == null) return null; try { Hashtable parameters = new Hashtable(); parameters.put("filter", filter); Document prunnedVocabulary = XMLUtil.transformDocument(vocabulary, parameters, vocabularyPrunningXSLT); return prunnedVocabulary; } catch (Exception e) { e.printStackTrace(); return null; } } /** * Loads into memory all the vocabularies found in the given directory. All * files with .xml extension are considered to be controlled vocabularies. * * @param directory * where the files are positioned * @return an hashtable with the filenames of the vocabularies as keys and * the XML documents representing the vocabularies as values. */ private static Hashtable loadControlledVocabularies(String directory) { Hashtable controlledVocabularies = new Hashtable(); File dir = new File(directory); FilenameFilter filter = new FilenameFilter() { public boolean accept(File dir, String name) { return name.endsWith(".xml"); } }; String[] children = dir.list(filter); if (children != null && children.length > 0) { for (int i = 0; i < children.length; i++) { String filename = children[i]; try { Document controlledVocabulary = XMLUtil.loadXML(directory + filename); controlledVocabularies.put(filename, controlledVocabulary); log.warn("Loaded vocabulary: " + filename); } catch (Exception e) { log.warn("Failed to load vocabulary from " + filename, e); } } } else { log.warn("Could not find any vocabularies..."); } return controlledVocabularies; } /** * Gets the filter provided as parameter to the tag * * @return the filter */ public String getFilter() { return filter; } /** * Sets the filter * * @param filter * the filter */ public void setFilter(String filter) { this.filter = filter; } /** * Returns the value of the multiple selection parameter * * @return true if the multiple selection was selected */ public boolean isAllowMultipleSelection() { return allowMultipleSelection; } /** * Defines if we want to be able to select multiple terms of the taxonomy * * @param allowMultipleSelection * true if we want to be able to select more than on term */ public void setAllowMultipleSelection(boolean allowMultipleSelection) { this.allowMultipleSelection = allowMultipleSelection; } /** * Gets the name of the vocabulary to be displayed * * @return the name of the vocabulary */ public String getVocabulary() { return vocabulary; } /** * Sets the name of the vocabulary to be displayed. If no name is provided, * all vocabularies loaded will be rendered to the output * * @param vocabulary * the name of the vocabulary to be selected */ public void setVocabulary(String vocabulary) { this.vocabulary = vocabulary; } }