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