| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| package org.apache.wiki.plugin; |
| |
| import org.apache.log4j.Logger; |
| import org.apache.oro.text.regex.MalformedPatternException; |
| import org.apache.oro.text.regex.Pattern; |
| import org.apache.oro.text.regex.PatternCompiler; |
| import org.apache.oro.text.regex.PatternMatcher; |
| import org.apache.oro.text.regex.Perl5Compiler; |
| import org.apache.oro.text.regex.Perl5Matcher; |
| import org.apache.wiki.WikiContext; |
| import org.apache.wiki.WikiEngine; |
| import org.apache.wiki.WikiPage; |
| import org.apache.wiki.api.exceptions.PluginException; |
| import org.apache.wiki.api.plugin.WikiPlugin; |
| import org.apache.wiki.references.ReferenceManager; |
| import org.apache.wiki.util.TextUtil; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| |
| /** |
| * Displays the pages referring to the current page. |
| * |
| * <p>Parameters</p> |
| * <ul> |
| * <li><b>name</b> - Name of the root page. Default name of calling page |
| * <li><b>type</b> - local|externalattachment |
| * <li><b>depth</b> - How many levels of pages to be parsed. |
| * <li><b>include</b> - Include only these pages. (eg. include='UC.*|BP.*' ) |
| * <li><b>exclude</b> - Exclude with this pattern. (eg. exclude='LeftMenu' ) |
| * <li><b>format</b> - full|compact, FULL now expands all levels correctly |
| * </ul> |
| * |
| */ |
| public class ReferredPagesPlugin implements WikiPlugin { |
| |
| private static Logger log = Logger.getLogger( ReferredPagesPlugin.class ); |
| private WikiEngine m_engine; |
| private int m_depth; |
| private HashSet<String> m_exists = new HashSet<>(); |
| private StringBuffer m_result = new StringBuffer(1024); |
| private PatternMatcher m_matcher = new Perl5Matcher(); |
| private Pattern m_includePattern; |
| private Pattern m_excludePattern; |
| private boolean m_formatCompact = true; |
| private boolean m_formatSort = false; |
| |
| /** The parameter name for the root page to start from. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_ROOT = "page"; |
| |
| /** The parameter name for the depth. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_DEPTH = "depth"; |
| |
| /** The parameter name for the type of the references. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_TYPE = "type"; |
| |
| /** The parameter name for the included pages. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_INCLUDE = "include"; |
| |
| /** The parameter name for the excluded pages. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_EXCLUDE = "exclude"; |
| |
| /** The parameter name for the format. Value is <tt>{@value}</tt>. */ |
| public static final String PARAM_FORMAT = "format"; |
| |
| /** The minimum depth. Value is <tt>{@value}</tt>. */ |
| public static final int MIN_DEPTH = 1; |
| |
| /** The maximum depth. Value is <tt>{@value}</tt>. */ |
| public static final int MAX_DEPTH = 8; |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public String execute( WikiContext context, Map<String, String> params ) throws PluginException { |
| m_engine = context.getEngine(); |
| |
| WikiPage page = context.getPage(); |
| if( page == null ) return ""; |
| |
| // parse parameters |
| String rootname = params.get( PARAM_ROOT ); |
| if( rootname == null ) rootname = page.getName() ; |
| |
| String format = params.get( PARAM_FORMAT ); |
| if( format == null) format = ""; |
| if( format.indexOf( "full" ) >=0 ) m_formatCompact = false ; |
| if( format.indexOf( "sort" ) >=0 ) m_formatSort = true ; |
| |
| m_depth = TextUtil.parseIntParameter( params.get( PARAM_DEPTH ), MIN_DEPTH ); |
| if( m_depth > MAX_DEPTH ) m_depth = MAX_DEPTH; |
| |
| String includePattern = params.get(PARAM_INCLUDE); |
| if( includePattern == null ) includePattern = ".*"; |
| |
| String excludePattern = params.get(PARAM_EXCLUDE); |
| if( excludePattern == null ) excludePattern = "^$"; |
| |
| log.debug( "Fetching referred pages for "+ rootname + |
| " with a depth of "+ m_depth + |
| " with include pattern of "+ includePattern + |
| " with exclude pattern of "+ excludePattern ); |
| |
| // |
| // do the actual work |
| // |
| String href = context.getViewURL(rootname); |
| String title = "ReferredPagesPlugin: depth["+m_depth+ |
| "] include["+includePattern+"] exclude["+excludePattern+ |
| "] format["+(m_formatCompact ? "compact" : "full") + |
| (m_formatSort ? " sort" : "") + "]"; |
| |
| m_result.append("<div class=\"ReferredPagesPlugin\">\n"); |
| m_result.append("<a class=\"wikipage\" href=\""+ href + |
| "\" title=\"" + TextUtil.replaceEntities(title) + |
| "\">" + TextUtil.replaceEntities(rootname) + "</a>\n"); |
| m_exists.add(rootname); |
| |
| // pre compile all needed patterns |
| // glob compiler : * is 0..n instance of any char -- more convenient as input |
| // perl5 compiler : .* is 0..n instances of any char -- more powerful |
| //PatternCompiler g_compiler = new GlobCompiler(); |
| PatternCompiler compiler = new Perl5Compiler(); |
| |
| try |
| { |
| m_includePattern = compiler.compile(includePattern); |
| |
| m_excludePattern = compiler.compile(excludePattern); |
| } |
| catch( MalformedPatternException e ) |
| { |
| if (m_includePattern == null ) |
| { |
| throw new PluginException("Illegal include pattern detected."); |
| } |
| else if (m_excludePattern == null ) |
| { |
| throw new PluginException("Illegal exclude pattern detected."); |
| } |
| else |
| { |
| throw new PluginException("Illegal internal pattern detected."); |
| } |
| } |
| |
| // go get all referred links |
| getReferredPages(context,rootname, 0); |
| |
| // close and finish |
| m_result.append ("</div>\n" ) ; |
| |
| return m_result.toString() ; |
| } |
| |
| |
| /** |
| * Retrieves a list of all referred pages. Is called recursively depending on the depth parameter. |
| */ |
| private void getReferredPages( WikiContext context, String pagename, int depth ) { |
| if( depth >= m_depth ) return; // end of recursion |
| if( pagename == null ) return; |
| if( !m_engine.pageExists(pagename) ) return; |
| |
| ReferenceManager mgr = m_engine.getReferenceManager(); |
| |
| Collection<String> allPages = mgr.findRefersTo( pagename ); |
| |
| handleLinks( context, allPages, ++depth, pagename ); |
| } |
| |
| private void handleLinks(WikiContext context,Collection<String> links, int depth, String pagename) { |
| boolean isUL = false; |
| HashSet<String> localLinkSet = new HashSet<>(); // needed to skip multiple |
| // links to the same page |
| localLinkSet.add(pagename); |
| |
| ArrayList<String> allLinks = new ArrayList<>(); |
| |
| if( links != null ) |
| allLinks.addAll( links ); |
| |
| if( m_formatSort ) context.getEngine().getPageManager().getPageSorter().sort( allLinks ); |
| |
| for( Iterator<String> i = allLinks.iterator(); i.hasNext(); ) { |
| String link = i.next() ; |
| |
| if( localLinkSet.contains( link ) ) continue; // skip multiple links to the same page |
| localLinkSet.add( link ); |
| |
| if( !m_engine.pageExists( link ) ) continue; // hide links to non existing pages |
| |
| if( m_matcher.matches( link , m_excludePattern ) ) continue; |
| if( !m_matcher.matches( link , m_includePattern ) ) continue; |
| |
| if( m_exists.contains( link ) ) { |
| if( !m_formatCompact ) { |
| if( !isUL ) { |
| isUL = true; |
| m_result.append("<ul>\n"); |
| } |
| |
| //See https://www.w3.org/wiki/HTML_lists for proper nesting of UL and LI |
| m_result.append("<li> " + TextUtil.replaceEntities(link) + "\n"); |
| |
| getReferredPages( context, link, depth ); // added recursive call - on general request |
| |
| m_result.append("\n</li>\n"); |
| |
| } |
| } else { |
| if( !isUL ) { |
| isUL = true; |
| m_result.append("<ul>\n"); |
| } |
| |
| String href = context.getURL(WikiContext.VIEW,link); |
| m_result.append("<li><a class=\"wikipage\" href=\""+ href + "\">" |
| + TextUtil.replaceEntities(link) + "</a>\n" ); |
| |
| m_exists.add( link ); |
| |
| getReferredPages( context, link, depth ); |
| |
| m_result.append("\n</li>\n"); |
| |
| } |
| } |
| |
| if( isUL ) { |
| m_result.append("</ul>\n"); |
| } |
| } |
| |
| } |