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