incubator-jspwiki-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Janne Jalkanen <janne.jalka...@iki.fi>
Subject Re: [jira] Created: (JSPWIKI-246) Remove/replace IndexPlugin
Date Tue, 15 Apr 2008 08:51:14 GMT
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 (Janne.Jalkanen@iki.fi)
> -
> -    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 {@link 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 {@link com.ecyrd.jspwiki.ReferenceManager#findCreated()} rather
> + *      than {@link 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
> +     *  {@link 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( ",&nbsp;\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 {@link java.lang.String#compareTo(Object)} method.
> +     */
> +    private class PageSorter implements Comparator
> +    {
> +        public int compare( Object o1, Object o2 )
>          {
> -            m_bodyPart.write(",&nbsp; ");
> +            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


Mime
View raw message