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