001/* 002 Licensed to the Apache Software Foundation (ASF) under one 003 or more contributor license agreements. See the NOTICE file 004 distributed with this work for additional information 005 regarding copyright ownership. The ASF licenses this file 006 to you under the Apache License, Version 2.0 (the 007 "License"); you may not use this file except in compliance 008 with the License. You may obtain a copy of the License at 009 010 http://www.apache.org/licenses/LICENSE-2.0 011 012 Unless required by applicable law or agreed to in writing, 013 software distributed under the License is distributed on an 014 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 KIND, either express or implied. See the License for the 016 specific language governing permissions and limitations 017 under the License. 018 */ 019 020package org.apache.wiki.plugin; 021 022import org.apache.log4j.Logger; 023import org.apache.wiki.api.core.Context; 024import org.apache.wiki.api.core.ContextEnum; 025import org.apache.wiki.api.exceptions.PluginException; 026import org.apache.wiki.api.exceptions.ProviderException; 027import org.apache.wiki.api.plugin.Plugin; 028import org.apache.wiki.pages.PageManager; 029import org.apache.wiki.references.ReferenceManager; 030import org.jdom2.Element; 031import org.jdom2.Namespace; 032import org.jdom2.output.Format; 033import org.jdom2.output.XMLOutputter; 034 035import java.util.ArrayList; 036import java.util.List; 037import java.util.Map; 038import java.util.Set; 039import java.util.regex.Pattern; 040 041/** 042 * A Plugin that creates an index of pages according to a certain pattern. 043 * <br /> 044 * The default is to include all pages. 045 * <p> 046 * This is a rewrite of the earlier JSPWiki IndexPlugin using JDOM2. 047 8 </p> 048 * <p> 049 * Parameters (from AbstractReferralPlugin): 050 * </p> 051 * <ul> 052 * <li><b>include</b> - A regexp pattern for marking which pages should be included.</li> 053 * <li><b>exclude</b> - A regexp pattern for marking which pages should be excluded.</li> 054 * </ul> 055 * 056 * @author Ichiro Furusato 057 */ 058public class IndexPlugin extends AbstractReferralPlugin implements Plugin { 059 060 private static final Logger log = Logger.getLogger(IndexPlugin.class); 061 062 private Namespace xmlns_XHTML = Namespace.getNamespace("http://www.w3.org/1999/xhtml"); 063 064 /** 065 * {@inheritDoc} 066 */ 067 @Override 068 public String execute( final Context context, final Map<String,String> params ) throws PluginException { 069 final String include = params.get(PARAM_INCLUDE); 070 final String exclude = params.get(PARAM_EXCLUDE); 071 072 final Element masterDiv = getElement("div","index"); 073 final Element indexDiv = getElement("div","header"); 074 masterDiv.addContent(indexDiv); 075 try { 076 final List<String> pages = listPages(context,include,exclude); 077 context.getEngine().getManager( PageManager.class ).getPageSorter().sort(pages); 078 char initialChar = ' '; 079 Element currentDiv = new Element("div",xmlns_XHTML); 080 for ( final String name : pages ) { 081 if ( name.charAt(0) != initialChar ) { 082 if ( initialChar != ' ' ) { 083 indexDiv.addContent(" - "); 084 } 085 initialChar = name.charAt(0); 086 masterDiv.addContent(makeHeader(String.valueOf(initialChar))); 087 currentDiv = getElement("div","body"); 088 masterDiv.addContent(currentDiv); 089 indexDiv.addContent(getLink("#"+initialChar,String.valueOf(initialChar))); 090 } else { 091 currentDiv.addContent(", "); 092 } 093 currentDiv.addContent( getLink( context.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), name ), name ) ); 094 } 095 096 } catch( final ProviderException e ) { 097 log.warn("could not load page index",e); 098 throw new PluginException( e.getMessage() ); 099 } 100 // serialize to raw format string (no changes to whitespace) 101 final XMLOutputter out = new XMLOutputter(Format.getRawFormat()); 102 return out.outputString(masterDiv); 103 } 104 105 private Element getLink( final String href, final String content ) { 106 final Element a = new Element( "a", xmlns_XHTML ); 107 a.setAttribute( "href", href ); 108 a.addContent( content ); 109 return a; 110 } 111 112 private Element makeHeader( final String initialChar ) { 113 final Element span = getElement( "span", "section" ); 114 final Element a = new Element( "a", xmlns_XHTML ); 115 a.setAttribute( "id", initialChar ); 116 a.addContent( initialChar ); 117 span.addContent( a ); 118 return span; 119 } 120 121 private Element getElement( final String gi, final String classValue ) { 122 final Element elt = new Element( gi, xmlns_XHTML ); 123 elt.setAttribute( "class", classValue ); 124 return elt; 125 } 126 127 /** 128 * Grabs a list of all pages and filters them according to the include/exclude patterns. 129 * 130 * @param context 131 * @param include 132 * @param exclude 133 * @return A list containing page names which matched the filters. 134 * @throws ProviderException 135 */ 136 private List<String> listPages( final Context context, final String include, final String exclude ) throws ProviderException { 137 final Pattern includePtrn = include != null ? Pattern.compile( include ) : Pattern.compile(".*"); 138 final Pattern excludePtrn = exclude != null ? Pattern.compile( exclude ) : Pattern.compile("\\p{Cntrl}"); // there are no control characters in page names 139 final List< String > result = new ArrayList<>(); 140 final Set< String > pages = context.getEngine().getManager( ReferenceManager.class ).findCreated(); 141 for( final String pageName : pages ) { 142 if( excludePtrn.matcher( pageName ).matches() ) { 143 continue; 144 } 145 if( includePtrn.matcher( pageName ).matches() ) { 146 result.add( pageName ); 147 } 148 } 149 return result; 150 } 151 152}