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