/*
JSPWiki - a JSP-based WikiWiki clone.
Copyright (C) 2001-2003 Janne Jalkanen (Janne.Jalkanen@iki.fi)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package com.ecyrd.jspwiki.tags;
import java.io.IOException;
import java.io.Serializable;
import java.util.LinkedList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.JspWriter;
import org.apache.log4j.Logger;
import com.ecyrd.jspwiki.WikiContext;
/**
* Implement a "breadcrumb" (most recently visited) trail. This tag can be added
* to any view jsp page. Separate breadcrumb trails are not tracked across
* multiple browser windows.
* The optional attributes are:
*
* maxpages, the number of pages to store, 10 by default
* separator, the separator string to use between pages, " | " by
* default
*
* This class is implemented by storing a breadcrumb trail, which is a fixed * size queue, into a session variable "breadCrumbTrail". This queue is * displayed as a series of links separated by a separator character. *
* ** JPSR: cambiado el comportamiento para que cuando el usuario haga click en un enlace del * breadcrumb se haga un pop del resto de enlaces hasta el final del breadcrumb, quedando * un comportamiento más intuitivo. Esto se consigue gestionando un parámetro adicional en la * request, navbreadcrumb. La página Wiki.jsp también ha sido cambiada un poco para evitar que * se muestre este parámetro en la url (hace un redirect a si misma pero pasando solamente el * parámetro page a la request). De este modo se consigue que el comportamiento añadido sea * totalmente transparente al resto de la aplicación. *
** JPSR: changed behaviour so when a user clicks on a breadcrumb link, the next links until * end of breadcrumb are "popped" out, which is a little more intuitive. This is done * managing the navbreadcrumb request parameter. Wiki.jsp has also a little change to * avoid showing this parameter on the url (it performs a redirect to itself with only * the page parameter). By doing this we achieve that the added behaviour remains transparent * to the rest of the application. *
* * @author Ken Liu ken@kenliu.net / modified by Juan Pablo Santos Rodríguez (juanpablo.santos at vass dot es) */ public class BreadcrumbsTag extends WikiTagBase { private static final long serialVersionUID = 0L; private static final Logger log = Logger.getLogger(BreadcrumbsTag.class); private static final String BREADCRUMBTRAIL_KEY = "breadCrumbTrail"; private int m_maxQueueSize = 11; private String m_separator = " > "; public int getMaxpages() { return m_maxQueueSize; } public void setMaxpages(int maxpages) { m_maxQueueSize = maxpages + 1; } public String getSeparator() { return m_separator; } public void setSeparator(String separator) { m_separator = separator; } public final int doWikiStartTag() throws IOException { HttpSession session = pageContext.getSession(); HttpServletRequest request = m_wikiContext.getHttpRequest(); // para gestionar la request más fácilmente // used to handle the request more easily FixedQueue trail = (FixedQueue) session .getAttribute(BREADCRUMBTRAIL_KEY); String page = m_wikiContext.getPage().getName(); if (trail == null) { trail = new FixedQueue(m_maxQueueSize); } // Detectar si el usuario ha hecho click en el breadcrumb // Detect if user has clicked on breadcrumb String clickOnBreadcrumb = request.getParameter("navbreadcrumb"); if (clickOnBreadcrumb != null) { int newSize = Integer.parseInt(clickOnBreadcrumb); if (newSize >= 0) { while (trail.size() >= newSize) { trail.pop(); } } } if (m_wikiContext.getRequestContext().equals(WikiContext.VIEW)) { if (trail.isEmpty()) { trail.push(page); } else { // // Don't add the page to the queue if the page was just // refreshed // if (!((String) trail.getLast()).equals(page)) { trail.push(page); log.debug("added page: " + page); } log.debug("didn't add page because of refresh"); } } session.setAttribute(BREADCRUMBTRAIL_KEY, trail); // // Print out the breadcrumb trail // // FIXME: this code would be much simpler if we could just output the // [pagename] and then use the // wiki engine to output the appropriate wikilink JspWriter out = pageContext.getOut(); int queueSize = trail.size(); String linkclass = "wikipage"; String curPage = null; for (int i = 0; i < queueSize - 1; i++) { curPage = (String) trail.get(i); // FIXME: I can't figure out how to detect the appropriate jsp page // to put here, so I hard coded Wiki.jsp // This breaks when you view an attachment metadata page String href = m_wikiContext.getViewURL(curPage); String hrefComplete = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + href; out.print("" + curPage + ""); // FIXMozilla: en los enlaces, si en el evento onmouseover se cambia el window.status y se devuelve // true entonces no lo cambia, que es lo que debería ocurrir cuando se devolviese false. Cfr con // http://www.quirksmode.org/bugreports/archives/mozilla/index.html // FIXMozilla: on anchors, if onmouseover event changes window.status and returns true then it does // *not* do anything, just the behaviour it should have when returning false. Check with // http://www.quirksmode.org/bugreports/archives/mozilla/index.html if (i < queueSize - 2) { out.print(m_separator); } } return SKIP_BODY; } /** * Extends the LinkedList class to provide a fixed-size queue implementation */ private static class FixedQueue extends LinkedList implements Serializable { private int m_size; private static final long serialVersionUID = 0L; FixedQueue(int size) { m_size = size; } Object push(Object o) { add(o); if (size() > m_size) { return removeFirst(); } return null; } Object pop() { if (size() > 0) { return removeLast(); } return null; } } }