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