Index: xwiki-platform-core/xwiki-core/pom.xml =================================================================== --- xwiki-platform-core/xwiki-core/pom.xml (revision 5683) +++ xwiki-platform-core/xwiki-core/pom.xml (working copy) @@ -485,6 +485,11 @@ xwiki-core-component ${version} + + joda-time + joda-time + 1.4 + Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/StatsService.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/StatsService.java (revision 0) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/StatsService.java (revision 0) @@ -0,0 +1,275 @@ +/* + * See the NOTICE file distributed with this work for additional + * information regarding copyright ownership. + * + * This is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this software; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA, or see the FSF site: http://www.fsf.org. + * + */ +package com.xpn.xwiki.api; + +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.joda.time.DateTime; + +import com.xpn.xwiki.XWikiContext; +import com.xpn.xwiki.stats.api.XWikiStatsService; +import com.xpn.xwiki.stats.impl.DocumentStats; + +/** + * Statistics api. The statistics module need to be activated (xwiki.stats=1 in xwiki.cfg) + */ +public class StatsService extends Api +{ + public StatsService(XWikiContext context) + { + super(context); + } + + /** + * Retrieve all-time statistics for top pages + * + * @param action Can be "view", "save", etc. + * @param space The space from which to consider pages. If space is the empty string or + * null then the whole wiki is considered. + * @param count The number of page stats to retrieve. + * @return a list of document stats + */ + public List getTopPages(String action, String space, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getTopPages(action, space, count, context); + } + + /** + * Retrieve annual statistics for top pages + * + * @see #getTopPages(String, String, int) + */ + public List getYearTopPages(String action, String space, DateTime year, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getYearTopPages(action, space, year, count, context); + } + + /** + * Retrieve monthly statistics for top pages + * + * @see #getTopPages(String, String, int) + */ + public List getMonthTopPages(String action, String space, DateTime month, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getMonthTopPages(action, space, month, count, context); + } + + /** + * Retrieve weekly statistics for top pages + * + * @see #getTopPages(String, String, int) + */ + public List getWeekTopPages(String action, String space, DateTime week, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getWeekTopPages(action, space, week, count, context); + } + + /** + * Retrieve daily statistics for top pages + * + * @see #getTopPages(String, String, int) + */ + public List getDayTopPages(String action, String space, DateTime day, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getDayTopPages(action, space, day, count, context); + } + + /** + * Retrieve all-time statistics for top contributors + * + * @param space The space in which to look for contributions. If space is the empty string or + * null then the whole wiki is considered. + * @param count The number of user stats to retrieve + * @return a list of user stats + */ + public List getTopContributors(String space, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getTopContributors(space, count, context); + } + + /** + * Retrieve annual statistics for top contributors + * + * @see #getTopContributors(String, int) + */ + public List getYearTopContributors(String space, DateTime year, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getYearTopContributors(space, year, count, context); + } + + /** + * Retrieve monthly statistics for top contributors + * + * @see #getTopContributors(String, int) + */ + public List getMonthTopContributors(String space, DateTime month, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getMonthTopContributors(space, month, count, context); + } + + /** + * Retrieve weekly statistics for top contributors + * + * @see #getTopContributors(String, int) + */ + public List getWeekTopContributors(String space, DateTime week, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getWeekTopContributors(space, week, count, context); + } + + /** + * Retrieve daily statistics for top contributors + * + * @see #getTopContributors(String, int) + */ + public List getDayTopContributors(String space, DateTime day, int count) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getDayTopContributors(space, day, count, context); + } + + /** + * Retrieve the annual evolution of the specified activity over a period of time + * + * @param action Can be "view", "save", etc. + * @param docOrSpace The (full)name of a document or space or the empty string / null for the + * whole wiki + * @param startYear The start date + * @param endYear The end date + * @param yearInterval The sample rate (e.g. at every 2 years) + * @return a map of (date, actionCount) pairs + */ + public Map getActivityPerYear(String action, String docOrSpace, DateTime startYear, + DateTime endYear, int yearInterval) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_MAP; + return stats.getActivityPerYear(action, docOrSpace, startYear, endYear, yearInterval, + context); + } + + /** + * Retrieve the monthly evolution of the specified activity over a period of time + * + * @see #getActivityPerYear(String, String, DateTime, DateTime, int) + */ + public Map getActivityPerMonth(String action, String docOrSpace, DateTime startMonth, + DateTime endMonth, int monthInterval) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_MAP; + return stats.getActivityPerMonth(action, docOrSpace, startMonth, endMonth, monthInterval, + context); + } + + /** + * Retrieve the weekly evolution of the specified activity over a period of time + * + * @see #getActivityPerYear(String, String, DateTime, DateTime, int) + */ + public Map getActivityPerWeek(String action, String docOrSpace, DateTime startWeek, + DateTime endWeek, int weekInterval) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_MAP; + return stats.getActivityPerWeek(action, docOrSpace, startWeek, endWeek, weekInterval, + context); + } + + /** + * Retrieve the daily evolution of the specified activity over a period of time + * + * @see #getActivityPerYear(String, String, DateTime, DateTime, int) + */ + public Map getActivityPerDay(String action, String docOrSpace, DateTime startDay, + DateTime endDay, int dayInterval) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_MAP; + return stats + .getActivityPerDay(action, docOrSpace, startDay, endDay, dayInterval, context); + } + + /** + * API to access the current starts for the Wiki for a specific action It retrieves the number + * of times the action was performed for the whole wiki. + * + * @param action action for which to retrieve statistics (view/save/download) + * @return A DocumentStats object with number of actions performed, unique visitors, number of + * visits + */ + public DocumentStats getCurrentMonthXWikiStats(String action) + { + return getXWikiContext().getWiki().getStatsService(getXWikiContext()).getDocMonthStats( + "", action, new Date(), getXWikiContext()); + } + + /** + * Returns the recently visited pages for a specific action + * + * @param action ("view" or "edit") + * @param size how many recent actions to retrieve + * @return a ArrayList of document names + */ + public java.util.Collection getRecentActions(String action, int size) + { + XWikiStatsService stats = getXWikiContext().getWiki().getStatsService(getXWikiContext()); + if (stats == null) + return Collections.EMPTY_LIST; + return stats.getRecentActions(action, size, getXWikiContext()); + } +} Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/XWiki.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/XWiki.java (revision 5683) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/api/XWiki.java (working copy) @@ -50,6 +50,11 @@ protected static final Log LOG = LogFactory.getLog(XWiki.class); private com.xpn.xwiki.XWiki xwiki; + + /** + * @see #getStatsService() + */ + private StatsService statsService; /** * XWiki API Constructor @@ -61,6 +66,7 @@ { super(context); this.xwiki = xwiki; + this.statsService = new StatsService(context); } /** @@ -1821,6 +1827,7 @@ * @param action action for which to retrieve statistics (view/save/download) * @return A DocumentStats object with number of actions performed, unique visitors, number of * visits + * @deprecated use {@link #getStatsService()} instead */ public DocumentStats getCurrentMonthXWikiStats(String action) { @@ -2099,6 +2106,7 @@ * @param action ("view" or "edit") * @param size how many recent actions to retrieve * @return a ArrayList of document names + * @deprecated use {@link #getStatsService()} instead */ public java.util.Collection getRecentActions(String action, int size) { @@ -2933,4 +2941,14 @@ long c = Long.parseLong(a) + Long.parseLong(b); return "" + c; } + + /** + * Access statistics api + * + * @return a StatsService instance that can be used to retrieve different xwiki statistics + */ + public StatsService getStatsService() + { + return this.statsService; + } } Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/api/XWikiStatsService.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/api/XWikiStatsService.java (revision 5683) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/api/XWikiStatsService.java (working copy) @@ -21,6 +21,13 @@ package com.xpn.xwiki.stats.api; +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.Map; + +import org.joda.time.DateTime; + import com.xpn.xwiki.XWikiContext; import com.xpn.xwiki.XWikiException; import com.xpn.xwiki.notify.XWikiActionNotificationInterface; @@ -26,10 +33,6 @@ import com.xpn.xwiki.notify.XWikiActionNotificationInterface; import com.xpn.xwiki.stats.impl.DocumentStats; -import java.util.Collection; -import java.util.Date; -import java.util.List; - public interface XWikiStatsService extends XWikiActionNotificationInterface { public void init(XWikiContext context); public DocumentStats getDocTotalStats(String docname, String action, XWikiContext context); @@ -37,4 +40,85 @@ public DocumentStats getDocDayStats(String docname, String action, Date day, XWikiContext context); public List getRefMonthStats(String docName, Date month, XWikiContext context) throws XWikiException; public Collection getRecentActions(String action, int size, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getTopPages(String, String, int) + */ + List getTopPages(String action, String space, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getYearTopPages(String, String, DateTime, int) + */ + List getYearTopPages(String action, String space, DateTime year, int count, + XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getMonthTopPages(String, String, DateTime, int) + */ + List getMonthTopPages(String action, String space, DateTime month, int count, + XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getWeekTopPages(String, String, DateTime, int) + */ + List getWeekTopPages(String action, String space, DateTime week, int count, + XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getDayTopPages(String, String, DateTime, int) + */ + List getDayTopPages(String action, String space, DateTime day, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getTopContributors(String, int) + */ + List getTopContributors(String space, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getYearTopContributors(String, DateTime, int) + */ + List getYearTopContributors(String space, DateTime year, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getMonthTopContributors(String, DateTime, int) + */ + List getMonthTopContributors(String space, DateTime month, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getWeekTopContributors(String, DateTime, int) + */ + List getWeekTopContributors(String space, DateTime week, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getDayTopContributors(String, DateTime, int) + */ + List getDayTopContributors(String space, DateTime day, int count, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getActivityPerYear(String, String, DateTime, DateTime, + * int) + */ + Map getActivityPerYear(String action, String docOrSpace, DateTime startYear, + DateTime endYear, int yearInterval, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getActivityPerMonth(String, String, DateTime, DateTime, + * int) + */ + Map getActivityPerMonth(String action, String docOrSpace, DateTime startMonth, + DateTime endMonth, int monthInterval, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getActivityPerWeek(String, String, DateTime, DateTime, + * int) + */ + Map getActivityPerWeek(String action, String docOrSpace, DateTime startWeek, + DateTime endWeek, int weekInterval, XWikiContext context); + + /** + * @see com.xpn.xwiki.api.StatsService#getActivityPerDay(String, String, DateTime, DateTime, + * int) + */ + Map getActivityPerDay(String action, String docOrSpace, DateTime startDay, DateTime endDay, + int dayInterval, XWikiContext context); } Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/StatsUtil.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/StatsUtil.java (revision 5683) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/StatsUtil.java (working copy) @@ -24,6 +24,8 @@ import java.util.Calendar; import java.util.Date; +import org.joda.time.DateTime; + /** * Utility class for statistics * @@ -62,4 +64,12 @@ + cal.get(Calendar.DAY_OF_MONTH); } } + + /** + * @see #getPeriodAsInt(Date, int) + */ + public static int getPeriodAsInt(DateTime period, int type) + { + return getPeriodAsInt(new Date(period.getMillis()), type); + } } Index: xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/XWikiStatsServiceImpl.java =================================================================== --- xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/XWikiStatsServiceImpl.java (revision 5694) +++ xwiki-platform-core/xwiki-core/src/main/java/com/xpn/xwiki/stats/impl/XWikiStatsServiceImpl.java (working copy) @@ -27,6 +27,9 @@ import com.xpn.xwiki.notify.XWikiActionRule; import com.xpn.xwiki.notify.XWikiNotificationRule; import com.xpn.xwiki.stats.api.XWikiStatsService; +import com.xpn.xwiki.stats.impl.DocumentStats; +import com.xpn.xwiki.stats.impl.StatsUtil; +import com.xpn.xwiki.stats.impl.VisitStats; import com.xpn.xwiki.store.XWikiHibernateStore; import com.xpn.xwiki.store.XWikiStoreInterface; import com.xpn.xwiki.store.jcr.XWikiJcrStore; @@ -43,6 +46,8 @@ import org.apache.portals.graffito.jcr.query.QueryManager; import org.hibernate.Query; import org.hibernate.Session; +import org.joda.time.DateTime; +import org.joda.time.MutableDateTime; import javax.servlet.http.Cookie; import javax.servlet.http.HttpSession; @@ -53,6 +58,16 @@ public class XWikiStatsServiceImpl implements XWikiStatsService { private static final Log log = LogFactory.getLog(XWikiStatsServiceImpl.class); + + /** + * The minimum date considered when retrieving all-time statistics + */ + private static final DateTime MIN_DATE = new DateTime(1000, 1, 1, 0, 0, 0, 0); + + /** + * The maximum date considered when retrieving all-time statistics + */ + private static final DateTime MAX_DATE = new DateTime(9999, 12, 31, 23, 59, 59, 999); public static Date expirationDate; public static String[] cookieDomains; @@ -565,7 +580,450 @@ context.getResponse().addCookie(cookie); return cookie; } + + /** + * Retrieves top document statistics for the specified action. + * + * @param action the action for which to retrieve the statistics; it can be one 'view', 'save' + * or 'download' + * @param name [spaceName|%](.[pageName|%])? + * @param startDate the start date + * @param endDate the end date + * @param periodType the type of period; it can be + * {@link com.xpn.xwiki.stats.impl.StatsUtil#PERIOD_MONTH} or + * {@link com.xpn.xwiki.stats.impl.StatsUtil#PERIOD_DAY} + * @param count the maximum number of statistics to retrieve + * @param context the xwiki context + * @return a list of {@link com.xpn.xwiki.stats.impl.DocumentStats} objects + */ + private List getDocumentStats(String action, String name, DateTime startDate, + DateTime endDate, int periodType, int count, XWikiContext context) + { + XWikiHibernateStore store = null; + try { + store = context.getWiki().getHibernateStore(); + store.beginTransaction(context); + Session session = store.getSession(context); + Query query = + session + .createQuery("select name, sum(pageViews) from DocumentStats where action=:action and name like :name and :startDate <= period and period <= :endDate group by name order by sum(pageViews) desc"); + query.setString("action", action); + query.setString("name", name); + query.setInteger("startDate", StatsUtil.getPeriodAsInt(startDate, periodType)); + query.setInteger("endDate", StatsUtil.getPeriodAsInt(endDate, periodType)); + + return getDocumentStats(store.search(query, count, 0, context), action); + } catch (XWikiException e) { + return Collections.EMPTY_LIST; + } finally { + try { + store.endTransaction(context, false); + } catch (Exception e) { + } + } + } + + /** + * Converts the rows retrieved from the database to a list of DocumentStats instances + * + * @param resultSet the result of a database query for document statistics + * @param action the action for which the statistics were retrieved + * @return a list of {@link com.xpn.xwiki.stats.impl.DocumentStats} objects + * @see #getDocumentStats(String, String, DateTime, DateTime, int, int, XWikiContext) + */ + private List getDocumentStats(List resultSet, String action) + { + Date now = Calendar.getInstance().getTime(); + List stats = new ArrayList(resultSet.size()); + Iterator it = resultSet.iterator(); + while (it.hasNext()) { + Object[] result = (Object[]) it.next(); + // We can't represent a custom period (e.g. year, week or some time interval) in the + // database and thus we use a default one, which sould be ignored + DocumentStats docStats = + new DocumentStats((String) result[0], action, now, StatsUtil.PERIOD_DAY); + docStats.setPageViews(((Integer) result[1]).intValue()); + stats.add(docStats); + } + return stats; + } + + /** + * Useful for retrieving statistics for an entire space or the whole wiki + */ + private String getSpacePattern(String spaceName) + { + if (spaceName == null || spaceName.equals("")) { + spaceName = "%"; + } + return spaceName + ".%"; + } + + /** + * Retrieves top visitor statistics for the specified action. + * + * @param action the action for which to retrieve the statistics; it can be one 'view', 'save' + * or 'download' + * @param startDate the start date + * @param endDate the end date + * @param count the maximum number of statistics to retrieve + * @param context the xwiki context + * @return a list of {@link com.xpn.xwiki.stats.impl.VisitStats} objects + */ + private List getVisitStats(String action, DateTime startDate, DateTime endDate, int count, + XWikiContext context) + { + String orderByClause = + "order by sum(pageSaves) desc, sum(pageViews) desc, sum(downloads) desc"; + if (action.equals("save")) { + orderByClause = "order by sum(pageSaves) desc"; + } else if (action.equals("view")) { + orderByClause = "order by sum(pageViews) desc"; + } else if (action.equals("download")) { + orderByClause = "order by sum(downloads) desc"; + } + XWikiHibernateStore store = null; + try { + store = context.getWiki().getHibernateStore(); + store.beginTransaction(context); + Session session = store.getSession(context); + Query query = + session + .createQuery("select name, uniqueID, cookie, IP, userAgent, sum(pageSaves), sum(pageViews), sum(downloads) from VisitStats where :startDate <= startDate and endDate < :endDate group by name " + + orderByClause); + query.setDate("startDate", new Date(startDate.getMillis())); + query.setDate("endDate", new Date(endDate.getMillis())); + return getVisitStats(store.search(query, count, 0, context), startDate, endDate); + } catch (XWikiException e) { + return Collections.EMPTY_LIST; + } finally { + try { + store.endTransaction(context, false); + } catch (Exception e) { + } + } + } + + /** + * Converts the rows retrieved from the database to a list of VisitStats instances + * + * @param resultSet the result of a database query for visitor statistics + * @param startDate the start date used in the query + * @param endDate the end date used in the query + * @return a list of {@link com.xpn.xwiki.stats.impl.VisitStats} objects + * @see #getVisitStats(String, DateTime, DateTime, int, XWikiContext) + */ + private List getVisitStats(List resultSet, DateTime startDate, DateTime endDate) + { + List stats = new ArrayList(resultSet.size()); + Iterator it = resultSet.iterator(); + while (it.hasNext()) { + Object[] result = (Object[]) it.next(); + String name = (String) result[0]; + String uniqueID = (String) result[1]; + String cookie = (String) result[2]; + String ip = (String) result[3]; + String userAgent = (String) result[4]; + int pageSaves = ((Integer) result[5]).intValue(); + int pageViews = ((Integer) result[6]).intValue(); + int downloads = ((Integer) result[7]).intValue(); + VisitStats vs = + new VisitStats(name, uniqueID, cookie, ip, userAgent, new Date(startDate + .getMillis()), StatsUtil.PERIOD_DAY); + vs.setStartDate(new Date(startDate.getMillis())); + vs.setEndDate(new Date(endDate.getMillis())); + vs.setPageSaves(pageSaves); + vs.setPageViews(pageViews); + vs.setDownloads(downloads); + stats.add(vs); + } + return stats; + } + + private static MutableDateTime toDayStart(MutableDateTime mdt) + { + mdt.setHourOfDay(mdt.hourOfDay().getMinimumValue()); + mdt.setMinuteOfHour(mdt.minuteOfHour().getMinimumValue()); + mdt.setSecondOfMinute(mdt.secondOfMinute().getMinimumValue()); + mdt.setMillisOfSecond(mdt.millisOfSecond().getMinimumValue()); + return mdt; + } + + private static MutableDateTime toDayEnd(MutableDateTime mdt) + { + mdt.addDays(1); + return toDayStart(mdt); + } + + private static MutableDateTime toWeekStart(MutableDateTime mdt) + { + mdt.setDayOfWeek(mdt.dayOfWeek().getMinimumValue()); + return toDayStart(mdt); + } + + private static MutableDateTime toWeekEnd(MutableDateTime mdt) + { + mdt.setDayOfWeek(mdt.dayOfWeek().getMaximumValue()); + return toDayEnd(mdt); + } + + private static MutableDateTime toMonthStart(MutableDateTime mdt) + { + mdt.setDayOfMonth(mdt.dayOfMonth().getMinimumValue()); + return toDayStart(mdt); + } + + private static MutableDateTime toMonthEnd(MutableDateTime mdt) + { + mdt.setDayOfMonth(mdt.dayOfMonth().getMaximumValue()); + return toDayEnd(mdt); + } + + private static MutableDateTime toYearStart(MutableDateTime mdt) + { + mdt.setDayOfYear(mdt.dayOfYear().getMinimumValue()); + return toDayStart(mdt); + } + + private static MutableDateTime toYearEnd(MutableDateTime mdt) + { + mdt.setDayOfYear(mdt.dayOfYear().getMaximumValue()); + return toDayEnd(mdt); + } + + /** + * {@inheritDoc} + */ + public Map getActivityPerDay(String action, String docOrSpace, DateTime startDay, + DateTime endDay, int dayInterval, XWikiContext context) + { + MutableDateTime start = toDayStart(startDay.toMutableDateTime()); + MutableDateTime end = toDayEnd(endDay.toMutableDateTime()); + Map activity = new HashMap(); + int index = 0, actionCount = 0; + while (start.compareTo(end) < 0) { + DateTime current = start.toDateTime(); + List stats = + this.getDocumentStats(action, docOrSpace, current, current, StatsUtil.PERIOD_DAY, + 1, context); + if (stats.size() > 0) { + actionCount += ((DocumentStats) stats.get(0)).getPageViews(); + } + if (++index % dayInterval == 0) { + activity.put(current, new Integer(actionCount)); + actionCount = 0; + } + start.addDays(1); + } + if (index % dayInterval != 0) { + activity.put(start.toDateTime(), new Integer(actionCount)); + } + return activity; + } -} + /** + * {@inheritDoc} + */ + public Map getActivityPerMonth(String action, String docOrSpace, DateTime startMonth, + DateTime endMonth, int monthInterval, XWikiContext context) + { + MutableDateTime start = toMonthStart(startMonth.toMutableDateTime()); + MutableDateTime end = toMonthEnd(endMonth.toMutableDateTime()); + Map activity = new HashMap(); + int index = 0, actionCount = 0; + while (start.compareTo(end) < 0) { + DateTime current = start.toDateTime(); + List stats = + this.getDocumentStats(action, docOrSpace, current, current, + StatsUtil.PERIOD_MONTH, 1, context); + if (stats.size() > 0) { + actionCount += ((DocumentStats) stats.get(0)).getPageViews(); + } + if (++index % monthInterval == 0) { + activity.put(current, new Integer(actionCount)); + actionCount = 0; + } + start.addMonths(1); + } + if (index % monthInterval != 0) { + activity.put(start.toDateTime(), new Integer(actionCount)); + } + return activity; + } + /** + * {@inheritDoc} + */ + public Map getActivityPerWeek(String action, String docOrSpace, DateTime startWeek, + DateTime endWeek, int weekInterval, XWikiContext context) + { + MutableDateTime start = toWeekStart(startWeek.toMutableDateTime()); + MutableDateTime end = toWeekEnd(endWeek.toMutableDateTime()); + Map activity = new HashMap(); + int index = 0, actionCount = 0; + while (start.compareTo(end) < 0) { + DateTime current = start.toDateTime(); + List stats = + this.getDocumentStats(action, docOrSpace, current, toWeekEnd( + current.toMutableDateTime()).toDateTime(), StatsUtil.PERIOD_DAY, 1, context); + if (stats.size() > 0) { + actionCount += ((DocumentStats) stats.get(0)).getPageViews(); + } + if (++index % weekInterval == 0) { + activity.put(current, new Integer(actionCount)); + actionCount = 0; + } + start.addWeeks(1); + } + if (index % weekInterval != 0) { + activity.put(start.toDateTime(), new Integer(actionCount)); + } + return activity; + } + /** + * {@inheritDoc} + */ + public Map getActivityPerYear(String action, String docOrSpace, DateTime startYear, + DateTime endYear, int yearInterval, XWikiContext context) + { + MutableDateTime start = toYearStart(startYear.toMutableDateTime()); + MutableDateTime end = toYearEnd(endYear.toMutableDateTime()); + Map activity = new HashMap(); + int index = 0, actionCount = 0; + while (start.compareTo(end) < 0) { + DateTime current = start.toDateTime(); + List stats = + this + .getDocumentStats(action, docOrSpace, current, toYearEnd( + current.toMutableDateTime()).toDateTime(), StatsUtil.PERIOD_MONTH, 1, + context); + if (stats.size() > 0) { + actionCount += ((DocumentStats) stats.get(0)).getPageViews(); + } + if (++index % yearInterval == 0) { + activity.put(current, new Integer(actionCount)); + actionCount = 0; + } + start.addYears(1); + } + if (index % yearInterval != 0) { + activity.put(start.toDateTime(), new Integer(actionCount)); + } + return activity; + } + + /** + * {@inheritDoc} + */ + public List getDayTopContributors(String space, DateTime day, int count, XWikiContext context) + { + MutableDateTime mdt = day.toMutableDateTime(); + DateTime startDate = toDayStart(mdt).toDateTime(); + DateTime endDate = toDayEnd(mdt).toDateTime(); + + // Currently, the space parameter is ignored + return getVisitStats("save", startDate, endDate, count, context); + } + + /** + * {@inheritDoc} + */ + public List getDayTopPages(String action, String space, DateTime day, int count, + XWikiContext context) + { + return getDocumentStats(action, getSpacePattern(space), day, day, StatsUtil.PERIOD_DAY, + count, context); + } + + /** + * {@inheritDoc} + */ + public List getMonthTopContributors(String space, DateTime month, int count, + XWikiContext context) + { + MutableDateTime mdt = month.toMutableDateTime(); + DateTime startDate = toMonthStart(mdt).toDateTime(); + DateTime endDate = toMonthEnd(mdt).toDateTime(); + + // Currently, the space parameter is ignored + return getVisitStats("save", startDate, endDate, count, context); + } + + /** + * {@inheritDoc} + */ + public List getMonthTopPages(String action, String space, DateTime month, int count, + XWikiContext context) + { + return getDocumentStats(action, getSpacePattern(space), month, month, + StatsUtil.PERIOD_MONTH, count, context); + } + + /** + * {@inheritDoc} + */ + public List getTopContributors(String space, int count, XWikiContext context) + { + return getVisitStats("save", MIN_DATE, MAX_DATE, count, context); + } + + /** + * {@inheritDoc} + */ + public List getTopPages(String action, String space, int count, XWikiContext context) + { + return getDocumentStats(action, getSpacePattern(space), MIN_DATE, MAX_DATE, + StatsUtil.PERIOD_MONTH, count, context); + } + + /** + * {@inheritDoc} + */ + public List getWeekTopContributors(String space, DateTime week, int count, + XWikiContext context) + { + MutableDateTime mdt = week.toMutableDateTime(); + DateTime startDate = toWeekStart(mdt).toDateTime(); + DateTime endDate = toWeekEnd(mdt).toDateTime(); + + // Currently, the space parameter is ignored + return getVisitStats("save", startDate, endDate, count, context); + } + + /** + * {@inheritDoc} + */ + public List getWeekTopPages(String action, String space, DateTime week, int count, + XWikiContext context) + { + return getDocumentStats(action, getSpacePattern(space), week.withDayOfWeek(week + .dayOfWeek().getMinimumValue()), week.withDayOfWeek(week.dayOfWeek() + .getMaximumValue()), StatsUtil.PERIOD_DAY, count, context); + } + + /** + * {@inheritDoc} + */ + public List getYearTopContributors(String space, DateTime year, int count, + XWikiContext context) + { + MutableDateTime mdt = year.toMutableDateTime(); + DateTime startDate = toYearStart(mdt).toDateTime(); + DateTime endDate = toYearEnd(mdt).toDateTime(); + + // Currently, the space parameter is ignored + return getVisitStats("save", startDate, endDate, count, context); + } + + /** + * {@inheritDoc} + */ + public List getYearTopPages(String action, String space, DateTime year, int count, + XWikiContext context) + { + return getDocumentStats(action, getSpacePattern(space), year.withMonthOfYear(year + .monthOfYear().getMinimumValue()), year.withMonthOfYear(year.monthOfYear() + .getMaximumValue()), StatsUtil.PERIOD_MONTH, count, context); + } +} \ No newline at end of file