/* WhatsNew - a plugin based on RecentChangesPlugin for: JSPWiki - a JSP-based WikiWiki clone. by Janne Jalkanen (Janne.Jalkanen@iki.fi) */ import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.GregorianCalendar; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import com.ecyrd.jspwiki.TextUtil; import com.ecyrd.jspwiki.WikiContext; import com.ecyrd.jspwiki.WikiEngine; import com.ecyrd.jspwiki.WikiPage; import com.ecyrd.jspwiki.attachment.Attachment; import com.ecyrd.jspwiki.plugin.PluginException; import com.ecyrd.jspwiki.plugin.WikiPlugin; import org.apache.ecs.xhtml.a; import org.apache.ecs.xhtml.li; import org.apache.ecs.xhtml.ul; import org.apache.log4j.Logger; /** * Returns the Recent Changes in the form of a simple bullet list. * * Parameters: since=number of days * entries=max number of entries, * width=max width in characters * suffix=string on which to split off page name suffixes * * @author Janne Jalkanen * @author Andre van Dalen * @version 0.1 */ public class WhatsNewPlugin implements WikiPlugin { /** The logger. */ private static Logger log = Logger.getLogger(WhatsNewPlugin.class); /** Name of the 'since' parameter. */ private static final String PARAM_SINCE = "since"; /** Name of the 'entries' parameter. */ private static final String PARAM_MAX_ENTRIES = "entries"; /** Name of the 'width' parameter. */ private static final String PARAM_MAX_WIDTH = "width"; /** Name of the 'suffix' parameter. */ private static final String PARAM_SUFFIX = "suffix"; /** String constant for truncation filler. */ private static final String DOTS = ".."; /** How many days we show by default. */ private static final int DEFAULT_SINCE = 365; /** How many entries we show by default. */ private static final int DEFAULT_MAX_ENTRIES = 16; /** What character width we show by default. */ private static final int DEFAULT_MAX_WIDTH = 64; /** * @see com.ecyrd.jspwiki.plugin.WikiPlugin#execute(com.ecyrd.jspwiki.WikiContext, java.util.Map) */ public String execute(WikiContext context, Map params) throws PluginException { WikiEngine engine = context.getEngine(); Calendar sincedate = new GregorianCalendar(); final int since = TextUtil.parseIntParameter((String) params.get(PARAM_SINCE), DEFAULT_SINCE); int maxEntries = TextUtil.parseIntParameter((String) params.get(PARAM_MAX_ENTRIES), DEFAULT_MAX_ENTRIES); final int maxWidth = TextUtil.parseIntParameter((String) params.get(PARAM_MAX_WIDTH), DEFAULT_MAX_WIDTH); String suffix = (String) params.get(PARAM_SUFFIX); sincedate.add(Calendar.DAY_OF_MONTH, -since); if (log.isDebugEnabled()) { log.debug("Calculating recent changes from " + sincedate.getTime()); } Collection changes = engine.getRecentChanges(); String result = ""; if (null != changes) { Set seen = new HashSet(maxEntries); ul ul = new ul(); ul.setClass("whatsnew"); for (Iterator i = changes.iterator(); i.hasNext() && 0 < maxEntries;) { WikiPage pageref = (WikiPage) i.next(); Date lastmod = pageref.getLastModified(); if (lastmod.before(sincedate.getTime())) { break; } String name = (pageref instanceof Attachment) ? ((Attachment) pageref).getParentName() : pageref.getName(); final int suffixOffset = (null == suffix) ? 0 : name.indexOf(suffix); if (0 < suffixOffset) { name = name.substring(0, suffixOffset); } if (!seen.contains(name)) { seen.add(name); maxEntries--; String link = context.getURL(WikiContext.VIEW, name); String title = fitToWidth(engine.beautifyTitle(name), maxWidth); a linkel = new a(link, title); linkel.setClass("wikipage"); li line = new li().addElement(linkel); ul.addElement(line); } } ul.setPrettyPrint(true); result = ul.toString(); } return result; } /** * Fit a wiki-like string to a maximum width. * * @param value The string the compress if its too long. * @param maxWidth The maximum width in characters. * @return String, the input value compressed to maxWidth characters. */ public String fitToWidth(String value, int maxWidth) { String result = value; if (0 < maxWidth && maxWidth < result.length()) { // first change AaaaBbbbCcc into AaaaB..Cccc by replacing chacacters before the last // Capitalised word with .. final int diff = result.length() - maxWidth + DOTS.length(); final boolean oneChar = (diff > result.length() - 1); int offset = result.length(); while (0 < offset) { if (Character.isUpperCase(result.charAt(--offset))) { break; } } if (0 < offset) { final boolean smallGap = oneChar || (1 >= offset - diff); result = result.substring(0, smallGap ? 1 : offset - diff) + DOTS + result.substring(oneChar || !smallGap ? offset : 1 + diff); } // if that didn't get the desired result, truncate what we got if (maxWidth < result.length()) { result = result.substring(0, maxWidth); } } return result; } }