diff --git a/intrace.appengine/src/org/gaecounter/ActionServlet.java b/intrace.appengine/src/org/gaecounter/ActionServlet.java index 8ef68d1..6729ee0 100644 --- a/intrace.appengine/src/org/gaecounter/ActionServlet.java +++ b/intrace.appengine/src/org/gaecounter/ActionServlet.java @@ -1,76 +1,68 @@ -package org.gaecounter; - -import java.io.IOException; - -import javax.jdo.PersistenceManager; -import javax.jdo.Query; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.gaecounter.data.Counter; -import org.gaecounter.data.PMF; - -public class ActionServlet extends HttpServlet -{ - private static final long serialVersionUID = 1L; - - @Override - protected void doGet(HttpServletRequest xiReq, - HttpServletResponse xiResp) - throws ServletException, - IOException - { - String lAction = xiReq.getParameter("action"); - String lRedir = xiReq.getParameter("redir"); - - if ("clear".equals(lAction) || - "clearfile".equals(lAction)) - { - PersistenceManager pm = PMF.get().getPersistenceManager(); - try - { - Query lDeletion = pm.newQuery(Counter.class); - if ("clearfile".equals(lAction)) - { - String lFile = Utils.dec(xiReq.getParameter("file")); - lDeletion.setFilter("mFile == mFilenameParam"); - lDeletion.declareParameters("String mFilenameParam"); - lDeletion.deletePersistentAll(lFile); - } - else - { - lDeletion.deletePersistentAll(); - } - } - finally - { - pm.close(); - } - } - else if ("testdata".equals(lAction)) - { - CountDownloadsFilter.countDownload("test_0.1.jar", 2010, 1, 1); - CountDownloadsFilter.countDownload("test_0.1.jar", 2010, 1, 1); - CountDownloadsFilter.countDownload("test_0.1.jar", 2010, 1, 2); - CountDownloadsFilter.countDownload("test_0.1.jar", 2010, 2, 2); - CountDownloadsFilter.countDownload("test_0.1.jar", 2010, 3, 2); - CountDownloadsFilter.countDownload("test_0.2.jar", 2010, 4, 2); - CountDownloadsFilter.countDownload("test_0.2.jar", 2010, 5, 2); - CountDownloadsFilter.countDownload("test_0.2.jar", 2010, 5, 2); - CountDownloadsFilter.countDownload("test_0.2.jar", 2010, 6, 2); - CountDownloadsFilter.countDownload("test_0.3.jar", 2011, 1, 1); - CountDownloadsFilter.countDownload("test_0.3.jar", 2011, 1, 1); - CountDownloadsFilter.countDownload("test_0.3.jar", 2011, 1, 2); - CountDownloadsFilter.countDownload("test_0.3.jar", 2011, 2, 2); - CountDownloadsFilter.countDownload("test_0.3.jar", 2011, 3, 2); - CountDownloadsFilter.countDownload("test_0.4.jar", 2011, 4, 2); - CountDownloadsFilter.countDownload("test_0.4.jar", 2011, 5, 2); - CountDownloadsFilter.countDownload("test_0.4.jar", 2011, 5, 2); - CountDownloadsFilter.countDownload("test_0.4.jar", 2011, 6, 2); - } - - xiResp.sendRedirect(lRedir); - } -} +package org.gaecounter; + +import java.io.IOException; + +import javax.jdo.PersistenceManager; +import javax.jdo.Query; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.gaecounter.data.Counter; +import org.gaecounter.data.PMF; + +public class ActionServlet extends HttpServlet +{ + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest xiReq, + HttpServletResponse xiResp) + throws ServletException, + IOException + { + String lAction = xiReq.getParameter("action"); + String lRedir = xiReq.getParameter("redir"); + + if ("clear".equals(lAction) || + "clearfile".equals(lAction)) + { + PersistenceManager pm = PMF.get().getPersistenceManager(); + try + { + Query lDeletion = pm.newQuery(Counter.class); + if ("clearfile".equals(lAction)) + { + String lFile = Utils.dec(xiReq.getParameter("file")); + lDeletion.setFilter("mFile == mFilenameParam"); + lDeletion.declareParameters("String mFilenameParam"); + lDeletion.deletePersistentAll(lFile); + } + else + { + lDeletion.deletePersistentAll(); + } + } + finally + { + pm.close(); + } + } + else if ("testdata".equals(lAction)) + { + for (int ii = 13; ii <= 25; ii++) + CountDownloadsFilter.countDownload("test_0.1.jar", 2012, 2, ii); + for (int ii = 28; ii <= 29; ii++) + CountDownloadsFilter.countDownload("test_0.1.jar", 2012, 2, ii); + for (int ii = 1; ii <= 2; ii++) + CountDownloadsFilter.countDownload("test_0.1.jar", 2012, 3, ii); + for (int ii = 5; ii <= 10; ii++) + CountDownloadsFilter.countDownload("test_0.1.jar", 2012, 3, ii); + for (int ii = 12; ii <= 15; ii++) + CountDownloadsFilter.countDownload("test_0.1.jar", 2012, 3, ii); + } + + xiResp.sendRedirect(lRedir); + } +} diff --git a/intrace.appengine/src/org/gaecounter/data/Counter.java b/intrace.appengine/src/org/gaecounter/data/Counter.java index ca44bbf..e9a3a4f 100644 --- a/intrace.appengine/src/org/gaecounter/data/Counter.java +++ b/intrace.appengine/src/org/gaecounter/data/Counter.java @@ -1,308 +1,307 @@ -package org.gaecounter.data; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import javax.jdo.PersistenceManager; -import javax.jdo.Query; -import javax.jdo.annotations.PersistenceCapable; -import javax.jdo.annotations.Persistent; -import javax.jdo.annotations.PrimaryKey; - -import org.joda.time.DateMidnight; -import org.joda.time.DateTimeConstants; -import org.joda.time.DateTimeFieldType; -import org.joda.time.Days; -import org.joda.time.Partial; -import org.joda.time.Period; - -@PersistenceCapable -public class Counter -{ - public Counter(Type mType, String mDate, String mFile) - { - this.mKey = getKey(mFile, mDate); - this.mType = mType; - this.mDate = mDate; - this.mFile = mFile; - this.mCount = 1; - } - - public static String getKey(String xiFile, String xiDate) - { - return xiFile + "_" + xiDate; - } - - @PrimaryKey - @Persistent - public String mKey; - public enum Type - { - YEAR("yyyy", Period.years(1)) - { - @Override - public Partial getPartial(int y, int m, int d) - { - return new Partial(new DateTimeFieldType[] - {DateTimeFieldType.year()}, - new int[] {y}); - } - }, - MONTH("yyyy/MM", Period.months(1)) - { - @Override - public Partial getPartial(int y, int m, int d) - { - return new Partial(new DateTimeFieldType[] - {DateTimeFieldType.year(), - DateTimeFieldType.monthOfYear()}, - new int[] {y, m}); - } - }, - WEEK("yyyy/MM/dd", Period.days(7)) - { - @Override - public Partial getPartial(int y, int m, int d) - { - return new Partial(new DateTimeFieldType[] - {DateTimeFieldType.year(), - DateTimeFieldType.monthOfYear(), - DateTimeFieldType.dayOfMonth()}, - new int[] {y, m, d}); - } - }, - DAY("yyyy/MM/dd", Period.days(1)) - { - @Override - public Partial getPartial(int y, int m, int d) - { - return new Partial(new DateTimeFieldType[] - {DateTimeFieldType.year(), - DateTimeFieldType.monthOfYear(), - DateTimeFieldType.dayOfMonth()}, - new int[] {y, m, d}); - } - }; - private final String mFormat; - public final Period mPeriod; - private Type (String xiF, Period xiP) {mFormat = xiF; mPeriod = xiP;} - public Partial getPartial(int y, int m, int d) {return null;} - public String getPartialStr(int y, int m, int d) - { - return getPartial(y, m, d).toString(mFormat); - } - } - @Persistent - public Type mType; - @Persistent - public String mDate; - @Persistent - public String mFile; - @Persistent - public Integer mCount; - - public void incrementCount() - { - mCount++; - } - - @SuppressWarnings("unchecked") - public static List getAllByType(Type xiType) - { - List detachedList = null, list = null; - PersistenceManager pm = PMF.get().getPersistenceManager(); - try - { - Query lQuery = pm.newQuery(Counter.class);; - lQuery.setFilter("mType == mTypeParam"); - lQuery.declareParameters("String mTypeParam"); - list = (List)lQuery.execute(xiType); - detachedList = new ArrayList(); - for (Counter obj : list) - { - detachedList.add(pm.detachCopy(obj)); - } - - } - finally - { - pm.close(); - } - return detachedList; - } - - private static final Pattern sVerPattern = Pattern.compile("(.+)_([0-9]+(\\.[0-9]+)*)(\\..+)"); - - public static Map> getPerFilePerDateMap(List xiList, - boolean xiCollapseVers) - { - Map> lFileMap = new HashMap>(); - - for (Counter lCounter : xiList) - { - String lFile = lCounter.mFile; - String lDateStr = lCounter.mDate; - Integer lCount = lCounter.mCount; - - if (xiCollapseVers) - { - Matcher matcher = sVerPattern.matcher(lFile); - if (matcher.matches()) - { - lFile = matcher.group(1) + "*" + matcher.group(4); - } - } - - Map lDateMap = lFileMap.get(lFile); - if (lDateMap == null) - { - lDateMap = new HashMap(); - lFileMap.put(lFile, lDateMap); - } - - if (xiCollapseVers) - { - Integer lAllVersCount = lDateMap.get(lDateStr); - if (lAllVersCount == null) - { - lAllVersCount = 0; - } - lAllVersCount += lCount; - lDateMap.put(lDateStr, lAllVersCount); - } - else - { - lDateMap.put(lDateStr, lCount); - } - } - - return lFileMap; - } - - public static List getDateStrs(Type xiType, - Partial xiStart, - Set xiDataDateStrs) - { - List lDateStrs = new ArrayList(); - - if (xiDataDateStrs.size() > 0) - { - if (xiType == Type.WEEK) - { - DateMidnight foundMonday = new DateMidnight(xiStart.get(DateTimeFieldType.year()), - xiStart.get(DateTimeFieldType.monthOfYear()), - xiStart.get(DateTimeFieldType.dayOfMonth())); - while (foundMonday.getDayOfWeek() != DateTimeConstants.MONDAY) - { - foundMonday = foundMonday.plus(Days.ONE); - } - xiStart = new Partial(new DateTimeFieldType[] - {DateTimeFieldType.year(), - DateTimeFieldType.monthOfYear(), - DateTimeFieldType.dayOfMonth()}, - new int[] {foundMonday.getYear(), - foundMonday.getMonthOfYear(), - foundMonday.getDayOfMonth()}); - } - - List lInDataStrsList = new ArrayList(xiDataDateStrs); - Collections.sort(lInDataStrsList); - String lOldestDate = lInDataStrsList.get(0); - - Partial lDate = xiStart; - String lDateStr = lDate.toString(xiType.mFormat); - - while (lDateStr.compareTo(lOldestDate) >= 0) - { - lDateStrs.add(lDateStr); - lDate = lDate.minus(xiType.mPeriod); - lDateStr = lDate.toString(xiType.mFormat); - } - lDateStrs.add(lDateStr); - - Collections.reverse(lDateStrs); - } - return lDateStrs; - } - - public static Map> getFilePerWeekMap(Map> xiPerFilePerDayData) - { - // Filename -> DateStr -> Count - Map> lRet = new HashMap>(); - - for (Entry> fileEntry : xiPerFilePerDayData.entrySet()) - { - String file = fileEntry.getKey(); - Map perWeekData = new HashMap(); - lRet.put(file, perWeekData); - - // DateStr -> Count - Map perDateData = fileEntry.getValue(); - List dateStrs = new ArrayList(perDateData.keySet()); - Collections.sort(dateStrs); - Collections.reverse(dateStrs); - - DateMidnight lastDate = null; - int weekCount = 0; - boolean unrecordedItem = false; - - for (String datestr : dateStrs) - { - DateMidnight date = new DateMidnight(datestr.replace("/", "-")); - if (unrecordedItem && (lastDate != null)) - { - Days d = Days.daysBetween(date, lastDate); - if (d.getDays() >= 7) - { - DateMidnight foundMonday = lastDate; - while (foundMonday.getDayOfWeek() != DateTimeConstants.MONDAY) - { - foundMonday = foundMonday.minus(Days.ONE); - } - perWeekData.put(Type.DAY.getPartialStr(foundMonday.getYear(), - foundMonday.getMonthOfYear(), - foundMonday.getDayOfMonth()), - weekCount); - weekCount = 0; - unrecordedItem = false; - } - } - - lastDate = date; - Integer count = perDateData.get(datestr); - weekCount += count; - unrecordedItem = true; - - if (date.getDayOfWeek() == DateTimeConstants.MONDAY) - { - perWeekData.put(datestr, weekCount); - weekCount = 0; - unrecordedItem = false; - } - } - - if (unrecordedItem) - { - DateMidnight foundMonday = lastDate; - while (foundMonday.getDayOfWeek() != DateTimeConstants.MONDAY) - { - foundMonday = foundMonday.minus(Days.ONE); - } - perWeekData.put(Type.DAY.getPartialStr(foundMonday.getYear(), - foundMonday.getMonthOfYear(), - foundMonday.getDayOfMonth()), - weekCount); - } - } - - return lRet; - } - -} +package org.gaecounter.data; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.jdo.PersistenceManager; +import javax.jdo.Query; +import javax.jdo.annotations.PersistenceCapable; +import javax.jdo.annotations.Persistent; +import javax.jdo.annotations.PrimaryKey; + +import org.joda.time.DateMidnight; +import org.joda.time.DateTimeConstants; +import org.joda.time.DateTimeFieldType; +import org.joda.time.Days; +import org.joda.time.Partial; +import org.joda.time.Period; + +@PersistenceCapable +public class Counter +{ + public Counter(Type mType, String mDate, String mFile) + { + this.mKey = getKey(mFile, mDate); + this.mType = mType; + this.mDate = mDate; + this.mFile = mFile; + this.mCount = 1; + } + + public static String getKey(String xiFile, String xiDate) + { + return xiFile + "_" + xiDate; + } + + @PrimaryKey + @Persistent + public String mKey; + public enum Type + { + YEAR("yyyy", Period.years(1)) + { + @Override + public Partial getPartial(int y, int m, int d) + { + return new Partial(new DateTimeFieldType[] + {DateTimeFieldType.year()}, + new int[] {y}); + } + }, + MONTH("yyyy/MM", Period.months(1)) + { + @Override + public Partial getPartial(int y, int m, int d) + { + return new Partial(new DateTimeFieldType[] + {DateTimeFieldType.year(), + DateTimeFieldType.monthOfYear()}, + new int[] {y, m}); + } + }, + WEEK("yyyy/MM/dd", Period.days(7)) + { + @Override + public Partial getPartial(int y, int m, int d) + { + return new Partial(new DateTimeFieldType[] + {DateTimeFieldType.year(), + DateTimeFieldType.monthOfYear(), + DateTimeFieldType.dayOfMonth()}, + new int[] {y, m, d}); + } + }, + DAY("yyyy/MM/dd", Period.days(1)) + { + @Override + public Partial getPartial(int y, int m, int d) + { + return new Partial(new DateTimeFieldType[] + {DateTimeFieldType.year(), + DateTimeFieldType.monthOfYear(), + DateTimeFieldType.dayOfMonth()}, + new int[] {y, m, d}); + } + }; + private final String mFormat; + public final Period mPeriod; + private Type (String xiF, Period xiP) {mFormat = xiF; mPeriod = xiP;} + public Partial getPartial(int y, int m, int d) {return null;} + public String getPartialStr(int y, int m, int d) + { + return getPartial(y, m, d).toString(mFormat); + } + } + @Persistent + public Type mType; + @Persistent + public String mDate; + @Persistent + public String mFile; + @Persistent + public Integer mCount; + + public void incrementCount() + { + mCount++; + } + + @SuppressWarnings("unchecked") + public static List getAllByType(Type xiType) + { + List detachedList = null, list = null; + PersistenceManager pm = PMF.get().getPersistenceManager(); + try + { + Query lQuery = pm.newQuery(Counter.class);; + lQuery.setFilter("mType == mTypeParam"); + lQuery.declareParameters("String mTypeParam"); + list = (List)lQuery.execute(xiType); + detachedList = new ArrayList(); + for (Counter obj : list) + { + detachedList.add(pm.detachCopy(obj)); + } + + } + finally + { + pm.close(); + } + return detachedList; + } + + private static final Pattern sVerPattern = Pattern.compile("(.+)_([0-9]+(\\.[0-9]+)*)(\\..+)"); + + public static Map> getPerFilePerDateMap(List xiList, + boolean xiCollapseVers) + { + Map> lFileMap = new HashMap>(); + + for (Counter lCounter : xiList) + { + String lFile = lCounter.mFile; + String lDateStr = lCounter.mDate; + Integer lCount = lCounter.mCount; + + if (xiCollapseVers) + { + Matcher matcher = sVerPattern.matcher(lFile); + if (matcher.matches()) + { + lFile = matcher.group(1) + "*" + matcher.group(4); + } + } + + Map lDateMap = lFileMap.get(lFile); + if (lDateMap == null) + { + lDateMap = new HashMap(); + lFileMap.put(lFile, lDateMap); + } + + if (xiCollapseVers) + { + Integer lAllVersCount = lDateMap.get(lDateStr); + if (lAllVersCount == null) + { + lAllVersCount = 0; + } + lAllVersCount += lCount; + lDateMap.put(lDateStr, lAllVersCount); + } + else + { + lDateMap.put(lDateStr, lCount); + } + } + + return lFileMap; + } + + public static List getDateStrs(Type xiType, + Partial xiStart, + Set xiDataDateStrs) + { + List lDateStrs = new ArrayList(); + + if (xiDataDateStrs.size() > 0) + { + if (xiType == Type.WEEK) + { + DateMidnight foundMonday = new DateMidnight(xiStart.get(DateTimeFieldType.year()), + xiStart.get(DateTimeFieldType.monthOfYear()), + xiStart.get(DateTimeFieldType.dayOfMonth())); + while (foundMonday.getDayOfWeek() != DateTimeConstants.MONDAY) + { + foundMonday = foundMonday.plus(Days.ONE); + } + xiStart = new Partial(new DateTimeFieldType[] + {DateTimeFieldType.year(), + DateTimeFieldType.monthOfYear(), + DateTimeFieldType.dayOfMonth()}, + new int[] {foundMonday.getYear(), + foundMonday.getMonthOfYear(), + foundMonday.getDayOfMonth()}); + } + + List lInDataStrsList = new ArrayList(xiDataDateStrs); + Collections.sort(lInDataStrsList); + String lOldestDate = lInDataStrsList.get(0); + + Partial lDate = xiStart; + String lDateStr = lDate.toString(xiType.mFormat); + + while (lDateStr.compareTo(lOldestDate) >= 0) + { + lDateStrs.add(lDateStr); + lDate = lDate.minus(xiType.mPeriod); + lDateStr = lDate.toString(xiType.mFormat); + } + lDateStrs.add(lDateStr); + + Collections.reverse(lDateStrs); + } + return lDateStrs; + } + + public static Map> getFilePerWeekMap(Map> xiPerFilePerDayData) + { + // Filename -> DateStr -> Count + Map> lRet = new HashMap>(); + + for (Entry> fileEntry : xiPerFilePerDayData.entrySet()) + { + String file = fileEntry.getKey(); + Map perWeekData = new HashMap(); + lRet.put(file, perWeekData); + + // DateStr -> Count + Map perDateData = fileEntry.getValue(); + List dateStrs = new ArrayList(perDateData.keySet()); + Collections.sort(dateStrs); + + DateMidnight nextPeriod = null; + int weekCount = 0; + boolean unrecordedItem = false; + + // Iterate through the dates from oldest to newest + for (String datestr : dateStrs) + { + DateMidnight date = new DateMidnight(datestr.replace("/", "-")); + + if (nextPeriod != null) + { + // We know when the next period starts so check whether this date + // is after the start of the next period + if (date.isEqual(nextPeriod) || date.isAfter(nextPeriod)) + { + DateMidnight prevPeriod = nextPeriod.minusDays(7); + perWeekData.put(Type.DAY.getPartialStr(prevPeriod.getYear(), + prevPeriod.getMonthOfYear(), + prevPeriod.getDayOfMonth()), + weekCount); + weekCount = 0; + unrecordedItem = false; + } + } + + // Add the count to the current period + Integer count = perDateData.get(datestr); + weekCount += count; + + if (!unrecordedItem) + { + // If this is the first item in the new period - work out when the period ends + nextPeriod = date.plusDays(1); + while (nextPeriod.getDayOfWeek() != DateTimeConstants.MONDAY) + { + nextPeriod = nextPeriod.plusDays(1); + } + } + + unrecordedItem = true; + } + + if (unrecordedItem) + { + // Store the details of the final period + DateMidnight prevPeriod = nextPeriod.minusDays(7); + perWeekData.put(Type.DAY.getPartialStr(prevPeriod.getYear(), + prevPeriod.getMonthOfYear(), + prevPeriod.getDayOfMonth()), + weekCount); + } + } + + return lRet; + } + +}