Sorry, I meant attach it to the JIRA issue. And you have to add it as a full .java-file to make sure there are no dependencies to the current Index plugin.
/Janne On Tue, Apr 15, 2008 at 07:38:49PM +1200, Murray Altheim wrote: > Janne Jalkanen wrote: > >>Okay, I've finished writing the IndexPlugin and fired off a message > >>to Craig Russell regarding a JIRA account, though he's yet to respond > >>(time zone likely culprit). I'd thought I had one and was all set up > >>but it doesn't seem to recognize any of my email addresses. > > > >Yeah, according to the svn-committers list you should have access to the > >SVN for both JSPWiki and xml-xindice... > > Yes, but when I try to retrieve the password for 'altheim' I see the > message "No user with that username exists". > > >http://people.apache.org/~jim/committers.html > > Yeah, understood. I note that I apparently don't have a signed CLA on > file -- thought I had faxed a copy before Christmas. If I need to fax > or send via post again, please let me know details. Thanks. I'm > guessing this is why I'm not able to log in. > > >>If there's any rush I can forward a patch, or do what is probably a > >>better thing: get with the programme by submitting it against the > >>existing JIRA bug. > > > >I guess there's no rush, but if you want to have a code review, you can > >always attach it as a patch. > > I'm not in any particular rush but since I've got a bit of a window > here I might as well attach it. This is against svn's trunk. > > Murray > > ........................................................................... > Murray Altheim <murray07 at altheim.com> === = = > http://www.altheim.com/murray/ = = === > SGML Grease Monkey, Banjo Player, Wantanabe Zen Monk = = = = > > Boundless wind and moon - the eye within eyes, > Inexhaustible heaven and earth - the light beyond light, > The willow dark, the flower bright - ten thousand houses, > Knock at any door - there's one who will respond. > -- The Blue Cliff Record > diff -Naur tronk/src/com/ecyrd/jspwiki/plugin/IndexPlugin.java > trunk/src/com/ecyrd/jspwiki/plugin/IndexPlugin.java > --- tronk/src/com/ecyrd/jspwiki/plugin/IndexPlugin.java 2008-04-15 > 10:29:32.000000000 +1200 > +++ trunk/src/com/ecyrd/jspwiki/plugin/IndexPlugin.java 2008-04-15 > 19:37:21.000000000 +1200 > @@ -1,235 +1,527 @@ > /* > JSPWiki - a JSP-based WikiWiki clone. > > - Copyright (C) 2002 Janne Jalkanen ([EMAIL PROTECTED]) > - > - This program is free software; you can redistribute it and/or modify > - it under the terms of the GNU Lesser General Public License as published > by > - the Free Software Foundation; either version 2.1 of the License, or > - (at your option) any later version. > - > - This program is distributed in the hope that it will be useful, > - but WITHOUT ANY WARRANTY; without even the implied warranty of > - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > - GNU Lesser General Public License for more details. > - > - You should have received a copy of the GNU Lesser General Public License > - along with this program; if not, write to the Free Software > - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA > + 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 com.ecyrd.jspwiki.plugin; > - > -import java.io.StringWriter; > -import java.util.*; > > -import org.apache.log4j.Logger; > -import org.apache.oro.text.GlobCompiler; > -import org.apache.oro.text.regex.*; > +package org.ceryle.wiki.plugin; > > -import com.ecyrd.jspwiki.*; > -import com.ecyrd.jspwiki.providers.ProviderException; > +import com.ecyrd.jspwiki.ReferenceManager; > +import com.ecyrd.jspwiki.TextUtil; > +import com.ecyrd.jspwiki.WikiContext; > +import com.ecyrd.jspwiki.WikiEngine; > +import com.ecyrd.jspwiki.plugin.PluginException; > +import com.ecyrd.jspwiki.plugin.PluginManager; > +import com.ecyrd.jspwiki.plugin.WikiPlugin; > +import com.ecyrd.jspwiki.providers.ProviderException; > + > +import org.apache.log4j.Logger; > + > +import java.text.Collator; > +import java.util.Comparator; > +import java.util.Iterator; > +import java.util.Locale; > +import java.util.Map; > +import java.util.MissingResourceException; > +import java.util.SortedSet; > +import java.util.StringTokenizer; > +import java.util.TreeSet; > +import java.util.regex.*; > > /** > - * Builds an index of all pages. > - * <P>Parameters</P> > - * <UL> > - * <LI>itemsPerLine: How many items should be allowed per line before > break. > - * If set to zero (the default), will not write breaks. > - * <LI>include: Include only these pages. > - * <LI>exclude: Exclude with this pattern. > - * </UL> > + * This IndexPlugin is a CeryleWikiPlugin reworking of the original JSPWiki > + * IndexPlugin. This was developed when the JSPWiki project moved to Apache > + * and IP permissions could not be obtained for the original plugin. > + * Changes include: > + * <ul> > + * <li>improved (Collator-based) locale-dependent sorting </li> > + * <li>ability to include and exclude pages based on multiple > + * (whitespace-delimited) regular expression (regex) patterns </li> > + * <li>include/exclude matching based on Java's regex rather than ORO > + * (one less dependency) </li> > + * <li>locale can be set for sorting (in absence of a parameter, uses > + * Unicode UTF-8 order) </li> > + * <li>produces valid XHTML markup </li> > + * </ul> > + * > + * <h4>Parameters</h4> > + * <ul> > + * <li><b>exclude</b> = <i>'regex regex'</i>. > + * one or more regular expressions (separated by whitespace) to match > + * pages that should be excluded from the generated index. > + * </li> > + * <li><b>include</b> = <i>'regex regex'</i>. > + * one or more regular expressions (separated by whitespace) to match > + * pages that should be included in the generated index. > + * </li> > + * <li><b>itemsPerLine</b> = <i>'int'</i>. > + * the number of page names to display per line of the generated index > + * </li> > + * <li><b>locale</b> = <i>'lang'</i> | <i>'lang_COUNTRY'</i>. > + * provides a locale for sorting page names. This can be specified as > + * either a two character lowercase ISO-639 language code (e.g., "en" > + * for English) , or a two character language code followed by a two > + * character uppercase ISO 3166 country code, separated by an underscore > + * character (e.g., "en_NZ" for New Zealand English). If this parameter > + * is not included the plugin will not use the default (environment) > + * locale, it will resort to Java's native Unicode (UTF-8) String sort > + * method, which may be faster but does not sort according to any > natural > + * language sort order, just the Unicode glyph ordering. To use the > + * default Locale of the server environment, specify an empty string > + * parameter. > + * </li> > + * <li><b>debug</b> = <i>'true' | 'false'</i>. > + * When true, displays debugging level information. Defaults to false. > + * </li> > + * </ul> > + * <p> > + * All parameters are optional. If both <tt>include</tt> and > <tt>exclude</tt> > + * are specified, the former acts as a filter on the results of the > latter. > + * </p> > + * > + * <h4>Notes</h4> > + * <ul> > + * <li> > + * If no locale is specified [EMAIL PROTECTED] > java.lang.String#CompareTo(Object)} is > + * used for sorting, which sorts using the Unicode glyph order. If your > + * wiki uses page names beginning with non-ASCII characters and you want > + * a more sensible sort order a Locale should be specified. > + * </li> > + * <li> > + * This uses [EMAIL PROTECTED] > com.ecyrd.jspwiki.ReferenceManager#findCreated()} rather > + * than [EMAIL PROTECTED] com.ecyrd.jspwiki.PageManager#getAllPages()} > as the source of > + * its page list, which as according to the documentation is > significantly > + * faster (as it incurs no disk access) but may not represent the actual > + * contents of the wiki, especially during startup. Because of the > performance > + * issues of this plugin in production environments speed was > considered more > + * important than an initial plugin display problem during startup. > + * </li> > + * </ul> > * > - * @author Alain Ravet > - * @author Janne Jalkanen > - * @since 1.9.9 > + * @author Murray Altheim > + * @since 2.6.x > */ > public class IndexPlugin implements WikiPlugin > { > - protected static final Logger log = Logger.getLogger(IndexPlugin.class); > + private static Logger log = Logger.getLogger(IndexPlugin.class); > > - public static final String INITIALS_COLOR = "red" ; > - private static final int DEFAULT_ITEMS_PER_LINE = 0 ; > + /** The name of the <tt>debug</tt> parameter. */ > + public static final String PARAM_DEBUG = "debug"; > > - private static final String PARAM_ITEMS_PER_LINE = > "itemsPerLine"; > - private static final String PARAM_INCLUDE = "include"; > - private static final String PARAM_EXCLUDE = "exclude"; > - > - private int m_currentNofPagesOnLine = 0; > - private int m_itemsPerLine; > - protected String m_previousPageFirstLetter = ""; > - protected StringWriter m_bodyPart = new StringWriter(); > - protected StringWriter m_headerPart = new StringWriter(); > - private Pattern m_includePattern; > - private Pattern m_excludePattern; > - > - > - public String execute( WikiContext wikiContext , Map params ) > - throws PluginException > - { > - // > - // Parse arguments and create patterns. > - // > - PatternCompiler compiler = new GlobCompiler(); > - m_itemsPerLine = TextUtil.parseIntParameter( (String) > params.get(PARAM_ITEMS_PER_LINE), > - DEFAULT_ITEMS_PER_LINE > ); > - try > - { > - String ptrn = (String) params.get(PARAM_INCLUDE); > - if( ptrn == null ) ptrn = "*"; > - m_includePattern = compiler.compile(ptrn); > + /** The name of the <tt>exclude</tt> parameter. */ > + public static final String PARAM_EXCLUDE = "exclude"; > > - ptrn = (String) params.get(PARAM_EXCLUDE); > - if( ptrn == null ) ptrn = ""; > - m_excludePattern = compiler.compile(ptrn); > - } > - catch( MalformedPatternException e ) > - { > - throw new PluginException("Illegal pattern detected."); // > FIXME, make a proper error. > - } > + /** The name of the <tt>include</tt> parameter. */ > + public static final String PARAM_INCLUDE = "include"; > > - // > - // Get pages, then sort. > - // > + /** The name of the <tt>itemsPerLine</tt> parameter. */ > + public static final String PARAM_ITEMS_PER_LINE = "itemsPerLine"; > > - final Collection allPages = getAllPagesSortedByName( > wikiContext ); > + /** The name of the <tt>locale</tt> parameter. */ > + public static final String PARAM_LOCALE = "locale"; > > - // > - // Build the page. > - // > - buildIndexPageHeaderAndBody( wikiContext, allPages ); > + /** The character used as a delimiter between page names in > + * the generated list. The default is a comma. */ > + public static char DELIM = ','; > > - StringBuffer res = new StringBuffer(); > + /** > + * When true, locale specifications are checked for availability of > associated > + * resources, throwing a MissingResourceException if the locale > specification > + * is invalid or resources for the specified locale are unavailable. > + * There is a performance hit for performing this check so you may wish > to > + * skip it if the check is unnecessary for your application. The > default value > + * is true. > + */ > + public static boolean CHECK_LOCALE_AVAILABILITY = true; > > - res.append( "<div class=\"index\">\n" ); > - res.append( "<div class=\"header\">\n" ); > - res.append( m_headerPart.toString() ); > - res.append( "</div>\n" ); > - res.append( "<div class=\"body\">\n" ); > - res.append( m_bodyPart.toString() ); > - res.append( "</div>\n</div>\n" ); > + /** > + * When true and no locale is specified (i.e., when simple sorting is > active), > + * comparisons are made using lowercased page names. This uses the Java > + * [EMAIL PROTECTED] java.lang.String#toLowerCase()} method. If a > Locale has been > + * specified (i.e., a Collator is being used) this flag has no effect. > + */ > + public static boolean LOWERCASE_SORT = true; > > - return res.toString(); > - } > + private static final int DEFAULT_ITEMS_PER_LINE = 0; > + private Pattern[] m_pattern_include = null, > + m_pattern_exclude = null; > + private Matcher[] m_matcher_include = null, > + m_matcher_exclude = null; > + private Locale m_locale = null; > + private Collator m_collator = null; > + private int m_maxItemsPerLine; > + private StringBuilder m_body = new StringBuilder(); > + private StringBuilder m_header = new StringBuilder(); > + private boolean m_debug = false; > > + // ............ > > - private void buildIndexPageHeaderAndBody( WikiContext context, > - final Collection allPages ) > + > + public String execute( WikiContext context, Map params ) throws > PluginException > { > - PatternMatcher matcher = new Perl5Matcher(); > + StringBuffer out = new StringBuffer(); > + > + // get parameters .................................................. > + m_debug = > TextUtil.isPositive((String)params.get(PARAM_DEBUG)); > + m_maxItemsPerLine = > TextUtil.parseIntParameter((String)params.get(PARAM_ITEMS_PER_LINE), > + DEFAULT_ITEMS_PER_LINE); > + String param_exclude = (String)params.get(PARAM_EXCLUDE); > + String param_include = (String)params.get(PARAM_INCLUDE); > + String param_locale = (String)params.get(PARAM_LOCALE); > > - for( Iterator i = allPages.iterator (); i.hasNext ();) > + // process parameters .............................................. > + > + try > { > - WikiPage curPage = (WikiPage) i.next(); > + // 'include' regex ................... > + setIncludePatterns(param_include); > > - if( matcher.matches( curPage.getName(), m_includePattern ) ) > - { > - if( !matcher.matches( curPage.getName(), m_excludePattern ) ) > - { > - ++m_currentNofPagesOnLine; > + // 'exclude' regex ................... > + setExcludePatterns(param_exclude); > > - String pageNameFirstLetter = > curPage.getName().substring(0,1).toUpperCase(); > - boolean sameFirstLetterAsPreviousPage = > m_previousPageFirstLetter.equals(pageNameFirstLetter); > + // locale ............................ > + setLocale(param_locale); > > - if( !sameFirstLetterAsPreviousPage ) > - { > - addLetterToIndexHeader( pageNameFirstLetter ); > - addLetterHeaderWithLine( pageNameFirstLetter ); > + // build index > ..................................................... > + > + // get a sorted Set of all page names > + SortedSet pages = new TreeSet( m_collator != null > + ? m_collator > + : new PageSorter() ); > + final ReferenceManager refMgr = > context.getEngine().getReferenceManager(); > + if ( refMgr != null ) { > + pages.addAll( refMgr.findCreated() ); > + } > > - m_currentNofPagesOnLine = 1; > - m_previousPageFirstLetter = pageNameFirstLetter; > - } > + buildIndex(context,pages); > + > + // generate XHTML output > ........................................... > > - addPageToIndex( context, curPage ); > - breakLineIfTooLong(); > + out.append( "<div class=\"index\">\n" ); > + if ( m_debug ) // I18N? > + { > + params.remove(PluginManager.PARAM_BODY); > + params.remove(PluginManager.PARAM_BOUNDS); > + params.remove(PluginManager.PARAM_CMDLINE); > + out.append( "<div class=\"debug\">\n" ); > + out.append( "<h4>" ); > + out.append( "Parameters:" ); > + out.append( "</h4>\n" ); > + out.append( "<p>\n" ); > + for ( int i = 0; i < m_matcher_exclude.length; i++ ) > + { > + out.append( "<b>exclude</b>: " > + + ( m_pattern_exclude[i] != null > + ? m_pattern_exclude[i].pattern() : "not > specified" ) + "<br />\n" ); > + } > + for ( int i = 0; i < m_matcher_include.length; i++ ) > + { > + out.append( "<b>include</b>: " > + + ( m_pattern_include[i] != null > + ? m_pattern_include[i].pattern() : "not > specified" ) + "<br />\n" ); > } > + out.append( "<b>locale</b>: " > + + ( m_locale != null ? m_locale.toString() : "not > specified" ) + "<br />\n" ); > + out.append( "<b>items per line</b>: " > + + m_maxItemsPerLine + ( > params.get(PARAM_ITEMS_PER_LINE) != null > + ? "" : " (default)" ) + "\n" ); > + out.append( "</p>\n" ); > + out.append( "</div>\n" ); > } > - } // for > + > + // write header > + out.append( "<div class=\"header\">\n" ); > + out.append( m_header.toString() ); > + out.append( "\n</div>\n" ); > + > + // write body > + out.append( "<div class=\"body\">\n" ); > + out.append( m_body.toString() ); > + out.append( "\n</div>\n" ); > + > + out.append( "</div>\n" ); > + > + } > + catch ( PatternSyntaxException pse ) // from 'include' or 'exclude' > parameter > + { > + log.error( " invalid regular expression in IndexPlugin: " + > pse.getMessage() ); // I18N > + out.setLength(0); > + out.append( "<div class=\"error\">\n" ); > + out.append( "invalid regular expression in IndexPlugin: " + > pse.getMessage() ); // I18N > + out.append( "</div>\n" ); > + } > + catch ( MissingResourceException mre ) > + { > + log.error( " bad locale specification in IndexPlugin '" > + + param_locale+"': " + mre.getMessage() ); // I18N > + out.setLength(0); > + out.append( "<div class=\"error\">\n" ); > + out.append( "bad locale specification in IndexPlugin '" > + + param_locale+"': " + mre.getMessage() ); // I18N > + out.append( "</div>\n" ); > + } > + catch ( Exception e ) > + { > + log.error( e.getClass().getName() + " thrown by IndexPlugin: " + > e.getMessage() ); // I18N > + out.setLength(0); > + out.append( "<div class=\"error\">\n" ); > + out.append( e.getClass().getName() + " thrown by IndexPlugin: " > + e.getMessage() ); // I18N > + out.append( "</div>\n" ); > + } > + return out.toString(); > } > > > /** > - * Gets all pages, then sorts them. > + * Generates an index based on the provided list of page names, with > + * all other factors provided by method variable parameters. > */ > - static Collection getAllPagesSortedByName( WikiContext wikiContext ) > + private void buildIndex( WikiContext context, final SortedSet pagenames ) > { > - final WikiEngine engine = wikiContext.getEngine(); > + String prevFirstLetter = ""; > + int itemsOnLine = 0; > + m_body.append(" "); > > - final PageManager pageManager = engine.getPageManager(); > - if( pageManager == null ) > - return null; > + for ( Iterator it = pagenames.iterator (); it.hasNext (); ) > + { > + String pagename = (String)it.next(); > > - Collection result = new TreeSet( new Comparator() { > - public int compare( Object o1, Object o2 ) > - { > - if( o1 == null || o2 == null ) return 0; > + boolean include = true; > + boolean exclude = false; > + > + // filter inclusions, then exclusions > + if ( includePage( pagename ) ) { > + if ( !excludePage( pagename ) ) { > > - WikiPage page1 = (WikiPage)o1; > - WikiPage page2 = (WikiPage)o2; > + ++itemsOnLine; > > - return page1.getName().compareTo( page2.getName() ); > + String firstLetter = > pagename.substring(0,1).toUpperCase(); > + > + if ( !prevFirstLetter.equals(firstLetter) ) // if not > same first letter as prev page > + { > + // add letter to index header > + if ( !prevFirstLetter.equals("") ) > + { > + m_header.append( " - " ); > + } > + m_header.append( "<a href=\"#" ); > + m_header.append( firstLetter ); > + m_header.append( "\">" ); > + m_header.append( firstLetter ); > + m_header.append( "</a> " ); > + > + // REMOVE_TRAILING_DELIM at end of previous section > + if ( m_body.charAt(m_body.length()-8) == DELIM ) { > + m_body.setCharAt(m_body.length()-8,' '); > + } > + // add letter header with line > + m_body.append( "\n<br /><br /><span > class=\"section\">" ); > + m_body.append( "<a id=\"" ); > + m_body.append( firstLetter ); > + m_body.append( "\">" ); > + m_body.append( firstLetter ); > + m_body.append( "</a></span><hr />\n" ); > + > + itemsOnLine = 1; > + > + prevFirstLetter = firstLetter; > + } > + > + // add page to index > + // if ( m_maxItemsPerLine == 0 || itemsOnLine >= 2 ) > + if ( itemsOnLine >= 2 ) > + { > + m_body.append( ", \n" ); > + } > + m_body.append( "<a href=\"" ); > + m_body.append( context.getURL( WikiContext.VIEW, > pagename ) ); > + m_body.append( "\">" ); > + m_body.append( context.getEngine().beautifyTitleNoBreak( > pagename ) ); > + m_body.append( "</a>" ); > + > + // break line if too long > + if ( m_maxItemsPerLine == itemsOnLine ) > + { > + m_body.append( DELIM ); // see REMOVE_TRAILING_DELIM > above > + m_body.append( "<br />\n" ); // 7 char length > + itemsOnLine = 0; > + } > + } > } > - }); > + } > + } > > - try > + > + // regex > ................................................................... > + > + > + /** > + * Sets the array of 'exclude' Patterns and Matchers by parsing > + * <tt>regexs</tt> as one or more whitespace-delimited regular > + * expressions. > + */ > + private void setExcludePatterns( String regexs ) > + { > + if ( regexs != null ) > { > - Collection allPages = pageManager.getAllPages(); > - result.addAll( allPages ); > + StringTokenizer st = new StringTokenizer(regexs); > + m_pattern_exclude = new Pattern[st.countTokens()]; > + m_matcher_exclude = new Matcher[st.countTokens()]; > + for ( int i = 0 ; st.hasMoreTokens(); i++ ) > + { > + String regex = st.nextToken(); > + m_pattern_exclude[i] = Pattern.compile(regex); > + m_matcher_exclude[i] = m_pattern_exclude[i].matcher(""); > + } > } > - catch( ProviderException e ) > + } > + > + > + /** > + * Sets the array of 'include' Patterns and Matchers by parsing > + * <tt>regexs</tt> as one or more whitespace-delimited regular > + * expressions. > + */ > + private void setIncludePatterns( String regexs ) > + { > + if ( regexs != null ) > { > - log.fatal("PageProvider is unable to list pages: ", e); > + StringTokenizer st = new StringTokenizer(regexs); > + m_pattern_include = new Pattern[st.countTokens()]; > + m_matcher_include = new Matcher[st.countTokens()]; > + for ( int i = 0 ; st.hasMoreTokens(); i++ ) > + { > + String regex = st.nextToken(); > + m_pattern_include[i] = Pattern.compile(regex); > + m_matcher_include[i] = m_pattern_include[i].matcher(""); > + } > } > - > - return result; > } > > > - private void addLetterToIndexHeader( final String firstLetter ) > + /** > + * Returns true if the wiki page with name <tt>pagename</tt> matches > + * any of the 'exclude' page parameters. > + */ > + private boolean excludePage( String pagename ) > { > - final boolean noLetterYetInTheIndex = ! > "".equals(m_previousPageFirstLetter); > - > - if( noLetterYetInTheIndex ) > + if ( m_matcher_exclude == null ) return true; > + for ( int i = 0; i < m_matcher_exclude.length; i++ ) > { > - m_headerPart.write(" - " ); > + m_matcher_exclude[i].reset(pagename); > + if ( m_matcher_exclude[i].matches() ) return true; > } > - > - m_headerPart.write("<a href=\"#" + firstLetter + "\">" + > firstLetter + "</a>" ); > + return false; > } > > > - private void addLetterHeaderWithLine( final String firstLetter ) > + /** > + * Returns true if the wiki page with name <tt>pagename</tt> matches > + * any of the 'include' page parameters. > + */ > + private boolean includePage( String pagename ) > { > - m_bodyPart.write("\n<br /><br />" + > - "<span class=\"section\">"+ > - "<a name=\"" + firstLetter + "\">"+ > - firstLetter+"</a></span>" + > - "<hr />\n" ); > + if ( m_matcher_include == null ) return true; > + for ( int i = 0; i < m_matcher_include.length; i++ ) > + { > + m_matcher_include[i].reset(pagename); > + if ( m_matcher_include[i].matches() ) return true; > + } > + return false; > } > > - protected void addPageToIndex( WikiContext context, WikiPage curPage ) > - { > - final boolean notFirstPageOnLine = 2 <= m_currentNofPagesOnLine; > > - if( notFirstPageOnLine ) > + // sorting > ................................................................. > + > + > + /** > + * A simple page sorter based on comparing the page names using the > + * Java native [EMAIL PROTECTED] java.lang.String#compareTo(Object)} > method. > + */ > + private class PageSorter implements Comparator > + { > + public int compare( Object o1, Object o2 ) > { > - m_bodyPart.write(", "); > + if ( o1 == null || o2 == null ) return 0; > + String pagename1 = (String)o1; > + String pagename2 = (String)o2; > + return LOWERCASE_SORT > + ? > pagename1.toLowerCase().compareTo(pagename2.toLowerCase()) > + : pagename1.compareTo(pagename2); > } > - > - m_bodyPart.write("<a href=\""+ > - context.getURL(WikiContext.VIEW, > curPage.getName())+"\">"+ > - > context.getEngine().beautifyTitleNoBreak(curPage.getName())+ > - "</a>"); > } > > - protected void breakLineIfTooLong() > - { > - final boolean limitReached = m_itemsPerLine == > m_currentNofPagesOnLine; > > - if( limitReached ) > + /** > + * Sets the Locale for the given locale specification, creating an > + * associated Collator to be used for sorting. > + * > + * @param locale the Locale specification, e.g., "en" or "en_US". A null > + * parameter sets no locale; an empty string uses the > default > + * locale. The underscore character can be used as a > + * delimiter between ISO 639 language (lowercase) and ISO > + * 3166 (uppercase) country codes. > + * @see #CHECK_LOCALE_AVAILABILITY > + * @throws java.util.MissingResourceException if the locale > specification > + * is invalid or the resources for the specified Locale > are > + * unavailable. > + */ > + protected void setLocale( String locale ) > + { > + if ( locale != null ) > { > - m_bodyPart.write( "<br />\n" ); > - m_currentNofPagesOnLine = 0; > + int underscore = locale.indexOf('_'); > + if ( locale.trim().length() == 0 ) > + { > + m_locale = Locale.getDefault(); // use default locale > + } > + else if ( underscore == -1 ) > + { > + m_locale = new Locale(locale); > + } > + else > + { > + m_locale = new Locale(locale.substring(0,underscore), > + locale.substring(underscore+1)); > + } > + if ( CHECK_LOCALE_AVAILABILITY ) > + { > + Locale[] locales = Collator.getAvailableLocales(); > + for ( int i = 0; i < locales.length; i++ ) > + { > + if ( ((Locale)locales[i]).equals(m_locale) ) > + { > + m_collator = Collator.getInstance(m_locale); > + return; > + } > + } > + // not found > + m_locale = null; > + throw new MissingResourceException( > + "locale specification invalid, unknown or resources > unavailable.", // I18N > + m_locale.getClass().getName(), locale ); > + } > + else > + { > + m_collator = Collator.getInstance(m_locale); > + } > } > } > > -} > + > +} // end org.ceryle.wiki.plugin.IndexPlugin
