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 java.text.SimpleDateFormat;
022import java.util.Calendar;
023import java.util.Collection;
024import java.util.Comparator;
025import java.util.Date;
026import java.util.Iterator;
027import java.util.List;
028import java.util.Map;
029import java.util.SortedSet;
030import java.util.TreeSet;
031
032import org.apache.log4j.Logger;
033import org.apache.wiki.WikiContext;
034import org.apache.wiki.WikiEngine;
035import org.apache.wiki.WikiPage;
036import org.apache.wiki.api.exceptions.PluginException;
037import org.apache.wiki.api.exceptions.ProviderException;
038import org.apache.wiki.api.plugin.WikiPlugin;
039import org.apache.wiki.util.TextUtil;
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 WikiPlugin
052{
053    private static Logger     log = Logger.getLogger(WeblogArchivePlugin.class);
054
055    /** Parameter name for setting the page.  Value is <tt>{@value}</tt>. */
056    public static final String PARAM_PAGE = "page";
057
058    private SimpleDateFormat m_monthUrlFormat;
059
060    /**
061     *  {@inheritDoc}
062     */
063    public String execute( WikiContext context, Map<String, String> params )
064        throws PluginException
065    {
066        WikiEngine engine = context.getEngine();
067
068        //
069        //  Parameters
070        //
071        String weblogName = params.get( PARAM_PAGE );
072
073        if( weblogName == null ) weblogName = context.getPage().getName();
074
075
076        m_monthUrlFormat = new SimpleDateFormat("'"+
077                                                context.getURL( WikiContext.VIEW, weblogName,
078                                                                "weblog.startDate='ddMMyy'&amp;weblog.days=%d")+"'");
079
080        StringBuilder sb = new StringBuilder();
081
082        sb.append( "<div class=\"weblogarchive\">\n" );
083
084
085        //
086        //  Collect months that have blog entries
087        //
088
089        try
090        {
091            Collection< Calendar > months = collectMonths( engine, weblogName );
092            int year = 0;
093
094            //
095            //  Output proper HTML.
096            //
097
098            sb.append( "<ul>\n" );
099
100            if( months.size() > 0 )
101            {
102                year = (months.iterator().next()).get( Calendar.YEAR );
103
104                sb.append( "<li class=\"archiveyear\">"+year+"</li>\n" );
105            }
106
107            for( Iterator< Calendar > i = months.iterator(); i.hasNext(); )
108            {
109                Calendar cal = i.next();
110
111                if( cal.get( Calendar.YEAR ) != year )
112                {
113                    year = cal.get( Calendar.YEAR );
114
115                    sb.append( "<li class=\"archiveyear\">"+year+"</li>\n" );
116                }
117
118                sb.append( "  <li>" );
119
120                sb.append( getMonthLink( cal ) );
121
122                sb.append( "</li>\n" );
123            }
124
125            sb.append( "</ul>\n" );
126        }
127        catch( ProviderException ex )
128        {
129            log.info( "Cannot get archive", ex );
130            sb.append("Cannot get archive: "+ex.getMessage());
131        }
132
133        sb.append( "</div>\n" );
134
135        return sb.toString();
136    }
137
138    private SortedSet< Calendar > collectMonths( WikiEngine engine, String page )
139        throws ProviderException
140    {
141        Comparator< Calendar > comp = new ArchiveComparator();
142        TreeSet<Calendar> res = new TreeSet<Calendar>( comp );
143
144        WeblogPlugin pl = new WeblogPlugin();
145
146        List< WikiPage > blogEntries = pl.findBlogEntries( engine, page, new Date(0L), new Date() );
147
148        for( Iterator< WikiPage > i = blogEntries.iterator(); i.hasNext(); )
149        {
150            WikiPage p = i.next();
151
152            // FIXME: Not correct, should parse page creation time.
153
154            Date d = p.getLastModified();
155            Calendar cal = Calendar.getInstance();
156            cal.setTime( d );
157            res.add( cal );
158        }
159
160        return res;
161    }
162
163    private String getMonthLink( Calendar day )
164    {
165        SimpleDateFormat monthfmt = new SimpleDateFormat( "MMMM" );
166        String result;
167
168        if( m_monthUrlFormat == null )
169        {
170            result = monthfmt.format( day.getTime() );
171        }
172        else
173        {
174            Calendar cal = (Calendar)day.clone();
175            int firstDay = cal.getActualMinimum( Calendar.DATE );
176            int lastDay  = cal.getActualMaximum( Calendar.DATE );
177
178            cal.set( Calendar.DATE, lastDay );
179            String url = m_monthUrlFormat.format( cal.getTime() );
180
181            url = TextUtil.replaceString( url, "%d", Integer.toString( lastDay-firstDay+1 ) );
182
183            result = "<a href=\""+url+"\">"+monthfmt.format(cal.getTime())+"</a>";
184        }
185
186        return result;
187
188    }
189
190
191    /**
192     * This is a simple comparator for ordering weblog archive entries.
193     * Two dates in the same month are considered equal.
194     */
195    private static class ArchiveComparator implements Comparator< Calendar > {
196
197        public int compare( Calendar a, Calendar b )
198        {
199            if( a == null || b == null )
200            {
201                throw new ClassCastException( "Invalid calendar supplied for comparison." );
202            }
203
204            if( a.get( Calendar.YEAR ) == b.get( Calendar.YEAR ) &&
205                a.get( Calendar.MONTH ) == b.get( Calendar.MONTH ) )
206            {
207                return 0;
208            }
209
210            //sort recent dates first
211            return b.getTime().before( a.getTime() ) ? -1 : 1;
212        }
213    }
214}