001: /*
002: ReferredPagesPlugin
003: Dirk Frederickx Aug 2004, Jan 2005
004: Janne Jalkanen 2005
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.plugin;
021:
022: /**
023: * Displays the pages referring to the current page.
024: *
025: * <P>Parameters</P>
026: * <UL>
027: * <LI>name: Name of the root page. Default name of calling page
028: * <LI>type: local|externalattachment
029: * <LI>depth: How many levels of pages to be parsed.
030: * <LI>include: Include only these pages. (eg. include='UC.*|BP.*' )
031: * <LI>exclude: Exclude with this pattern. (eg. exclude='LeftMenu' )
032: * <LI>format: full|compact
033: * <br>FULL now expands all levels correctly
034: * </UL>
035: *
036: * @author Dirk Frederickx
037: */
038:
039: import java.util.*;
040:
041: import org.apache.log4j.Logger;
042: import org.apache.oro.text.regex.*;
043:
044: import com.ecyrd.jspwiki.*;
045:
046: public class ReferredPagesPlugin implements WikiPlugin {
047: private static Logger log = Logger
048: .getLogger(ReferredPagesPlugin.class);
049: private WikiEngine m_engine;
050: private int m_depth;
051: private HashSet m_exists = new HashSet();
052: private StringBuffer m_result = new StringBuffer(1024);
053: private PatternMatcher m_matcher = new Perl5Matcher();
054: private Pattern m_includePattern;
055: private Pattern m_excludePattern;
056: private boolean m_formatCompact = true;
057: private boolean m_formatSort = false;
058:
059: public static final String PARAM_ROOT = "page";
060: public static final String PARAM_DEPTH = "depth";
061: public static final String PARAM_TYPE = "type";
062: public static final String PARAM_INCLUDE = "include";
063: public static final String PARAM_EXCLUDE = "exclude";
064: public static final String PARAM_FORMAT = "format";
065: public static final int MIN_DEPTH = 1;
066: public static final int MAX_DEPTH = 8;
067:
068: public String execute(WikiContext context, Map params)
069: throws PluginException {
070: m_engine = context.getEngine();
071:
072: WikiPage page = context.getPage();
073: if (page == null)
074: return "";
075:
076: // parse parameters
077: String rootname = (String) params.get(PARAM_ROOT);
078: if (rootname == null)
079: rootname = page.getName();
080:
081: String format = (String) params.get(PARAM_FORMAT);
082: if (format == null)
083: format = "";
084: if (format.indexOf("full") >= 0)
085: m_formatCompact = false;
086: if (format.indexOf("sort") >= 0)
087: m_formatSort = true;
088:
089: m_depth = TextUtil.parseIntParameter((String) params
090: .get(PARAM_DEPTH), MIN_DEPTH);
091: if (m_depth > MAX_DEPTH)
092: m_depth = MAX_DEPTH;
093:
094: String includePattern = (String) params.get(PARAM_INCLUDE);
095: if (includePattern == null)
096: includePattern = ".*";
097:
098: String excludePattern = (String) params.get(PARAM_EXCLUDE);
099: if (excludePattern == null)
100: excludePattern = "^$";
101:
102: log.debug("Fetching referred pages for " + rootname
103: + " with a depth of " + m_depth
104: + " with include pattern of " + includePattern
105: + " with exclude pattern of " + excludePattern);
106:
107: //
108: // do the actual work
109: //
110: String href = context.getViewURL(rootname);
111: String title = "ReferredPagesPlugin: depth[" + m_depth
112: + "] include[" + includePattern + "] exclude["
113: + excludePattern + "] format["
114: + (m_formatCompact ? "compact" : "full")
115: + (m_formatSort ? " sort" : "") + "]";
116:
117: m_result.append("<div class=\"ReferredPagesPlugin\">\n");
118: m_result.append("<a class=\"wikipage\" href=\"" + href
119: + "\" title=\"" + title + "\">" + rootname + "</a>\n");
120: m_exists.add(rootname);
121:
122: // pre compile all needed patterns
123: // glob compiler : * is 0..n instance of any char -- more convenient as input
124: // perl5 compiler : .* is 0..n instances of any char -- more powerful
125: //PatternCompiler g_compiler = new GlobCompiler();
126: PatternCompiler compiler = new Perl5Compiler();
127:
128: try {
129: m_includePattern = compiler.compile(includePattern);
130:
131: m_excludePattern = compiler.compile(excludePattern);
132: } catch (MalformedPatternException e) {
133: if (m_includePattern == null) {
134: throw new PluginException(
135: "Illegal include pattern detected.");
136: } else if (m_excludePattern == null) {
137: throw new PluginException(
138: "Illegal exclude pattern detected.");
139: } else {
140: throw new PluginException(
141: "Illegal internal pattern detected.");
142: }
143: }
144:
145: // go get all referred links
146: getReferredPages(context, rootname, 0);
147:
148: // close and finish
149: m_result.append("</div>\n");
150:
151: return m_result.toString();
152: }
153:
154: /**
155: * Retrieves a list of all referred pages. Is called recursively
156: * depending on the depth parameter
157: */
158: protected void getReferredPages(WikiContext context,
159: String pagename, int depth) {
160: if (depth >= m_depth)
161: return; // end of recursion
162: if (pagename == null)
163: return;
164: if (!m_engine.pageExists(pagename))
165: return;
166:
167: ReferenceManager mgr = m_engine.getReferenceManager();
168:
169: Collection allPages = mgr.findRefersTo(pagename);
170:
171: handleLinks(context, allPages, ++depth, pagename);
172: }
173:
174: protected void handleLinks(WikiContext context, Collection links,
175: int depth, String pagename) {
176: boolean isUL = false;
177: HashSet localLinkSet = new HashSet(); // needed to skip multiple
178: // links to the same page
179: localLinkSet.add(pagename);
180:
181: ArrayList allLinks = new ArrayList();
182:
183: if (links != null)
184: allLinks.addAll(links);
185:
186: if (m_formatSort)
187: Collections.sort(allLinks);
188:
189: for (Iterator i = allLinks.iterator(); i.hasNext();) {
190: String link = (String) i.next();
191:
192: if (localLinkSet.contains(link))
193: continue; // skip multiple
194: // links to the same
195: // page
196: localLinkSet.add(link);
197:
198: if (!m_engine.pageExists(link))
199: continue; // hide links to non
200: // existing pages
201:
202: if (m_matcher.matches(link, m_excludePattern))
203: continue;
204: if (!m_matcher.matches(link, m_includePattern))
205: continue;
206:
207: if (m_exists.contains(link)) {
208: if (!m_formatCompact) {
209: if (!isUL) {
210: isUL = true;
211: m_result.append("<ul>\n");
212: }
213:
214: m_result.append("<li> " + link + " </li>\n");
215:
216: getReferredPages(context, link, depth); // added recursive
217: // call - on general
218: // request
219: }
220: } else {
221: if (!isUL) {
222: isUL = true;
223: m_result.append("<ul>\n");
224: }
225:
226: String href = context.getURL(WikiContext.VIEW, link);
227: m_result.append("<li><a class=\"wikipage\" href=\""
228: + href + "\">" + link + "</a></li>\n");
229:
230: m_exists.add(link);
231:
232: getReferredPages(context, link, depth);
233: }
234: }
235:
236: if (isUL)
237: m_result.append("</ul>\n");
238: }
239: }
|