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'&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 }