001: /*
002: JSPWiki - a JSP-based WikiWiki clone.
003:
004: Copyright (C) 2001-2003 Janne Jalkanen (Janne.Jalkanen@iki.fi)
005:
006: This program is free software; you can redistribute it and/or modify
007: it under the terms of the GNU Lesser General Public License as published by
008: the Free Software Foundation; either version 2.1 of the License, or
009: (at your option) any later version.
010:
011: This program is distributed in the hope that it will be useful,
012: but WITHOUT ANY WARRANTY; without even the implied warranty of
013: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: GNU Lesser General Public License for more details.
015:
016: You should have received a copy of the GNU Lesser General Public License
017: along with this program; if not, write to the Free Software
018: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020: package com.ecyrd.jspwiki.tags;
021:
022: import com.ecyrd.jspwiki.WikiEngine;
023: import com.ecyrd.jspwiki.WikiContext;
024:
025: import javax.servlet.http.HttpSession;
026: import javax.servlet.jsp.JspWriter;
027:
028: import org.apache.log4j.Logger;
029:
030: import java.io.IOException;
031: import java.io.Serializable;
032: import java.util.LinkedList;
033:
034: /**
035: * Implement a "breadcrumb" (most recently visited) trail. This tag can be added to any view jsp page.
036: * Separate breadcrumb trails are not tracked across multiple browser windows.<br>
037: * The optional attributes are:
038: * <p>
039: * <b>maxpages</b>, the number of pages to store, 10 by default<br>
040: * <b>separator</b>, the separator string to use between pages, " | " by default<br>
041: * </p>
042: *
043: * <p>
044: * This class is implemented by storing a breadcrumb trail, which is a
045: * fixed size queue, into a session variable "breadCrumbTrail".
046: * This queue is displayed as a series of links separated by a separator
047: * character.
048: * </p>
049: * @author Ken Liu ken@kenliu.net
050: */
051: public class BreadcrumbsTag extends WikiTagBase {
052: private static final Logger log = Logger
053: .getLogger(BreadcrumbsTag.class);
054: private static final String BREADCRUMBTRAIL_KEY = "breadCrumbTrail";
055: private int m_maxQueueSize = 11;
056: private String m_separator = " > ";
057:
058: public int getMaxpages() {
059: return m_maxQueueSize;
060: }
061:
062: public void setMaxpages(int maxpages) {
063: m_maxQueueSize = maxpages + 1;
064: }
065:
066: public String getSeparator() {
067: return m_separator;
068: }
069:
070: public void setSeparator(String separator) {
071: m_separator = separator;
072: }
073:
074: public final int doWikiStartTag() throws IOException {
075: HttpSession session = pageContext.getSession();
076: FixedQueue trail = (FixedQueue) m_wikiContext
077: .getPrivateSessionAttribute(BREADCRUMBTRAIL_KEY);
078:
079: String page = m_wikiContext.getPage().getName();
080:
081: if (trail == null) {
082: trail = new FixedQueue(m_maxQueueSize);
083: }
084:
085: if (m_wikiContext.getRequestContext().equals(WikiContext.VIEW)) {
086: if (trail.isEmpty()) {
087: trail.push(page);
088: } else {
089: //
090: // Don't add the page to the queue if the page was just refreshed
091: //
092: if (!((String) trail.getLast()).equals(page)) {
093: trail.push(page);
094: log.debug("added page: " + page);
095: }
096: log.debug("didn't add page because of refresh");
097: }
098: }
099:
100: m_wikiContext.setPrivateSessionAttribute(BREADCRUMBTRAIL_KEY,
101: trail);
102:
103: //
104: // Print out the breadcrumb trail
105: //
106:
107: // FIXME: this code would be much simpler if we could just output the [pagename] and then use the
108: // wiki engine to output the appropriate wikilink
109:
110: JspWriter out = pageContext.getOut();
111: int queueSize = trail.size();
112: String linkclass = "wikipage";
113: WikiEngine engine = m_wikiContext.getEngine();
114: String curPage = null;
115:
116: for (int i = 0; i < queueSize; i++) {
117: curPage = (String) trail.get(i);
118:
119: // skip the last page if it is the current page
120: if (i == queueSize - 1 && curPage.equals(page))
121: break;
122:
123: if (i > 0) {
124: out.print(m_separator);
125: }
126:
127: //FIXME: I can't figure out how to detect the appropriate jsp page to put here, so I hard coded Wiki.jsp
128: //This breaks when you view an attachment metadata page
129: out.print("<a class=\"" + linkclass + "\" href=\""
130: + m_wikiContext.getViewURL(curPage) + "\">"
131: + WikiEngine.getRelativeToWikiPageName(curPage)
132: + "</a>");
133:
134: }
135:
136: return SKIP_BODY;
137: }
138:
139: /**
140: * Extends the LinkedList class to provide a fixed-size queue implementation
141: */
142: private static class FixedQueue extends LinkedList implements
143: Serializable {
144: private int m_size;
145:
146: FixedQueue(int size) {
147: m_size = size;
148: }
149:
150: Object push(Object o) {
151: add(o);
152: if (size() > m_size)
153: return removeFirst();
154: else
155: return null;
156: }
157: }
158:
159: }
|