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.WikiContext; 024import org.apache.wiki.api.exceptions.PluginException; 025import org.apache.wiki.api.exceptions.ProviderException; 026import org.apache.wiki.api.plugin.WikiPlugin; 027import org.apache.wiki.plugin.AbstractReferralPlugin; 028import org.jdom2.Element; 029import org.jdom2.Namespace; 030import org.jdom2.output.Format; 031import org.jdom2.output.XMLOutputter; 032 033import java.util.ArrayList; 034import java.util.Collection; 035import java.util.Iterator; 036import java.util.List; 037import java.util.Map; 038import java.util.regex.Pattern; 039 040/** 041 * A WikiPlugin that creates an index of pages according to a certain pattern. 042 * <br /> 043 * The default is to include all pages. 044 * <p> 045 * This is a rewrite of the earlier JSPWiki IndexPlugin using JDOM2. 046 8 </p> 047 * <p> 048 * Parameters (from AbstractReferralPlugin): 049 * </p> 050 * <ul> 051 * <li><b>include</b> - A regexp pattern for marking which pages should be included.</li> 052 * <li><b>exclude</b> - A regexp pattern for marking which pages should be excluded.</li> 053 * </ul> 054 * 055 * @author Ichiro Furusato 056 */ 057public class IndexPlugin extends AbstractReferralPlugin implements WikiPlugin 058{ 059 private static Logger log = Logger.getLogger(IndexPlugin.class); 060 061 private Namespace xmlns_XHTML = Namespace.getNamespace("http://www.w3.org/1999/xhtml"); 062 063 /** 064 * {@inheritDoc} 065 */ 066 public String execute( WikiContext context, Map<String,String> params ) throws PluginException 067 { 068 String include = params.get(PARAM_INCLUDE); 069 String exclude = params.get(PARAM_EXCLUDE); 070 071 Element masterDiv = getElement("div","index"); 072 Element indexDiv = getElement("div","header"); 073 masterDiv.addContent(indexDiv); 074 try { 075 List<String> pages = listPages(context,include,exclude); 076 context.getEngine().getPageSorter().sort(pages); 077 char initialChar = ' '; 078 Element currentDiv = new Element("div",xmlns_XHTML); 079 for ( String name : pages ) { 080 if ( name.charAt(0) != initialChar ) { 081 if ( initialChar != ' ' ) { 082 indexDiv.addContent(" - "); 083 } 084 initialChar = name.charAt(0); 085 masterDiv.addContent(makeHeader(String.valueOf(initialChar))); 086 currentDiv = getElement("div","body"); 087 masterDiv.addContent(currentDiv); 088 indexDiv.addContent(getLink("#"+initialChar,String.valueOf(initialChar))); 089 } else { 090 currentDiv.addContent(", "); 091 } 092 currentDiv.addContent(getLink(context.getURL(WikiContext.VIEW,name),name)); 093 } 094 095 } catch( ProviderException e ) { 096 log.warn("could not load page index",e); 097 throw new PluginException( e.getMessage() ); 098 } 099 // serialize to raw format string (no changes to whitespace) 100 XMLOutputter out = new XMLOutputter(Format.getRawFormat()); 101 return out.outputString(masterDiv); 102 } 103 104 105 private Element getLink( String href, String content ) 106 { 107 Element a = new Element("a",xmlns_XHTML); 108 a.setAttribute("href",href); 109 a.addContent(content); 110 return a; 111 } 112 113 114 private Element makeHeader( String initialChar ) 115 { 116 Element span = getElement("span","section"); 117 Element a = new Element("a",xmlns_XHTML); 118 a.setAttribute("id",initialChar); 119 a.addContent(initialChar); 120 span.addContent(a); 121 return span; 122 } 123 124 125 private Element getElement( String gi, String classValue ) 126 { 127 Element elt = new Element(gi,xmlns_XHTML); 128 elt.setAttribute("class",classValue); 129 return elt; 130 } 131 132 133 /** 134 * Grabs a list of all pages and filters them according to the include/exclude patterns. 135 * 136 * @param context 137 * @param include 138 * @param exclude 139 * @return A list containing page names which matched the filters. 140 * @throws ProviderException 141 */ 142 private List<String> listPages( WikiContext context, String include, String exclude ) 143 throws ProviderException 144 { 145 Pattern includePtrn = include != null 146 ? Pattern.compile( include ) 147 : Pattern.compile(".*"); 148 Pattern excludePtrn = exclude != null 149 ? Pattern.compile( exclude ) 150 : Pattern.compile("\\p{Cntrl}"); // there are no control characters in page names 151 List<String> result = new ArrayList<String>(); 152 @SuppressWarnings("unchecked") 153 Collection<String> pages = (Collection<String>)context.getEngine().getReferenceManager().findCreated(); 154 for ( Iterator<String> i = pages.iterator(); i.hasNext(); ) { 155 String pageName = (String) i.next(); 156 if ( excludePtrn.matcher( pageName ).matches() ) continue; 157 if ( includePtrn.matcher( pageName ).matches() ) { 158 result.add( pageName ); 159 } 160 } 161 return result; 162 } 163 164}