killbill-memoizeit
Changes
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java 6(+3 -3)
Details
diff --git a/osgi-bundles/bundles/analytics/README.md b/osgi-bundles/bundles/analytics/README.md
index b411bec..41847d6 100644
--- a/osgi-bundles/bundles/analytics/README.md
+++ b/osgi-bundles/bundles/analytics/README.md
@@ -44,3 +44,4 @@ The dashboard system is controlled by query parameters:
* AVERAGE\_MONTHLY: average the values on a monthly basis
* SUM\_WEEKLY: sum all values on a weekly basis
* SUM\_MONTHLY: sum all values on a monthly basis
+* To filter pivots from a report, use *!* for exclusions and *$* for inclusions. For example, report1=payments_per_day$AUD$EUR will graph the payments for AUD and EUR only, whereas report1=payments_per_day!AUD!EUR will graph all payments but the ones in AUD and EUR.
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java
index 6fbcf1a..9947d93 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java
@@ -173,8 +173,8 @@ public class AnalyticsServlet extends HttpServlet {
}
private void doHandleReports(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
- final String[] reportNames = req.getParameterValues(REPORTS_QUERY_NAME);
- if (reportNames == null || reportNames.length == 0) {
+ final String[] rawReportNames = req.getParameterValues(REPORTS_QUERY_NAME);
+ if (rawReportNames == null || rawReportNames.length == 0) {
resp.sendError(404);
return;
}
@@ -185,7 +185,7 @@ public class AnalyticsServlet extends HttpServlet {
final SmootherType smootherType = Smoother.fromString(Strings.emptyToNull(req.getParameter(REPORTS_SMOOTHER_NAME)));
// TODO PIERRE Switch to an equivalent of StreamingOutputStream?
- final List<NamedXYTimeSeries> result = reportsUserApi.getTimeSeriesDataForReport(reportNames, startDate, endDate, smootherType);
+ final List<NamedXYTimeSeries> result = reportsUserApi.getTimeSeriesDataForReport(rawReportNames, startDate, endDate, smootherType);
resp.getOutputStream().write(mapper.writeValueAsBytes(result));
resp.setContentType("application/json");
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportSpecification.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportSpecification.java
new file mode 100644
index 0000000..a569ab8
--- /dev/null
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportSpecification.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package com.ning.billing.osgi.bundles.analytics.reports;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import com.google.common.base.Splitter;
+
+public class ReportSpecification {
+
+ private final List<String> pivotNamesToExclude = new ArrayList<String>();
+ private final List<String> pivotNamesToInclude = new ArrayList<String>();
+
+ private final String rawReportName;
+
+ private String reportName;
+
+ public ReportSpecification(final String rawReportName) {
+ this.rawReportName = rawReportName;
+ parseRawReportName();
+ }
+
+ public List<String> getPivotNamesToExclude() {
+ return pivotNamesToExclude;
+ }
+
+ public List<String> getPivotNamesToInclude() {
+ return pivotNamesToInclude;
+ }
+
+ public String getReportName() {
+ return reportName;
+ }
+
+ private void parseRawReportName() {
+ final boolean hasExcludes = rawReportName.contains("!");
+ final boolean hasIncludes = rawReportName.contains("$");
+ if (hasExcludes && hasIncludes) {
+ throw new IllegalArgumentException();
+ }
+
+ // rawReportName is in the form payments_per_day!AUD!BRL or payments_per_day$USD$EUR (but not both!)
+ final Iterator<String> reportIterator = Splitter.on(Pattern.compile("[\\!\\$]"))
+ .trimResults()
+ .omitEmptyStrings()
+ .split(rawReportName)
+ .iterator();
+ boolean isFirst = true;
+ while (reportIterator.hasNext()) {
+ final String piece = reportIterator.next();
+
+ if (isFirst) {
+ reportName = piece;
+ } else {
+ if (hasExcludes) {
+ pivotNamesToExclude.add(piece);
+ } else if (hasIncludes) {
+ pivotNamesToInclude.add(piece);
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ isFirst = false;
+ }
+ }
+}
diff --git a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportsUserApi.java b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportsUserApi.java
index cc0b89c..1dbd9b3 100644
--- a/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportsUserApi.java
+++ b/osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/reports/ReportsUserApi.java
@@ -16,6 +16,7 @@
package com.ning.billing.osgi.bundles.analytics.reports;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
@@ -67,18 +68,24 @@ public class ReportsUserApi {
dbiThreadsExecutor.shutdownNow();
}
- public List<NamedXYTimeSeries> getTimeSeriesDataForReport(final String[] reportNames,
+ public List<NamedXYTimeSeries> getTimeSeriesDataForReport(final String[] rawReportNames,
@Nullable final LocalDate startDate,
@Nullable final LocalDate endDate,
@Nullable final SmootherType smootherType) {
// Mapping of report name -> pivots -> data
final Map<String, Map<String, List<XY>>> dataForReports = new ConcurrentHashMap<String, Map<String, List<XY>>>();
+ // Parse the reports
+ final List<ReportSpecification> reportSpecifications = new ArrayList<ReportSpecification>();
+ for (final String rawReportName : rawReportNames) {
+ reportSpecifications.add(new ReportSpecification(rawReportName));
+ }
+
// Fetch the data
- fetchData(reportNames, dataForReports);
+ fetchData(reportSpecifications, dataForReports);
// Filter the data first
- filterValues(dataForReports, startDate, endDate);
+ filterValues(reportSpecifications, dataForReports, startDate, endDate);
// Normalize and sort the data
normalizeAndSortXValues(dataForReports, startDate, endDate);
@@ -113,9 +120,10 @@ public class ReportsUserApi {
return results;
}
- private void fetchData(final String[] reportNames, final Map<String, Map<String, List<XY>>> dataForReports) {
+ private void fetchData(final List<ReportSpecification> reportSpecifications, final Map<String, Map<String, List<XY>>> dataForReports) {
final List<Future> jobs = new LinkedList<Future>();
- for (final String reportName : reportNames) {
+ for (final ReportSpecification reportSpecification : reportSpecifications) {
+ final String reportName = reportSpecification.getReportName();
final String tableName = reportsConfiguration.getTableNameForReport(reportName);
if (tableName != null) {
jobs.add(dbiThreadsExecutor.submit(new Runnable() {
@@ -139,12 +147,36 @@ public class ReportsUserApi {
}
}
- private void filterValues(final Map<String, Map<String, List<XY>>> dataForReports, @Nullable final LocalDate startDate, @Nullable final LocalDate endDate) {
+ private void filterValues(final List<ReportSpecification> reportSpecifications,
+ final Map<String, Map<String, List<XY>>> dataForReports,
+ @Nullable final LocalDate startDate,
+ @Nullable final LocalDate endDate) {
if (startDate == null && endDate == null) {
return;
}
- for (final Map<String, List<XY>> dataForReport : dataForReports.values()) {
+ for (final ReportSpecification reportSpecification : reportSpecifications) {
+ final String reportName = reportSpecification.getReportName();
+ final Map<String, List<XY>> dataForReport = dataForReports.get(reportName);
+ if (dataForReport == null) {
+ throw new IllegalArgumentException();
+ }
+
+ // Handle the exclusion list
+ Iterables.removeAll(dataForReport.keySet(), reportSpecification.getPivotNamesToExclude());
+
+ // Handle the inclusion list
+ if (reportSpecification.getPivotNamesToInclude().size() > 0) {
+ Iterables.removeIf(dataForReport.keySet(),
+ new Predicate<String>() {
+ @Override
+ public boolean apply(final String pivotName) {
+ return !reportSpecification.getPivotNamesToInclude().contains(pivotName);
+ }
+ });
+ }
+
+ // Handle the dates filter
for (final List<XY> dataForPivot : dataForReport.values()) {
Iterables.removeIf(dataForPivot,
new Predicate<XY>() {