    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 */
    019package org.apache.wiki.plugin;
    020
    021import org.apache.wiki.api.core.Context;
    022import org.apache.wiki.api.core.ContextEnum;
    023import org.apache.wiki.api.core.Engine;
    024import org.apache.wiki.api.core.Page;
    025import org.apache.wiki.api.exceptions.PluginException;
    026import org.apache.wiki.api.plugin.Plugin;
    027import org.apache.wiki.util.TextUtil;
    028
    029import java.text.SimpleDateFormat;
    030import java.util.Calendar;
    031import java.util.Collection;
    032import java.util.Comparator;
    033import java.util.Date;
    034import java.util.List;
    035import java.util.Locale;
    036import java.util.Map;
    037import java.util.ResourceBundle;
    038import java.util.SortedSet;
    039import java.util.TreeSet;
    040
    041/**
    042 *  Creates a list of all weblog entries on a monthly basis.
    043 *
    044 *  <p>Parameters : </p>
    045 *  <ul>
    046 *  <li><b>page</b> - the page name</li>
    047 *  </ul>
    048 *
    049 *  @since 1.9.21
    050 */
    051public class WeblogArchivePlugin implements Plugin {
    052
    053    /** Parameter name for setting the page.  Value is <tt>{@value}</tt>. */
    054    public static final String PARAM_PAGE = "page";
    055
    056    private SimpleDateFormat m_monthUrlFormat;
    057
    058    @Override
    059    public String getDisplayName(Locale locale) {
    060        final ResourceBundle rb = ResourceBundle.getBundle(PluginManager.PLUGIN_I18N_RESOURCE, locale);
    061        return rb.getString(this.getClass().getSimpleName());
    062    }
    063
    064    /**
    065     *  {@inheritDoc}
    066     */
    067    @Override
    068    public String execute( final Context context, final Map< String, String > params ) throws PluginException {
    069        final Engine engine = context.getEngine();
    070
    071        //  Parameters
    072        String weblogName = params.get( PARAM_PAGE );
    073
    074        if( weblogName == null ) {
    075            weblogName = context.getPage().getName();
    076        }
    077
    078        final String pttrn = "'" + context.getURL( ContextEnum.PAGE_VIEW.getRequestContext(), weblogName,"weblog.startDate='ddMMyy'&amp;weblog.days=%d" ) + "'";
    079        m_monthUrlFormat = new SimpleDateFormat( pttrn );
    080
    081        final StringBuilder sb = new StringBuilder();
    082        sb.append( "<div class=\"weblogarchive\">\n" );
    083
    084        //  Collect months that have blog entries
    085        final Collection< Calendar > months = collectMonths( engine, weblogName );
    086        int year = 0;
    087
    088        //  Output proper HTML.
    089        sb.append( "<ul>\n" );
    090
    091        if(!months.isEmpty()) {
    092            year = ( months.iterator().next() ).get( Calendar.YEAR );
    093            sb.append( "<li class=\"archiveyear\">" ).append( year ).append( "</li>\n" );
    094        }
    095
    096        for( final Calendar cal : months ) {
    097            if( cal.get( Calendar.YEAR ) != year ) {
    098                year = cal.get( Calendar.YEAR );
    099                sb.append( "<li class=\"archiveyear\">" ).append( year ).append( "</li>\n" );
    100            }
    101            sb.append( "  <li>" );
    102            sb.append( getMonthLink( cal ) );
    103            sb.append( "</li>\n" );
    104        }
    105
    106        sb.append( "</ul>\n" );
    107        sb.append( "</div>\n" );
    108        return sb.toString();
    109    }
    110
    111    private SortedSet< Calendar > collectMonths( final Engine engine, final String page ) {
    112        final Comparator< Calendar > comp = new ArchiveComparator();
    113        final TreeSet<Calendar> res = new TreeSet<>( comp );
    114
    115        final WeblogPlugin pl = new WeblogPlugin();
    116
    117        final List< Page > blogEntries = pl.findBlogEntries( engine, page, new Date(0L), new Date() );
    118
    119        for( final Page p : blogEntries ) {
    120            // FIXME: Not correct, should parse page creation time.
    121            final Date d = p.getLastModified();
    122            final Calendar cal = Calendar.getInstance();
    123            cal.setTime( d );
    124            res.add( cal );
    125        }
    126
    127        return res;
    128    }
    129
    130    private String getMonthLink( final Calendar day )
    131    {
    132        final SimpleDateFormat monthfmt = new SimpleDateFormat( "MMMM" );
    133        final String result;
    134
    135        if( m_monthUrlFormat == null ) {
    136            result = monthfmt.format( day.getTime() );
    137        } else {
    138            final Calendar cal = (Calendar)day.clone();
    139            final int firstDay = cal.getActualMinimum( Calendar.DATE );
    140            final int lastDay  = cal.getActualMaximum( Calendar.DATE );
    141
    142            cal.set( Calendar.DATE, lastDay );
    143            String url = m_monthUrlFormat.format( cal.getTime() );
    144
    145            url = TextUtil.replaceString( url, "%d", Integer.toString( lastDay-firstDay+1 ) );
    146
    147            result = "<a href=\""+url+"\">"+monthfmt.format(cal.getTime())+"</a>";
    148        }
    149
    150        return result;
    151
    152    }
    153
    154
    155    /**
    156     * This is a simple comparator for ordering weblog archive entries.
    157     * Two dates in the same month are considered equal.
    158     */
    159    private static class ArchiveComparator implements Comparator< Calendar > {
    160
    161        @Override
    162        public int compare( final Calendar a, final Calendar b ) {
    163            if( a == null || b == null ) {
    164                throw new ClassCastException( "Invalid calendar supplied for comparison." );
    165            }
    166
    167            if( a.get( Calendar.YEAR ) == b.get( Calendar.YEAR ) && a.get( Calendar.MONTH ) == b.get( Calendar.MONTH ) ) {
    168                return 0;
    169            }
    170
    171            //sort recent dates first
    172            return b.getTime().before( a.getTime() ) ? -1 : 1;
    173        }
    174    }
    175
    176}