killbill-memoizeit
Changes
osgi-bundles/bundles/analytics/src/main/java/com/ning/billing/osgi/bundles/analytics/http/AnalyticsServlet.java 66(+27 -39)
Details
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 1dd0b1a..7f72951 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
@@ -18,9 +18,7 @@ package com.ning.billing.osgi.bundles.analytics.http;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.net.URL;
-import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -39,7 +37,6 @@ import org.osgi.service.log.LogService;
import com.ning.billing.osgi.bundles.analytics.AnalyticsRefreshException;
import com.ning.billing.osgi.bundles.analytics.api.BusinessSnapshot;
import com.ning.billing.osgi.bundles.analytics.api.user.AnalyticsUserApi;
-import com.ning.billing.osgi.bundles.analytics.json.NamedTimeSeries;
import com.ning.billing.osgi.bundles.analytics.json.NamedXYTimeSeries;
import com.ning.billing.util.callcontext.CallContext;
import com.ning.billing.util.callcontext.CallOrigin;
@@ -47,12 +44,11 @@ import com.ning.billing.util.callcontext.UserType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.base.Objects;
-import com.google.common.io.CharStreams;
import com.google.common.io.Resources;
public class AnalyticsServlet extends HttpServlet {
- public static DateTimeFormatter DATE_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd");
+ public static DateTimeFormatter DATE_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd");
private static final String QUERY_TENANT_ID = "tenantId";
@@ -60,10 +56,6 @@ public class AnalyticsServlet extends HttpServlet {
private static final String HDR_REASON = "X-Killbill-Reason";
private static final String HDR_COMMENT = "X-Killbill-Comment";
- private final static String ANALYTICS_DASHBOARD_HTML = "dashboard.html";
- private final static String JQUERY_JS = "jquery-1.9.0.min.js";
- private final static String D3_JS = "d3.js";
- private final static String KILLBILL_JS = "killbill.js";
private final static String STATIC_RESOURCES = "static";
@@ -103,7 +95,7 @@ public class AnalyticsServlet extends HttpServlet {
}
}
-// Access-Control-Allow-Origin: *
+ // Access-Control-Allow-Origin: *
@Override
protected void doGet(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
@@ -176,26 +168,23 @@ public class AnalyticsServlet extends HttpServlet {
final String products = req.getParameter(QUERY_PRODUCTS);
logService.log(LogService.LOG_INFO, "PlanTransitionsOverTime " +
- "startDate = " + Objects.firstNonNull(startDate, "") +
- ", endDate = " + Objects.firstNonNull(endDate, "") +
- ", products = " + Objects.firstNonNull(products, ""));
+ "startDate = " + Objects.firstNonNull(startDate, "") +
+ ", endDate = " + Objects.firstNonNull(endDate, "") +
+ ", products = " + Objects.firstNonNull(products, ""));
// TODO STEPH until we plug the DAO to get real data, fake it...
- final String linesDataDJson = "[{\"name\": \"new\"," +
- "\"dates\": [\"2013-01-01\", \"2013-01-02\", \"2013-01-03\", \"2013-01-04\", \"2013-01-05\", \"2013-01-06\", \"2013-01-07\", \"2013-01-08\", \"2013-01-09\", \"2013-01-10\", \"2013-01-11\", \"2013-01-12\", \"2013-01-13\", \"2013-01-14\", \"2013-01-15\", \"2013-01-16\", \"2013-01-17\", \"2013-01-18\", \"2013-01-19\", \"2013-01-20\", \"2013-01-21\", \"2013-01-22\", \"2013-01-23\", \"2013-01-24\", \"2013-01-25\", \"2013-01-26\", \"2013-01-27\", \"2013-01-28\", \"2013-01-29\", \"2013-01-30\", \"2013-01-31\", \"2013-02-01\", \"2013-02-02\", \"2013-02-03\", \"2013-02-04\", \"2013-02-05\", \"2013-02-06\", \"2013-02-07\", \"2013-02-08\", \"2013-02-09\", \"2013-02-10\", \"2013-02-11\", \"2013-02-12\", \"2013-02-13\", \"2013-02-14\", \"2013-02-15\", \"2013-02-16\", \"2013-02-17\", \"2013-02-18\", \"2013-02-19\", \"2013-02-20\", \"2013-02-21\", \"2013-02-22\", \"2013-02-23\", \"2013-02-24\", \"2013-02-25\", \"2013-02-26\", \"2013-02-27\", \"2013-02-28\", \"2013-03-01\", \"2013-03-02\", \"2013-03-03\", \"2013-03-04\", \"2013-03-05\", \"2013-03-06\", \"2013-03-07\", \"2013-03-08\", \"2013-03-09\", \"2013-03-10\", \"2013-03-11\"]," +
- "\"values\": [8, 9, 9, 7, 7, 5, 9, 11, 5, 6, 5, 6, 11, 10, 6, 7, 6, 9, 11, 11, 9, 9, 9, 11, 11, 9, 7, 6, 7, 7, 11, 5, 10, 10, 7, 9, 11, 5, 7, 9, 6, 11, 9, 5, 9, 8, 7, 8, 8, 6, 7, 6, 10, 5, 9, 8, 10, 10, 5, 7, 11, 5, 11, 6, 11, 6, 6, 7, 11, 10]}," +
- "{\"name\": \"changed\"," +
- "\"dates\": [\"2013-01-01\", \"2013-01-02\", \"2013-01-03\", \"2013-01-04\", \"2013-01-05\", \"2013-01-06\", \"2013-01-07\", \"2013-01-08\", \"2013-01-09\", \"2013-01-10\", \"2013-01-11\", \"2013-01-12\", \"2013-01-13\", \"2013-01-14\", \"2013-01-15\", \"2013-01-16\", \"2013-01-17\", \"2013-01-18\", \"2013-01-19\", \"2013-01-20\", \"2013-01-21\", \"2013-01-22\", \"2013-01-23\", \"2013-01-24\", \"2013-01-25\", \"2013-01-26\", \"2013-01-27\", \"2013-01-28\", \"2013-01-29\", \"2013-01-30\", \"2013-01-31\", \"2013-02-01\", \"2013-02-02\", \"2013-02-03\", \"2013-02-04\", \"2013-02-05\", \"2013-02-06\", \"2013-02-07\", \"2013-02-08\", \"2013-02-09\", \"2013-02-10\", \"2013-02-11\", \"2013-02-12\", \"2013-02-13\", \"2013-02-14\", \"2013-02-15\", \"2013-02-16\", \"2013-02-17\", \"2013-02-18\", \"2013-02-19\", \"2013-02-20\", \"2013-02-21\", \"2013-02-22\", \"2013-02-23\", \"2013-02-24\", \"2013-02-25\", \"2013-02-26\", \"2013-02-27\", \"2013-02-28\", \"2013-03-01\", \"2013-03-02\", \"2013-03-03\", \"2013-03-04\", \"2013-03-05\", \"2013-03-06\", \"2013-03-07\", \"2013-03-08\", \"2013-03-09\", \"2013-03-10\", \"2013-03-11\"]," +
- "\"values\": [7, 7, 7, 6, 7, 5, 6, 5, 7, 5, 6, 5, 5, 6, 6, 6, 7, 6, 7, 6, 6, 5, 5, 5, 6, 6, 5, 5, 6, 5, 6, 6, 7, 6, 7, 5, 5, 7, 7, 7, 6, 5, 5, 7, 5, 5, 7, 6, 5, 6, 5, 7, 6, 6, 5, 7, 6, 6, 6, 5, 6, 7, 6, 5, 7, 5, 6, 5, 5, 5]}," +
- "{\"name\": \"cancelled\"," +
- "\"dates\": [\"2013-01-01\", \"2013-01-02\", \"2013-01-03\", \"2013-01-04\", \"2013-01-05\", \"2013-01-06\", \"2013-01-07\", \"2013-01-08\", \"2013-01-09\", \"2013-01-10\", \"2013-01-11\", \"2013-01-12\", \"2013-01-13\", \"2013-01-14\", \"2013-01-15\", \"2013-01-16\", \"2013-01-17\", \"2013-01-18\", \"2013-01-19\", \"2013-01-20\", \"2013-01-21\", \"2013-01-22\", \"2013-01-23\", \"2013-01-24\", \"2013-01-25\", \"2013-01-26\", \"2013-01-27\", \"2013-01-28\", \"2013-01-29\", \"2013-01-30\", \"2013-01-31\", \"2013-02-01\", \"2013-02-02\", \"2013-02-03\", \"2013-02-04\", \"2013-02-05\", \"2013-02-06\", \"2013-02-07\", \"2013-02-08\", \"2013-02-09\", \"2013-02-10\", \"2013-02-11\", \"2013-02-12\", \"2013-02-13\", \"2013-02-14\", \"2013-02-15\", \"2013-02-16\", \"2013-02-17\", \"2013-02-18\", \"2013-02-19\", \"2013-02-20\", \"2013-02-21\", \"2013-02-22\", \"2013-02-23\", \"2013-02-24\", \"2013-02-25\", \"2013-02-26\", \"2013-02-27\", \"2013-02-28\", \"2013-03-01\", \"2013-03-02\", \"2013-03-03\", \"2013-03-04\", \"2013-03-05\", \"2013-03-06\", \"2013-03-07\", \"2013-03-08\", \"2013-03-09\", \"2013-03-10\", \"2013-03-11\"]," +
- "\"values\": [7, 6, 8, 6, 6, 6, 5, 8, 5, 5, 4, 3, 6, 4, 6, 6, 3, 8, 6, 8, 7, 4, 5, 4, 6, 6, 5, 7, 5, 8, 6, 3, 6, 4, 4, 4, 4, 3, 4, 3, 7, 5, 4, 5, 4, 4, 3, 3, 4, 6, 5, 7, 7, 7, 3, 7, 7, 6, 3, 8, 7, 7, 6, 7, 4, 7, 6, 4, 3, 5]}," +
- "{\"name\": \"next Phase\"," +
- "\"dates\": [\"2013-01-01\", \"2013-01-02\", \"2013-01-03\", \"2013-01-04\", \"2013-01-05\", \"2013-01-06\", \"2013-01-07\", \"2013-01-08\", \"2013-01-09\", \"2013-01-10\", \"2013-01-11\", \"2013-01-12\", \"2013-01-13\", \"2013-01-14\", \"2013-01-15\", \"2013-01-16\", \"2013-01-17\", \"2013-01-18\", \"2013-01-19\", \"2013-01-20\", \"2013-01-21\", \"2013-01-22\", \"2013-01-23\", \"2013-01-24\", \"2013-01-25\", \"2013-01-26\", \"2013-01-27\", \"2013-01-28\", \"2013-01-29\", \"2013-01-30\", \"2013-01-31\", \"2013-02-01\", \"2013-02-02\", \"2013-02-03\", \"2013-02-04\", \"2013-02-05\", \"2013-02-06\", \"2013-02-07\", \"2013-02-08\", \"2013-02-09\", \"2013-02-10\", \"2013-02-11\", \"2013-02-12\", \"2013-02-13\", \"2013-02-14\", \"2013-02-15\", \"2013-02-16\", \"2013-02-17\", \"2013-02-18\", \"2013-02-19\", \"2013-02-20\", \"2013-02-21\", \"2013-02-22\", \"2013-02-23\", \"2013-02-24\", \"2013-02-25\", \"2013-02-26\", \"2013-02-27\", \"2013-02-28\", \"2013-03-01\", \"2013-03-02\", \"2013-03-03\", \"2013-03-04\", \"2013-03-05\", \"2013-03-06\", \"2013-03-07\", \"2013-03-08\", \"2013-03-09\", \"2013-03-10\", \"2013-03-11\"]," +
- "\"values\": [-4, -4, -5, -5, -5, -3, -4, -3, -3, -4, -5, -3, -3, -4, -3, -4, -4, -5, -4, -5, -4, -4, -4, -4, -3, -5, -3, -3, -5, -5, -3, -3, -3, -4, -4, -5, -5, -3, -4, -4, -4, -4, -5, -4, -5, -4, -4, -3, -5, -4, -3, -5, -4, -3, -4, -5, -5, -3, -3, -3, -3, -5, -4, -5, -3, -4, -4, -3, -3, -5]}" +
- "]";
-
- List<NamedTimeSeries> result = mapper.readValue(linesDataDJson, List.class);
+ final String linesDataJson = "[" +
+ "{\"name\":\"new\"," +
+ "\"values\":[{\"x\":\"2013-01-01\", \"y\":6}, {\"x\":\"2013-01-02\", \"y\":5}, {\"x\":\"2013-01-03\", \"y\":10}, {\"x\":\"2013-01-04\", \"y\":5}, {\"x\":\"2013-01-05\", \"y\":7}, {\"x\":\"2013-01-06\", \"y\":11}, {\"x\":\"2013-01-07\", \"y\":9}, {\"x\":\"2013-01-08\", \"y\":5}, {\"x\":\"2013-01-09\", \"y\":5}, {\"x\":\"2013-01-10\", \"y\":6}, {\"x\":\"2013-01-11\", \"y\":8}, {\"x\":\"2013-01-12\", \"y\":11}, {\"x\":\"2013-01-13\", \"y\":8}, {\"x\":\"2013-01-14\", \"y\":10}, {\"x\":\"2013-01-15\", \"y\":10}, {\"x\":\"2013-01-16\", \"y\":9}, {\"x\":\"2013-01-17\", \"y\":9}, {\"x\":\"2013-01-18\", \"y\":7}, {\"x\":\"2013-01-19\", \"y\":8}, {\"x\":\"2013-01-20\", \"y\":5}, {\"x\":\"2013-01-21\", \"y\":5}, {\"x\":\"2013-01-22\", \"y\":7}, {\"x\":\"2013-01-23\", \"y\":6}, {\"x\":\"2013-01-24\", \"y\":10}, {\"x\":\"2013-01-25\", \"y\":7}, {\"x\":\"2013-01-26\", \"y\":9}, {\"x\":\"2013-01-27\", \"y\":10}, {\"x\":\"2013-01-28\", \"y\":6}, {\"x\":\"2013-01-29\", \"y\":5}, {\"x\":\"2013-01-30\", \"y\":9}, {\"x\":\"2013-01-31\", \"y\":6}, {\"x\":\"2013-02-01\", \"y\":9}, {\"x\":\"2013-02-02\", \"y\":7}, {\"x\":\"2013-02-03\", \"y\":11}, {\"x\":\"2013-02-04\", \"y\":10}, {\"x\":\"2013-02-05\", \"y\":11}, {\"x\":\"2013-02-06\", \"y\":9}, {\"x\":\"2013-02-07\", \"y\":10}, {\"x\":\"2013-02-08\", \"y\":8}, {\"x\":\"2013-02-09\", \"y\":10}, {\"x\":\"2013-02-10\", \"y\":8}, {\"x\":\"2013-02-11\", \"y\":7}, {\"x\":\"2013-02-12\", \"y\":9}, {\"x\":\"2013-02-13\", \"y\":9}, {\"x\":\"2013-02-14\", \"y\":7}, {\"x\":\"2013-02-15\", \"y\":5}, {\"x\":\"2013-02-16\", \"y\":8}, {\"x\":\"2013-02-17\", \"y\":7}, {\"x\":\"2013-02-18\", \"y\":7}, {\"x\":\"2013-02-19\", \"y\":6}, {\"x\":\"2013-02-20\", \"y\":5}, {\"x\":\"2013-02-21\", \"y\":6}, {\"x\":\"2013-02-22\", \"y\":6}, {\"x\":\"2013-02-23\", \"y\":11}, {\"x\":\"2013-02-24\", \"y\":10}, {\"x\":\"2013-02-25\", \"y\":11}, {\"x\":\"2013-02-26\", \"y\":10}, {\"x\":\"2013-02-27\", \"y\":6}, {\"x\":\"2013-02-28\", \"y\":10}, {\"x\":\"2013-03-01\", \"y\":9}, {\"x\":\"2013-03-02\", \"y\":10}, {\"x\":\"2013-03-03\", \"y\":9}, {\"x\":\"2013-03-04\", \"y\":7}, {\"x\":\"2013-03-05\", \"y\":8}, {\"x\":\"2013-03-06\", \"y\":8}, {\"x\":\"2013-03-07\", \"y\":6}, {\"x\":\"2013-03-08\", \"y\":5}, {\"x\":\"2013-03-09\", \"y\":6}, {\"x\":\"2013-03-10\", \"y\":6}, {\"x\":\"2013-03-11\", \"y\":7}]}," +
+ "{\"name\":\"changed\"," +
+ "\"values\":[{\"x\":\"2013-01-01\", \"y\":5}, {\"x\":\"2013-01-02\", \"y\":6}, {\"x\":\"2013-01-03\", \"y\":7}, {\"x\":\"2013-01-04\", \"y\":6}, {\"x\":\"2013-01-05\", \"y\":6}, {\"x\":\"2013-01-06\", \"y\":6}, {\"x\":\"2013-01-07\", \"y\":7}, {\"x\":\"2013-01-08\", \"y\":6}, {\"x\":\"2013-01-09\", \"y\":6}, {\"x\":\"2013-01-10\", \"y\":5}, {\"x\":\"2013-01-11\", \"y\":6}, {\"x\":\"2013-01-12\", \"y\":5}, {\"x\":\"2013-01-13\", \"y\":5}, {\"x\":\"2013-01-14\", \"y\":5}, {\"x\":\"2013-01-15\", \"y\":5}, {\"x\":\"2013-01-16\", \"y\":6}, {\"x\":\"2013-01-17\", \"y\":5}, {\"x\":\"2013-01-18\", \"y\":5}, {\"x\":\"2013-01-19\", \"y\":5}, {\"x\":\"2013-01-20\", \"y\":5}, {\"x\":\"2013-01-21\", \"y\":5}, {\"x\":\"2013-01-22\", \"y\":5}, {\"x\":\"2013-01-23\", \"y\":7}, {\"x\":\"2013-01-24\", \"y\":7}, {\"x\":\"2013-01-25\", \"y\":6}, {\"x\":\"2013-01-26\", \"y\":6}, {\"x\":\"2013-01-27\", \"y\":7}, {\"x\":\"2013-01-28\", \"y\":7}, {\"x\":\"2013-01-29\", \"y\":7}, {\"x\":\"2013-01-30\", \"y\":7}, {\"x\":\"2013-01-31\", \"y\":5}, {\"x\":\"2013-02-01\", \"y\":5}, {\"x\":\"2013-02-02\", \"y\":7}, {\"x\":\"2013-02-03\", \"y\":6}, {\"x\":\"2013-02-04\", \"y\":6}, {\"x\":\"2013-02-05\", \"y\":6}, {\"x\":\"2013-02-06\", \"y\":6}, {\"x\":\"2013-02-07\", \"y\":6}, {\"x\":\"2013-02-08\", \"y\":5}, {\"x\":\"2013-02-09\", \"y\":5}, {\"x\":\"2013-02-10\", \"y\":6}, {\"x\":\"2013-02-11\", \"y\":6}, {\"x\":\"2013-02-12\", \"y\":5}, {\"x\":\"2013-02-13\", \"y\":7}, {\"x\":\"2013-02-14\", \"y\":7}, {\"x\":\"2013-02-15\", \"y\":7}, {\"x\":\"2013-02-16\", \"y\":7}, {\"x\":\"2013-02-17\", \"y\":7}, {\"x\":\"2013-02-18\", \"y\":7}, {\"x\":\"2013-02-19\", \"y\":6}, {\"x\":\"2013-02-20\", \"y\":7}, {\"x\":\"2013-02-21\", \"y\":5}, {\"x\":\"2013-02-22\", \"y\":7}, {\"x\":\"2013-02-23\", \"y\":5}, {\"x\":\"2013-02-24\", \"y\":7}, {\"x\":\"2013-02-25\", \"y\":5}, {\"x\":\"2013-02-26\", \"y\":5}, {\"x\":\"2013-02-27\", \"y\":7}, {\"x\":\"2013-02-28\", \"y\":7}, {\"x\":\"2013-03-01\", \"y\":5}, {\"x\":\"2013-03-02\", \"y\":5}, {\"x\":\"2013-03-03\", \"y\":6}, {\"x\":\"2013-03-04\", \"y\":6}, {\"x\":\"2013-03-05\", \"y\":5}, {\"x\":\"2013-03-06\", \"y\":5}, {\"x\":\"2013-03-07\", \"y\":6}, {\"x\":\"2013-03-08\", \"y\":7}, {\"x\":\"2013-03-09\", \"y\":5}, {\"x\":\"2013-03-10\", \"y\":6}, {\"x\":\"2013-03-11\", \"y\":7}]}," +
+ "{\"name\":\"cancelled\"," +
+ "\"values\":[{\"x\":\"2013-01-01\", \"y\":5}, {\"x\":\"2013-01-02\", \"y\":4}, {\"x\":\"2013-01-03\", \"y\":5}, {\"x\":\"2013-01-04\", \"y\":5}, {\"x\":\"2013-01-05\", \"y\":4}, {\"x\":\"2013-01-06\", \"y\":6}, {\"x\":\"2013-01-07\", \"y\":6}, {\"x\":\"2013-01-08\", \"y\":7}, {\"x\":\"2013-01-09\", \"y\":8}, {\"x\":\"2013-01-10\", \"y\":5}, {\"x\":\"2013-01-11\", \"y\":6}, {\"x\":\"2013-01-12\", \"y\":6}, {\"x\":\"2013-01-13\", \"y\":7}, {\"x\":\"2013-01-14\", \"y\":8}, {\"x\":\"2013-01-15\", \"y\":6}, {\"x\":\"2013-01-16\", \"y\":7}, {\"x\":\"2013-01-17\", \"y\":4}, {\"x\":\"2013-01-18\", \"y\":7}, {\"x\":\"2013-01-19\", \"y\":4}, {\"x\":\"2013-01-20\", \"y\":8}, {\"x\":\"2013-01-21\", \"y\":4}, {\"x\":\"2013-01-22\", \"y\":6}, {\"x\":\"2013-01-23\", \"y\":6}, {\"x\":\"2013-01-24\", \"y\":7}, {\"x\":\"2013-01-25\", \"y\":6}, {\"x\":\"2013-01-26\", \"y\":8}, {\"x\":\"2013-01-27\", \"y\":7}, {\"x\":\"2013-01-28\", \"y\":5}, {\"x\":\"2013-01-29\", \"y\":8}, {\"x\":\"2013-01-30\", \"y\":3}, {\"x\":\"2013-01-31\", \"y\":3}, {\"x\":\"2013-02-01\", \"y\":5}, {\"x\":\"2013-02-02\", \"y\":6}, {\"x\":\"2013-02-03\", \"y\":7}, {\"x\":\"2013-02-04\", \"y\":8}, {\"x\":\"2013-02-05\", \"y\":4}, {\"x\":\"2013-02-06\", \"y\":8}, {\"x\":\"2013-02-07\", \"y\":8}, {\"x\":\"2013-02-08\", \"y\":8}, {\"x\":\"2013-02-09\", \"y\":6}, {\"x\":\"2013-02-10\", \"y\":8}, {\"x\":\"2013-02-11\", \"y\":7}, {\"x\":\"2013-02-12\", \"y\":8}, {\"x\":\"2013-02-13\", \"y\":8}, {\"x\":\"2013-02-14\", \"y\":8}, {\"x\":\"2013-02-15\", \"y\":5}, {\"x\":\"2013-02-16\", \"y\":7}, {\"x\":\"2013-02-17\", \"y\":6}, {\"x\":\"2013-02-18\", \"y\":8}, {\"x\":\"2013-02-19\", \"y\":5}, {\"x\":\"2013-02-20\", \"y\":4}, {\"x\":\"2013-02-21\", \"y\":8}, {\"x\":\"2013-02-22\", \"y\":8}, {\"x\":\"2013-02-23\", \"y\":8}, {\"x\":\"2013-02-24\", \"y\":5}, {\"x\":\"2013-02-25\", \"y\":5}, {\"x\":\"2013-02-26\", \"y\":6}, {\"x\":\"2013-02-27\", \"y\":7}, {\"x\":\"2013-02-28\", \"y\":3}, {\"x\":\"2013-03-01\", \"y\":7}, {\"x\":\"2013-03-02\", \"y\":4}, {\"x\":\"2013-03-03\", \"y\":5}, {\"x\":\"2013-03-04\", \"y\":8}, {\"x\":\"2013-03-05\", \"y\":7}, {\"x\":\"2013-03-06\", \"y\":6}, {\"x\":\"2013-03-07\", \"y\":6}, {\"x\":\"2013-03-08\", \"y\":7}, {\"x\":\"2013-03-09\", \"y\":7}, {\"x\":\"2013-03-10\", \"y\":5}, {\"x\":\"2013-03-11\", \"y\":6}]}," +
+ "{\"name\":\"next phase\"," +
+ "\"values\":[{\"x\":\"2013-01-01\", \"y\":-1}, {\"x\":\"2013-01-02\", \"y\":6}, {\"x\":\"2013-01-03\", \"y\":6}, {\"x\":\"2013-01-04\", \"y\":1}, {\"x\":\"2013-01-05\", \"y\":13}, {\"x\":\"2013-01-06\", \"y\":2}, {\"x\":\"2013-01-07\", \"y\":14}, {\"x\":\"2013-01-08\", \"y\":12}, {\"x\":\"2013-01-09\", \"y\":7}, {\"x\":\"2013-01-10\", \"y\":2}, {\"x\":\"2013-01-11\", \"y\":-1}, {\"x\":\"2013-01-12\", \"y\":8}, {\"x\":\"2013-01-13\", \"y\":6}, {\"x\":\"2013-01-14\", \"y\":14}, {\"x\":\"2013-01-15\", \"y\":1}, {\"x\":\"2013-01-16\", \"y\":9}, {\"x\":\"2013-01-17\", \"y\":6}, {\"x\":\"2013-01-18\", \"y\":5}, {\"x\":\"2013-01-19\", \"y\":11}, {\"x\":\"2013-01-20\", \"y\":11}, {\"x\":\"2013-01-21\", \"y\":4}, {\"x\":\"2013-01-22\", \"y\":8}, {\"x\":\"2013-01-23\", \"y\":3}, {\"x\":\"2013-01-24\", \"y\":12}, {\"x\":\"2013-01-25\", \"y\":0}, {\"x\":\"2013-01-26\", \"y\":11}, {\"x\":\"2013-01-27\", \"y\":12}, {\"x\":\"2013-01-28\", \"y\":3}, {\"x\":\"2013-01-29\", \"y\":5}, {\"x\":\"2013-01-30\", \"y\":12}, {\"x\":\"2013-01-31\", \"y\":10}, {\"x\":\"2013-02-01\", \"y\":-2}, {\"x\":\"2013-02-02\", \"y\":4}, {\"x\":\"2013-02-03\", \"y\":12}, {\"x\":\"2013-02-04\", \"y\":7}, {\"x\":\"2013-02-05\", \"y\":4}, {\"x\":\"2013-02-06\", \"y\":10}, {\"x\":\"2013-02-07\", \"y\":14}, {\"x\":\"2013-02-08\", \"y\":4}, {\"x\":\"2013-02-09\", \"y\":6}, {\"x\":\"2013-02-10\", \"y\":9}, {\"x\":\"2013-02-11\", \"y\":14}, {\"x\":\"2013-02-12\", \"y\":9}, {\"x\":\"2013-02-13\", \"y\":14}, {\"x\":\"2013-02-14\", \"y\":8}, {\"x\":\"2013-02-15\", \"y\":5}, {\"x\":\"2013-02-16\", \"y\":13}, {\"x\":\"2013-02-17\", \"y\":6}, {\"x\":\"2013-02-18\", \"y\":0}, {\"x\":\"2013-02-19\", \"y\":1}, {\"x\":\"2013-02-20\", \"y\":11}, {\"x\":\"2013-02-21\", \"y\":11}, {\"x\":\"2013-02-22\", \"y\":9}, {\"x\":\"2013-02-23\", \"y\":9}, {\"x\":\"2013-02-24\", \"y\":5}, {\"x\":\"2013-02-25\", \"y\":2}, {\"x\":\"2013-02-26\", \"y\":-1}, {\"x\":\"2013-02-27\", \"y\":-2}, {\"x\":\"2013-02-28\", \"y\":1}, {\"x\":\"2013-03-01\", \"y\":2}, {\"x\":\"2013-03-02\", \"y\":7}, {\"x\":\"2013-03-03\", \"y\":4}, {\"x\":\"2013-03-04\", \"y\":1}, {\"x\":\"2013-03-05\", \"y\":6}, {\"x\":\"2013-03-06\", \"y\":10}, {\"x\":\"2013-03-07\", \"y\":5}, {\"x\":\"2013-03-08\", \"y\":1}, {\"x\":\"2013-03-09\", \"y\":4}, {\"x\":\"2013-03-10\", \"y\":11}, {\"x\":\"2013-03-11\", \"y\":10}]}" +
+ "];";
+
+ List<NamedXYTimeSeries> result = mapper.readValue(linesDataJson, List.class);
resp.getOutputStream().write(mapper.writeValueAsBytes(result));
resp.setContentType("application/json");
setCrossSiteScriptingHeaders(resp);
@@ -209,16 +198,16 @@ public class AnalyticsServlet extends HttpServlet {
final String products = req.getParameter(QUERY_PRODUCTS);
logService.log(LogService.LOG_INFO, "RecurringRevenueOverTime " +
- "startDate = " + Objects.firstNonNull(startDate, "") +
- ", endDate = " + Objects.firstNonNull(endDate, "") +
- ", products = " + Objects.firstNonNull(products, ""));
+ "startDate = " + Objects.firstNonNull(startDate, "") +
+ ", endDate = " + Objects.firstNonNull(endDate, "") +
+ ", products = " + Objects.firstNonNull(products, ""));
// TODO STEPH until we plug the DAO to get real data, fake it...
- final String layersDataDJson = "[" +
- "{\"name\":\"ultimate\"," + "\"values\":[{\"x\":\"2013-01-01\",\"y\":11},{\"x\":\"2013-01-02\",\"y\":37},{\"x\":\"2013-01-03\",\"y\":16},{\"x\":\"2013-01-04\",\"y\":29},{\"x\":\"2013-01-05\",\"y\":40},{\"x\":\"2013-01-06\",\"y\":3},{\"x\":\"2013-01-07\",\"y\":4},{\"x\":\"2013-01-08\",\"y\":39},{\"x\":\"2013-01-09\",\"y\":34},{\"x\":\"2013-01-10\",\"y\":31},{\"x\":\"2013-01-11\",\"y\":20},{\"x\":\"2013-01-12\",\"y\":28},{\"x\":\"2013-01-13\",\"y\":19},{\"x\":\"2013-01-14\",\"y\":15},{\"x\":\"2013-01-15\",\"y\":31},{\"x\":\"2013-01-16\",\"y\":16},{\"x\":\"2013-01-17\",\"y\":40},{\"x\":\"2013-01-18\",\"y\":29},{\"x\":\"2013-01-19\",\"y\":31},{\"x\":\"2013-01-20\",\"y\":11},{\"x\":\"2013-01-21\",\"y\":36},{\"x\":\"2013-01-22\",\"y\":18},{\"x\":\"2013-01-23\",\"y\":12},{\"x\":\"2013-01-24\",\"y\":23},{\"x\":\"2013-01-25\",\"y\":32},{\"x\":\"2013-01-26\",\"y\":27},{\"x\":\"2013-01-27\",\"y\":33},{\"x\":\"2013-01-28\",\"y\":34},{\"x\":\"2013-01-29\",\"y\":5},{\"x\":\"2013-01-30\",\"y\":7},{\"x\":\"2013-01-31\",\"y\":13},{\"x\":\"2013-02-01\",\"y\":10},{\"x\":\"2013-02-02\",\"y\":43},{\"x\":\"2013-02-03\",\"y\":15},{\"x\":\"2013-02-04\",\"y\":38},{\"x\":\"2013-02-05\",\"y\":34},{\"x\":\"2013-02-06\",\"y\":38},{\"x\":\"2013-02-07\",\"y\":26},{\"x\":\"2013-02-08\",\"y\":27},{\"x\":\"2013-02-09\",\"y\":1},{\"x\":\"2013-02-10\",\"y\":12},{\"x\":\"2013-02-11\",\"y\":28},{\"x\":\"2013-02-12\",\"y\":10},{\"x\":\"2013-02-13\",\"y\":27},{\"x\":\"2013-02-14\",\"y\":34},{\"x\":\"2013-02-15\",\"y\":25},{\"x\":\"2013-02-16\",\"y\":39},{\"x\":\"2013-02-17\",\"y\":39},{\"x\":\"2013-02-18\",\"y\":25},{\"x\":\"2013-02-19\",\"y\":38},{\"x\":\"2013-02-20\",\"y\":1},{\"x\":\"2013-02-21\",\"y\":8},{\"x\":\"2013-02-22\",\"y\":31},{\"x\":\"2013-02-23\",\"y\":38},{\"x\":\"2013-02-24\",\"y\":43},{\"x\":\"2013-02-25\",\"y\":16},{\"x\":\"2013-02-26\",\"y\":41},{\"x\":\"2013-02-27\",\"y\":44},{\"x\":\"2013-02-28\",\"y\":20},{\"x\":\"2013-03-01\",\"y\":44},{\"x\":\"2013-03-02\",\"y\":25},{\"x\":\"2013-03-03\",\"y\":41},{\"x\":\"2013-03-04\",\"y\":34},{\"x\":\"2013-03-05\",\"y\":4},{\"x\":\"2013-03-06\",\"y\":28},{\"x\":\"2013-03-07\",\"y\":34},{\"x\":\"2013-03-08\",\"y\":25},{\"x\":\"2013-03-09\",\"y\":9},{\"x\":\"2013-03-10\",\"y\":33},{\"x\":\"2013-03-11\",\"y\":40}]}," +
- "{\"name\":\"scale\",\"values\":[{\"x\":\"2013-01-01\",\"y\":22},{\"x\":\"2013-01-02\",\"y\":5},{\"x\":\"2013-01-03\",\"y\":20},{\"x\":\"2013-01-04\",\"y\":3},{\"x\":\"2013-01-05\",\"y\":7},{\"x\":\"2013-01-06\",\"y\":22},{\"x\":\"2013-01-07\",\"y\":3},{\"x\":\"2013-01-08\",\"y\":5},{\"x\":\"2013-01-09\",\"y\":5},{\"x\":\"2013-01-10\",\"y\":23},{\"x\":\"2013-01-11\",\"y\":6},{\"x\":\"2013-01-12\",\"y\":24},{\"x\":\"2013-01-13\",\"y\":7},{\"x\":\"2013-01-14\",\"y\":17},{\"x\":\"2013-01-15\",\"y\":5},{\"x\":\"2013-01-16\",\"y\":8},{\"x\":\"2013-01-17\",\"y\":3},{\"x\":\"2013-01-18\",\"y\":4},{\"x\":\"2013-01-19\",\"y\":15},{\"x\":\"2013-01-20\",\"y\":15},{\"x\":\"2013-01-21\",\"y\":2},{\"x\":\"2013-01-22\",\"y\":16},{\"x\":\"2013-01-23\",\"y\":5},{\"x\":\"2013-01-24\",\"y\":8},{\"x\":\"2013-01-25\",\"y\":10},{\"x\":\"2013-01-26\",\"y\":26},{\"x\":\"2013-01-27\",\"y\":15},{\"x\":\"2013-01-28\",\"y\":27},{\"x\":\"2013-01-29\",\"y\":24},{\"x\":\"2013-01-30\",\"y\":21},{\"x\":\"2013-01-31\",\"y\":18},{\"x\":\"2013-02-01\",\"y\":15},{\"x\":\"2013-02-02\",\"y\":23},{\"x\":\"2013-02-03\",\"y\":2},{\"x\":\"2013-02-04\",\"y\":16},{\"x\":\"2013-02-05\",\"y\":17},{\"x\":\"2013-02-06\",\"y\":15},{\"x\":\"2013-02-07\",\"y\":8},{\"x\":\"2013-02-08\",\"y\":23},{\"x\":\"2013-02-09\",\"y\":19},{\"x\":\"2013-02-10\",\"y\":26},{\"x\":\"2013-02-11\",\"y\":24},{\"x\":\"2013-02-12\",\"y\":22},{\"x\":\"2013-02-13\",\"y\":3},{\"x\":\"2013-02-14\",\"y\":0},{\"x\":\"2013-02-15\",\"y\":10},{\"x\":\"2013-02-16\",\"y\":14},{\"x\":\"2013-02-17\",\"y\":6},{\"x\":\"2013-02-18\",\"y\":5},{\"x\":\"2013-02-19\",\"y\":9},{\"x\":\"2013-02-20\",\"y\":29},{\"x\":\"2013-02-21\",\"y\":14},{\"x\":\"2013-02-22\",\"y\":16},{\"x\":\"2013-02-23\",\"y\":15},{\"x\":\"2013-02-24\",\"y\":29},{\"x\":\"2013-02-25\",\"y\":7},{\"x\":\"2013-02-26\",\"y\":4},{\"x\":\"2013-02-27\",\"y\":28},{\"x\":\"2013-02-28\",\"y\":29},{\"x\":\"2013-03-01\",\"y\":1},{\"x\":\"2013-03-02\",\"y\":23},{\"x\":\"2013-03-03\",\"y\":10},{\"x\":\"2013-03-04\",\"y\":26},{\"x\":\"2013-03-05\",\"y\":18},{\"x\":\"2013-03-06\",\"y\":25},{\"x\":\"2013-03-07\",\"y\":21},{\"x\":\"2013-03-08\",\"y\":5},{\"x\":\"2013-03-09\",\"y\":29},{\"x\":\"2013-03-10\",\"y\":13},{\"x\":\"2013-03-11\",\"y\":12}]}," +
- "{\"name\":\"basic\",\"values\":[{\"x\":\"2013-01-01\",\"y\":14},{\"x\":\"2013-01-02\",\"y\":55},{\"x\":\"2013-01-03\",\"y\":14},{\"x\":\"2013-01-04\",\"y\":55},{\"x\":\"2013-01-05\",\"y\":7},{\"x\":\"2013-01-06\",\"y\":15},{\"x\":\"2013-01-07\",\"y\":15},{\"x\":\"2013-01-08\",\"y\":39},{\"x\":\"2013-01-09\",\"y\":28},{\"x\":\"2013-01-10\",\"y\":30},{\"x\":\"2013-01-11\",\"y\":32},{\"x\":\"2013-01-12\",\"y\":49},{\"x\":\"2013-01-13\",\"y\":67},{\"x\":\"2013-01-14\",\"y\":69},{\"x\":\"2013-01-15\",\"y\":29},{\"x\":\"2013-01-16\",\"y\":39},{\"x\":\"2013-01-17\",\"y\":54},{\"x\":\"2013-01-18\",\"y\":56},{\"x\":\"2013-01-19\",\"y\":52},{\"x\":\"2013-01-20\",\"y\":60},{\"x\":\"2013-01-21\",\"y\":4},{\"x\":\"2013-01-22\",\"y\":37},{\"x\":\"2013-01-23\",\"y\":67},{\"x\":\"2013-01-24\",\"y\":72},{\"x\":\"2013-01-25\",\"y\":45},{\"x\":\"2013-01-26\",\"y\":2},{\"x\":\"2013-01-27\",\"y\":70},{\"x\":\"2013-01-28\",\"y\":26},{\"x\":\"2013-01-29\",\"y\":19},{\"x\":\"2013-01-30\",\"y\":36},{\"x\":\"2013-01-31\",\"y\":73},{\"x\":\"2013-02-01\",\"y\":63},{\"x\":\"2013-02-02\",\"y\":67},{\"x\":\"2013-02-03\",\"y\":11},{\"x\":\"2013-02-04\",\"y\":38},{\"x\":\"2013-02-05\",\"y\":7},{\"x\":\"2013-02-06\",\"y\":53},{\"x\":\"2013-02-07\",\"y\":52},{\"x\":\"2013-02-08\",\"y\":31},{\"x\":\"2013-02-09\",\"y\":18},{\"x\":\"2013-02-10\",\"y\":66},{\"x\":\"2013-02-11\",\"y\":32},{\"x\":\"2013-02-12\",\"y\":49},{\"x\":\"2013-02-13\",\"y\":38},{\"x\":\"2013-02-14\",\"y\":1},{\"x\":\"2013-02-15\",\"y\":61},{\"x\":\"2013-02-16\",\"y\":54},{\"x\":\"2013-02-17\",\"y\":71},{\"x\":\"2013-02-18\",\"y\":69},{\"x\":\"2013-02-19\",\"y\":59},{\"x\":\"2013-02-20\",\"y\":58},{\"x\":\"2013-02-21\",\"y\":28},{\"x\":\"2013-02-22\",\"y\":66},{\"x\":\"2013-02-23\",\"y\":59},{\"x\":\"2013-02-24\",\"y\":62},{\"x\":\"2013-02-25\",\"y\":65},{\"x\":\"2013-02-26\",\"y\":18},{\"x\":\"2013-02-27\",\"y\":57},{\"x\":\"2013-02-28\",\"y\":0},{\"x\":\"2013-03-01\",\"y\":24},{\"x\":\"2013-03-02\",\"y\":48},{\"x\":\"2013-03-03\",\"y\":2},{\"x\":\"2013-03-04\",\"y\":28},{\"x\":\"2013-03-05\",\"y\":58},{\"x\":\"2013-03-06\",\"y\":9},{\"x\":\"2013-03-07\",\"y\":59},{\"x\":\"2013-03-08\",\"y\":30},{\"x\":\"2013-03-09\",\"y\":30},{\"x\":\"2013-03-10\",\"y\":66},{\"x\":\"2013-03-11\",\"y\":48}]}" +
- "]";
+ final String layersDataDJson = "[" +
+ "{\"name\":\"ultimate\"," + "\"values\":[{\"x\":\"2013-01-01\",\"y\":11},{\"x\":\"2013-01-02\",\"y\":37},{\"x\":\"2013-01-03\",\"y\":16},{\"x\":\"2013-01-04\",\"y\":29},{\"x\":\"2013-01-05\",\"y\":40},{\"x\":\"2013-01-06\",\"y\":3},{\"x\":\"2013-01-07\",\"y\":4},{\"x\":\"2013-01-08\",\"y\":39},{\"x\":\"2013-01-09\",\"y\":34},{\"x\":\"2013-01-10\",\"y\":31},{\"x\":\"2013-01-11\",\"y\":20},{\"x\":\"2013-01-12\",\"y\":28},{\"x\":\"2013-01-13\",\"y\":19},{\"x\":\"2013-01-14\",\"y\":15},{\"x\":\"2013-01-15\",\"y\":31},{\"x\":\"2013-01-16\",\"y\":16},{\"x\":\"2013-01-17\",\"y\":40},{\"x\":\"2013-01-18\",\"y\":29},{\"x\":\"2013-01-19\",\"y\":31},{\"x\":\"2013-01-20\",\"y\":11},{\"x\":\"2013-01-21\",\"y\":36},{\"x\":\"2013-01-22\",\"y\":18},{\"x\":\"2013-01-23\",\"y\":12},{\"x\":\"2013-01-24\",\"y\":23},{\"x\":\"2013-01-25\",\"y\":32},{\"x\":\"2013-01-26\",\"y\":27},{\"x\":\"2013-01-27\",\"y\":33},{\"x\":\"2013-01-28\",\"y\":34},{\"x\":\"2013-01-29\",\"y\":5},{\"x\":\"2013-01-30\",\"y\":7},{\"x\":\"2013-01-31\",\"y\":13},{\"x\":\"2013-02-01\",\"y\":10},{\"x\":\"2013-02-02\",\"y\":43},{\"x\":\"2013-02-03\",\"y\":15},{\"x\":\"2013-02-04\",\"y\":38},{\"x\":\"2013-02-05\",\"y\":34},{\"x\":\"2013-02-06\",\"y\":38},{\"x\":\"2013-02-07\",\"y\":26},{\"x\":\"2013-02-08\",\"y\":27},{\"x\":\"2013-02-09\",\"y\":1},{\"x\":\"2013-02-10\",\"y\":12},{\"x\":\"2013-02-11\",\"y\":28},{\"x\":\"2013-02-12\",\"y\":10},{\"x\":\"2013-02-13\",\"y\":27},{\"x\":\"2013-02-14\",\"y\":34},{\"x\":\"2013-02-15\",\"y\":25},{\"x\":\"2013-02-16\",\"y\":39},{\"x\":\"2013-02-17\",\"y\":39},{\"x\":\"2013-02-18\",\"y\":25},{\"x\":\"2013-02-19\",\"y\":38},{\"x\":\"2013-02-20\",\"y\":1},{\"x\":\"2013-02-21\",\"y\":8},{\"x\":\"2013-02-22\",\"y\":31},{\"x\":\"2013-02-23\",\"y\":38},{\"x\":\"2013-02-24\",\"y\":43},{\"x\":\"2013-02-25\",\"y\":16},{\"x\":\"2013-02-26\",\"y\":41},{\"x\":\"2013-02-27\",\"y\":44},{\"x\":\"2013-02-28\",\"y\":20},{\"x\":\"2013-03-01\",\"y\":44},{\"x\":\"2013-03-02\",\"y\":25},{\"x\":\"2013-03-03\",\"y\":41},{\"x\":\"2013-03-04\",\"y\":34},{\"x\":\"2013-03-05\",\"y\":4},{\"x\":\"2013-03-06\",\"y\":28},{\"x\":\"2013-03-07\",\"y\":34},{\"x\":\"2013-03-08\",\"y\":25},{\"x\":\"2013-03-09\",\"y\":9},{\"x\":\"2013-03-10\",\"y\":33},{\"x\":\"2013-03-11\",\"y\":40}]}," +
+ "{\"name\":\"scale\",\"values\":[{\"x\":\"2013-01-01\",\"y\":22},{\"x\":\"2013-01-02\",\"y\":5},{\"x\":\"2013-01-03\",\"y\":20},{\"x\":\"2013-01-04\",\"y\":3},{\"x\":\"2013-01-05\",\"y\":7},{\"x\":\"2013-01-06\",\"y\":22},{\"x\":\"2013-01-07\",\"y\":3},{\"x\":\"2013-01-08\",\"y\":5},{\"x\":\"2013-01-09\",\"y\":5},{\"x\":\"2013-01-10\",\"y\":23},{\"x\":\"2013-01-11\",\"y\":6},{\"x\":\"2013-01-12\",\"y\":24},{\"x\":\"2013-01-13\",\"y\":7},{\"x\":\"2013-01-14\",\"y\":17},{\"x\":\"2013-01-15\",\"y\":5},{\"x\":\"2013-01-16\",\"y\":8},{\"x\":\"2013-01-17\",\"y\":3},{\"x\":\"2013-01-18\",\"y\":4},{\"x\":\"2013-01-19\",\"y\":15},{\"x\":\"2013-01-20\",\"y\":15},{\"x\":\"2013-01-21\",\"y\":2},{\"x\":\"2013-01-22\",\"y\":16},{\"x\":\"2013-01-23\",\"y\":5},{\"x\":\"2013-01-24\",\"y\":8},{\"x\":\"2013-01-25\",\"y\":10},{\"x\":\"2013-01-26\",\"y\":26},{\"x\":\"2013-01-27\",\"y\":15},{\"x\":\"2013-01-28\",\"y\":27},{\"x\":\"2013-01-29\",\"y\":24},{\"x\":\"2013-01-30\",\"y\":21},{\"x\":\"2013-01-31\",\"y\":18},{\"x\":\"2013-02-01\",\"y\":15},{\"x\":\"2013-02-02\",\"y\":23},{\"x\":\"2013-02-03\",\"y\":2},{\"x\":\"2013-02-04\",\"y\":16},{\"x\":\"2013-02-05\",\"y\":17},{\"x\":\"2013-02-06\",\"y\":15},{\"x\":\"2013-02-07\",\"y\":8},{\"x\":\"2013-02-08\",\"y\":23},{\"x\":\"2013-02-09\",\"y\":19},{\"x\":\"2013-02-10\",\"y\":26},{\"x\":\"2013-02-11\",\"y\":24},{\"x\":\"2013-02-12\",\"y\":22},{\"x\":\"2013-02-13\",\"y\":3},{\"x\":\"2013-02-14\",\"y\":0},{\"x\":\"2013-02-15\",\"y\":10},{\"x\":\"2013-02-16\",\"y\":14},{\"x\":\"2013-02-17\",\"y\":6},{\"x\":\"2013-02-18\",\"y\":5},{\"x\":\"2013-02-19\",\"y\":9},{\"x\":\"2013-02-20\",\"y\":29},{\"x\":\"2013-02-21\",\"y\":14},{\"x\":\"2013-02-22\",\"y\":16},{\"x\":\"2013-02-23\",\"y\":15},{\"x\":\"2013-02-24\",\"y\":29},{\"x\":\"2013-02-25\",\"y\":7},{\"x\":\"2013-02-26\",\"y\":4},{\"x\":\"2013-02-27\",\"y\":28},{\"x\":\"2013-02-28\",\"y\":29},{\"x\":\"2013-03-01\",\"y\":1},{\"x\":\"2013-03-02\",\"y\":23},{\"x\":\"2013-03-03\",\"y\":10},{\"x\":\"2013-03-04\",\"y\":26},{\"x\":\"2013-03-05\",\"y\":18},{\"x\":\"2013-03-06\",\"y\":25},{\"x\":\"2013-03-07\",\"y\":21},{\"x\":\"2013-03-08\",\"y\":5},{\"x\":\"2013-03-09\",\"y\":29},{\"x\":\"2013-03-10\",\"y\":13},{\"x\":\"2013-03-11\",\"y\":12}]}," +
+ "{\"name\":\"basic\",\"values\":[{\"x\":\"2013-01-01\",\"y\":14},{\"x\":\"2013-01-02\",\"y\":55},{\"x\":\"2013-01-03\",\"y\":14},{\"x\":\"2013-01-04\",\"y\":55},{\"x\":\"2013-01-05\",\"y\":7},{\"x\":\"2013-01-06\",\"y\":15},{\"x\":\"2013-01-07\",\"y\":15},{\"x\":\"2013-01-08\",\"y\":39},{\"x\":\"2013-01-09\",\"y\":28},{\"x\":\"2013-01-10\",\"y\":30},{\"x\":\"2013-01-11\",\"y\":32},{\"x\":\"2013-01-12\",\"y\":49},{\"x\":\"2013-01-13\",\"y\":67},{\"x\":\"2013-01-14\",\"y\":69},{\"x\":\"2013-01-15\",\"y\":29},{\"x\":\"2013-01-16\",\"y\":39},{\"x\":\"2013-01-17\",\"y\":54},{\"x\":\"2013-01-18\",\"y\":56},{\"x\":\"2013-01-19\",\"y\":52},{\"x\":\"2013-01-20\",\"y\":60},{\"x\":\"2013-01-21\",\"y\":4},{\"x\":\"2013-01-22\",\"y\":37},{\"x\":\"2013-01-23\",\"y\":67},{\"x\":\"2013-01-24\",\"y\":72},{\"x\":\"2013-01-25\",\"y\":45},{\"x\":\"2013-01-26\",\"y\":2},{\"x\":\"2013-01-27\",\"y\":70},{\"x\":\"2013-01-28\",\"y\":26},{\"x\":\"2013-01-29\",\"y\":19},{\"x\":\"2013-01-30\",\"y\":36},{\"x\":\"2013-01-31\",\"y\":73},{\"x\":\"2013-02-01\",\"y\":63},{\"x\":\"2013-02-02\",\"y\":67},{\"x\":\"2013-02-03\",\"y\":11},{\"x\":\"2013-02-04\",\"y\":38},{\"x\":\"2013-02-05\",\"y\":7},{\"x\":\"2013-02-06\",\"y\":53},{\"x\":\"2013-02-07\",\"y\":52},{\"x\":\"2013-02-08\",\"y\":31},{\"x\":\"2013-02-09\",\"y\":18},{\"x\":\"2013-02-10\",\"y\":66},{\"x\":\"2013-02-11\",\"y\":32},{\"x\":\"2013-02-12\",\"y\":49},{\"x\":\"2013-02-13\",\"y\":38},{\"x\":\"2013-02-14\",\"y\":1},{\"x\":\"2013-02-15\",\"y\":61},{\"x\":\"2013-02-16\",\"y\":54},{\"x\":\"2013-02-17\",\"y\":71},{\"x\":\"2013-02-18\",\"y\":69},{\"x\":\"2013-02-19\",\"y\":59},{\"x\":\"2013-02-20\",\"y\":58},{\"x\":\"2013-02-21\",\"y\":28},{\"x\":\"2013-02-22\",\"y\":66},{\"x\":\"2013-02-23\",\"y\":59},{\"x\":\"2013-02-24\",\"y\":62},{\"x\":\"2013-02-25\",\"y\":65},{\"x\":\"2013-02-26\",\"y\":18},{\"x\":\"2013-02-27\",\"y\":57},{\"x\":\"2013-02-28\",\"y\":0},{\"x\":\"2013-03-01\",\"y\":24},{\"x\":\"2013-03-02\",\"y\":48},{\"x\":\"2013-03-03\",\"y\":2},{\"x\":\"2013-03-04\",\"y\":28},{\"x\":\"2013-03-05\",\"y\":58},{\"x\":\"2013-03-06\",\"y\":9},{\"x\":\"2013-03-07\",\"y\":59},{\"x\":\"2013-03-08\",\"y\":30},{\"x\":\"2013-03-09\",\"y\":30},{\"x\":\"2013-03-10\",\"y\":66},{\"x\":\"2013-03-11\",\"y\":48}]}" +
+ "]";
List<NamedXYTimeSeries> result = mapper.readValue(layersDataDJson.getBytes(), List.class);
resp.getOutputStream().write(mapper.writeValueAsBytes(result));
@@ -240,8 +229,7 @@ public class AnalyticsServlet extends HttpServlet {
final URL resourceUrl = Resources.getResource(resourceName);
-
- final String [] parts = resourceName.split("/");
+ final String[] parts = resourceName.split("/");
if (parts.length > 2) {
if (parts[1].equals("javascript")) {
resp.setContentType("application/javascript");
@@ -255,7 +243,7 @@ public class AnalyticsServlet extends HttpServlet {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
Resources.copy(resourceUrl, out);
- String inputHtml = new String(out.toByteArray());
+ String inputHtml = new String(out.toByteArray());
// TODO STEPH we need to extract real ip port on which http sever is listening to
String tmp1 = inputHtml.replace("$VAR_SERVER", "\"127.0.0.1\"");
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/static/dashboard.html b/osgi-bundles/bundles/analytics/src/main/resources/static/dashboard.html
index 0d15319..e6fd558 100644
--- a/osgi-bundles/bundles/analytics/src/main/resources/static/dashboard.html
+++ b/osgi-bundles/bundles/analytics/src/main/resources/static/dashboard.html
@@ -28,8 +28,96 @@
</head>
<body>
<div id="chartAnchor"></div>
-
+
<script type="text/javascript">
+
+ function doGetData(server, port, analyticsPrefix, endpoint, queryParams, fn) {
+
+ var request_url = "http://" + server + ":" + port + analyticsPrefix + endpoint;
+ var first = true;
+
+ if (queryParams) {
+ var queryKeys = Object.keys(queryParams);
+ for (var i = 0; i < queryKeys.length; i++) {
+ var curKey = queryKeys[i];
+ var delim = first ? "?" : "&";
+ request_url = request_url + "?" + curKey + "=" + queryParams[curKey]
+ first = false;
+ }
+ }
+
+ console.log("request_url " + request_url);
+
+ return $.ajax({
+ type: "GET",
+ contentType: "application/json",
+ url: request_url
+ }).done(function(data) {
+ console.log("Done " + request_url + " with data " + data.length);
+ fn(data);
+ });
+ }
+
+ function drawAll(input) {
+
+ var canvasHeigthWithMargins = input.canvasHeigth + input.topMargin + input.betweenGraphMargin + input.bottomMargin;
+ var canvasHeigthGraph = input.canvasHeigth / 2;
+
+ var translateX = input.leftMargin;
+
+ var graphStructure = new killbillGraph.GraphStructure();
+
+
+ graphStructure.setupDomStructure();
+ var canvas = graphStructure.createCanvas([input.topMargin, input.rightMargin, input.bottomMargin, input.leftMargin],
+ input.canvasWidth, canvasHeigthWithMargins);
+
+ var curTranslateY = input.topMargin;
+ var curTranslateLabelY = curTranslateY + (canvasHeigthGraph / 2);
+ var lineCanvas = graphStructure.createCanvasGroup(canvas, translateX, curTranslateY);
+ var linesGraph = new killbillGraph.KBLinesGraph(lineCanvas, input.linesData, input.canvasWidth, canvasHeigthGraph, d3.scale.category20b());
+ linesGraph.drawLines();
+ linesGraph.addLabels("labelsLine", curTranslateLabelY);
+
+ curTranslateY = curTranslateY + canvasHeigthGraph + input.betweenGraphMargin;
+ curTranslateLabelY = curTranslateLabelY + input.betweenGraphMargin;
+ var stackCanvas = graphStructure.createCanvasGroup(canvas, translateX, curTranslateY);
+ var layersGraph = new killbillGraph.KBLayersGraph(stackCanvas, input.layersData, input.canvasWidth, canvasHeigthGraph, d3.scale.category20c());
+ layersGraph.drawStackLayers();
+ layersGraph.addLabels("labelsLayer", curTranslateLabelY);
+
+
+ curTranslateY = curTranslateY + canvasHeigthGraph + input.betweenGraphMargin;
+ var xAxisCanvaGroup = graphStructure.createCanvasGroup(canvas, translateX, curTranslateY);
+ layersGraph.createXAxis(xAxisCanvaGroup, 2 * (canvasHeigthGraph + input.betweenGraphMargin));
+
+ layersGraph.addMouseOverCircleForValue();
+ }
+
+ function fetchDataAndDrawAll(server, port) {
+
+ $().ready(function() {
+
+ var layersData;
+ var linesData;
+
+ $.when(doGetData(server, port, "/plugins/killbill-analytics", "/planTransitionsOverTime", null, function(data) {
+ linesData = data;
+ }), doGetData(server, port, "/plugins/killbill-analytics", "/recurringRevenueOverTime", null, function(data) {
+ layersData = data;
+ })).done(function() {
+ console.log( 'I fire once BOTH ajax requests have completed...');
+
+ var input = new killbillGraph.KBInputGraphs(800, 600, 80, 80, 80, 80, 30, [linesData, layersData]);
+ drawAll(input);
+ }) .fail(function() {
+ console.log( 'I fire if one or more requests failed.' );
+ });
+ });
+ }
+
+
+
fetchDataAndDrawAll($VAR_SERVER, $VAR_PORT);
</script>
</body>
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/static/javascript/killbill.js b/osgi-bundles/bundles/analytics/src/main/resources/static/javascript/killbill.js
index 3082242..bd11a98 100644
--- a/osgi-bundles/bundles/analytics/src/main/resources/static/javascript/killbill.js
+++ b/osgi-bundles/bundles/analytics/src/main/resources/static/javascript/killbill.js
@@ -1,499 +1,503 @@
-
-/**
-* Extract the 'x' or 'y' from dataLyer format
-* where each entry if of the form:
+/*
+* 'killbillGraph' is the namespace required to access all the public objects
*
-* "name": "crescendo",
-* "values": [
-* { "x": "2010-07-08", "y": 0},
-* ....
-*/
-function extractKeyOrValueFromDataLayer(dataLayer, attr) {
- var result = [];
- for (var i = 0; i < dataLayer.values.length; i++) {
- result.push(dataLayer.values[i][attr])
- }
- return result;
-}
-
-
-/**
-* Create the 'x' scale -- with x being a date
-*/
-function getScaleDate(dataX, w) {
- var minDate = new Date(dataX[0]);
- var maxDate = new Date(dataX[dataX.length - 1]);
- return d3.time.scale().domain([minDate, maxDate]).range([0, w]);
-}
-
-/**
-* Create the 'y' scale for line graphs (non stacked)
-*/
-function getScaleValue(dataYs, h) {
- var minValue = 0;
- var maxValue = 0;
- for (var i=0; i<dataYs.length; i++) {
- for (var j = 0; j < dataYs[i].length; j++) {
- if (dataYs[i][j] < minValue) {
- minValue = dataYs[i][j];
- }
- if (dataYs[i][j] > maxValue) {
- maxValue = dataYs[i][j];
- }
- }
- }
- if (minValue > 0) {
- minValue = 0;
- }
- return d3.scale.linear().domain([minValue, maxValue]).range([h, 0]);
- }
-
-/**
-* Create the 'y' scale for the stack graph
*
-* Extract min/max for each x value across all layers
-*
-*/
-function getStackedScaleValue(dataLayers, h) {
-
- var tmp = [];
- for (var i = 0; i < dataLayers.length; i++) {
- tmp.push(dataLayers[i].values)
- }
-
- var sumValues = [];
- for (var i = 0; i < tmp[0].length; i++) {
- var max = 0;
- for (var j = 0; j < tmp.length; j++) {
- max = max + tmp[j][i].y;
- }
- sumValues.push(max);
- }
- var minValue = 0;
- var maxValue = 0;
- for (var i = 0; i < sumValues.length; i++) {
- if (sumValues[i] < minValue) {
- minValue = sumValues[i];
- }
- if (sumValues[i] > maxValue) {
- maxValue = sumValues[i];
- }
- }
- if (minValue > 0) {
- minValue = 0;
- }
- return d3.scale.linear().domain([minValue, maxValue]).range([h, 0]);
-}
-
-
-/**
-* Create the 'X' axis in a new svg group
-*/
-function createXAxis(graph, scaleX, h, xAxisHeightTick) {
- var xAxis = d3.svg.axis().scale(scaleX).tickSize(- xAxisHeightTick).tickSubdivide(true);
- graph.append("svg:g")
- .attr("class", "x axis")
- .attr("transform", "translate(0," + h + ")")
- .call(xAxis);
-}
-
-/**
-* Create the 'Y' axis in a new svg group
-*/
-function createYAxis(graph, scaleY) {
- var yAxisLeft = d3.svg.axis().scale(scaleY).ticks(4).orient("left");
- graph.append("svg:g")
- .attr("class", "y axis")
- .attr("transform", "translate(-25,0)")
- .call(yAxisLeft);
-}
-
-/**
-* Create the area function that defines for each point in the stack graph
-* its x, y0 (offest from previous stacked graph) and y position
+* Input are expected to be of the form:
+* dataForGraph = [ {"name":"line1", "values":[{"x":"2013-01-01", "y":6}, {"x":"2013-01-02", "y":6}] },
+* {"name":"line2", "values":[{"x":"2013-01-01", "y":12}, {"x":"2013-01-02", "y":3}] } ];
+*
+* There can be up to 20 lines -- limited by the color palette -- per graph; the graph can be either:
+* - layered graph (KBLayersGraph)
+* - lines graph (KBLinesGraph)
+*
+* Description of the fields:
+* - name is the 'name of the line-- as shown in the label
+* - values are the {x,y} coordinates for each point; the x coordinates should be dates and should all be the same for each entries.
+*
*/
-function createLayerArea(scaleX, scaleY) {
- var area = d3.svg.area()
- .x(function(d) {
- return scaleX(new Date(d.x));
- })
- .y0(function(d) {
- return scaleY(d.y0);
- })
- .y1(function(d) {
- return scaleY(d.y + d.y0);
+(function(killbillGraph, $, undefined) {
+
+ /**
+ * Input parameters to draw all the graphs
+ */
+ killbillGraph.KBInputGraphs = function(canvasWidth, canvasHeigth, topMargin, rightMargin, bottomMargin, leftMargin, betweenGraphMargin, graphData) {
+
+ this.topMargin = topMargin;
+ this.rightMargin = rightMargin;
+ this.bottomMargin = bottomMargin;
+ this.leftMargin = leftMargin;
+
+
+ this.betweenGraphMargin = betweenGraphMargin;
+
+ this.canvasWidth = canvasWidth;
+ this.canvasHeigth = canvasHeigth;
+
+ this.linesData = graphData[0];
+ this.layersData = graphData[1];
+ }
+
+
+ /**
+ * KBGraph : Base class for both layered and non layered graphs
+ */
+ killbillGraph.KBGraph = function(graphCanvas, data, width, heigth, palette) {
+
+ this.graphCanvas = graphCanvas;
+ this.data = data;
+ this.width = width;
+ this.heigth = heigth;
+
+ // the palette function out of which we create color map
+ this.palette = palette;
+
+
+ /**
+ * Create the 'x' date scale
+ * - dataX is is an ordered array of all the dates
+ */
+ this.getScaleDate = function() {
+
+ var dataX = this.extractKeyOrValueFromDataLayer(this.data[0], 'x');
+ var minDate = new Date(dataX[0]);
+ var maxDate = new Date(dataX[dataX.length - 1]);
+ return d3.time.scale().domain([minDate, maxDate]).range([0, width]);
+ }
+
+ /**
+ * Create the 'Y' axis in a new svg group
+ * - scaleY is the d3 scale built based on height and y point range
+ */
+ this.createYAxis = function(scaleY) {
+ var yAxisLeft = d3.svg.axis().scale(scaleY).ticks(4).orient("left");
+ this.graphCanvas.append("svg:g")
+ .attr("class", "y axis")
+ .attr("transform", "translate(-25,0)")
+ .call(yAxisLeft);
+ }
+
+ /**
+ * Create the 'X' axis in a new svg group
+ * - dataLayer : the data for the layer forma
+ * - xAxisGraphGroup the group where this axis will be attached to
+ * - xAxisHeightTick the height of the ticks
+ */
+ this.createXAxis = function(xAxisGraphGroup, xAxisHeightTick) {
+
+ var scaleX = this.getScaleDate();
+ var xAxis = d3.svg.axis().scale(scaleX).tickSize(- xAxisHeightTick).tickSubdivide(true);
+ xAxisGraphGroup.append("svg:g")
+ .attr("class", "x axis")
+ .call(xAxis);
+ }
+
+
+ /**
+ * Add the cirles for each point in the graph line
+ *
+ * This is used for both stacked and non stacked lines
+ */
+ this.addCirclesForGraph = function(circleGroup, lineId, dataX, dataY, scaleX, scaleY, lineColor) {
+ var node = circleGroup.selectAll("circles")
+ .data(dataY)
+ .enter()
+ .append("svg:g");
+
+ /* First we add the circle */
+ node.append("svg:circle")
+ .attr("id", function(d, i) {
+ return "circle-" + lineId + "-" + i; })
+ .attr("cx", function(d, i) {
+ return scaleX(new Date(dataX[i]));
+ })
+ .attr("cy", function(d, i) {
+ return scaleY(d);
+ })
+ .attr("r", 3)
+ .attr("fill", lineColor)
+ .attr("value", function(d, i) {
+ return d;
+ });
+
+ /* Second we do another pass and add the overlay text for value */
+ node.append("svg:text")
+ .attr("x", function(d, i) {
+ return scaleX(new Date(dataX[i]));
+ })
+ .attr("y", function(d, i) {
+ return scaleY(d);
+ })
+ .attr("class", "overlay")
+ .attr("display", "none")
+ .text(function(d, i) {
+ return "value = " + d;
+ });
+ }
+
+ /**
+ * Extract the 'x' or 'y' from dataLyer format where each entry if of the form:
+ * - attr is either the 'x' or 'y'
+ * - dataLayer : the data for a given layer
+ * E.g:
+ * "name": "crescendo",
+ * "values": [
+ * { "x": "2010-07-08", "y": 0},
+ * ....
+ */
+ this.extractKeyOrValueFromDataLayer = function(dataLayer, attr) {
+ var result = [];
+ for (var i = 0; i < dataLayer.values.length; i++) {
+ result.push(dataLayer.values[i][attr])
+ }
+ return result;
+ }
+
+
+ /**
+ * Create the 'y' scale for the stack graph
+ *
+ * Extract min/max for each x value across all layers
+ *
+ */
+ this.getYScaleValue = function(dataLayers, h) {
+
+ var tmp = [];
+ for (var i = 0; i < dataLayers.length; i++) {
+ tmp.push(dataLayers[i].values)
+ }
+
+ var sumValues = [];
+ for (var i = 0; i < tmp[0].length; i++) {
+ var max = 0;
+ for (var j = 0; j < tmp.length; j++) {
+ max = max + tmp[j][i].y;
+ }
+ sumValues.push(max);
+ }
+ var minValue = 0;
+ var maxValue = 0;
+ for (var i = 0; i < sumValues.length; i++) {
+ if (sumValues[i] < minValue) {
+ minValue = sumValues[i];
+ }
+ if (sumValues[i] > maxValue) {
+ maxValue = sumValues[i];
+ }
+ }
+ if (minValue > 0) {
+ minValue = 0;
+ }
+ return d3.scale.linear().domain([minValue, maxValue]).range([h, 0]);
+ }
+
+
+
+ /**
+ * Add on the path the name of the line -- not used anymore as we are using external labels
+ */
+ this.addPathLabel = function(graph, lineId, positionPercent) {
+ graph.append("svg:g")
+ .append("text")
+ .attr("font-size", "15")
+ .append("svg:textPath")
+ .attr("xlink:href", "#" + lineId)
+ .attr("startOffset", positionPercent)
+ .text(function(d) { return lineId; });
+ }
+
+
+
+ /**
+ * Create a new group for the circles-- no translations needed
+ */
+ this.createCircleGroup = function(canvas, lineId) {
+ return this.graphCanvas.append("svg:g")
+ .attr("id", "circles-" + lineId);
+ }
+
+ /**
+ * Given a colorMap, extract the k-ieme color
+ *
+ * The colormap are standard d3 colormap which swicth to new color every 4 colors;
+ * in order to maximize the difference among colors we first get colors that are far apar
+ *
+ */
+ this.getColor = function(k) {
+ var div = Math.floor(k / 4);
+ var mod = k % 4;
+ var value = div + 4 * mod;
+ return this.colorMap[value];
+ }
+
+ /**
+ * Create the color map from the d3 palette
+ */
+ this.createColorMap = function() {
+ var colorMap = {}
+ for (var i = 0; i < 20; i++) {
+ colorMap[i] = this.palette(i);
+ }
+ return colorMap;
+ }
+
+ /**
+ * Add the list label on the 'legend'
+ */
+
+ this.addLabels = function(labelId, translateY) {
+
+ var $divLabelLayers = $('<div id=' + labelId +' style="margin-top:' + translateY + 'px"></div>');
+ var $labelList = $('<ul></ul>');
+ $divLabelLayers.append($labelList);
+
+ $("#legend").append($divLabelLayers);
+ for (var i = 0; i < this.data.length; i++) {
+ this.addLabel($labelList, this.getColor(i), this.data[i].name);
+ }
+ }
+
+ /**
+ * Add a given label
+ */
+ this.addLabel = function(labelList, color, labelName) {
+
+ var $labelListItem = $('<li style="list-style-type: none">');
+ var $divLabelListItem = $('<div id=label-"' + labelName + '" class="swatch" style="background-color:' + color + '"></div>');
+ var $spanListItemName = $('<span>' + labelName + '</span> ');
+
+ $labelListItem.append($divLabelListItem);
+ $labelListItem.append($spanListItemName);
+ labelList.append($labelListItem);
+ }
+
+ /**
+ * Attach handlers to all circles so as to display value
+ *
+ * Note that this will attach for all graphs-- not only the one attached to that objec
+ */
+ this.addMouseOverCircleForValue = function() {
+
+ $('circle').each(function(i) {
+ var circleGroup = $(this).parent();
+ var circleText = circleGroup.find('text').first();
+
+ $(this).hover(function() {
+ circleText.show();
+ }, function() {
+ circleText.hide();
+ });
});
- return area;
-}
+ }
-/**
-* All all layers on the graph
-*/
-function addLayers(graph, colorMapLayers, stack, area, dataLayers) {
-
- var dataLayerStack = stack(dataLayers);
-
- graph.selectAll("path")
- .data(dataLayerStack)
- .enter()
- .append("path")
- .style("fill", function(d,i) {
- return getColor(colorMapLayers, i);
- }).attr("d", function(d) {
- return area(d.values);
- })
- .attr("id", function(d) {
- return d.name;
- });
-}
-
-/**
-* Draw all layers-- calls previous function addLayers
-* It will create its Y axis
-*/
-function drawStackLayers(graph, margins, colorMapLayers, dataLayers, w, h, xAxisHeightTick) {
+ /* Build and save colorMap */
+ this.colorMap = this.createColorMap();
+ }
- // Compute scales
- var dataX = extractKeyOrValueFromDataLayer(dataLayers[0], 'x');
- var scaleX = getScaleDate(dataX, w);
- var scaleY = getStackedScaleValue(dataLayers, h);
+ /**
+ * KBLayersGraph : Inherits KBGraph abd offers specifities for layered graphs
+ */
+ killbillGraph.KBLayersGraph = function(graphCanvas, data, width, heigth, palette) {
- var stack = d3.layout.stack()
- .offset("zero")
- .values(function(d) { return d.values; });
+ killbillGraph.KBGraph.call(this, graphCanvas, data, width, heigth, palette);
- var area = createLayerArea(scaleX, scaleY);
- addLayers(graph, colorMapLayers, stack, area, dataLayers);
- var dataY0 = null;
- for (var i = 0; i < dataLayers.length; i++) {
+ /**
+ * Create the area function that defines for each point in the stack graph
+ * its x, y0 (offest from previous stacked graph) and y position
+ */
+ this.createLayerArea = function(scaleX, scaleY) {
+ var area = d3.svg.area()
+ .x(function(d) {
+ return scaleX(new Date(d.x));
+ })
+ .y0(function(d) {
+ return scaleY(d.y0);
+ })
+ .y1(function(d) {
+ return scaleY(d.y + d.y0);
+ });
+ return area;
+ }
- var circleGroup = createCircleGroup(graph, dataLayers[i]['name'], margins[3], margins[0]);
- var dataY = extractKeyOrValueFromDataLayer(dataLayers[i], 'y');
- if (dataY0) {
- for (var k = 0; k < dataY.length; k++) {
- dataY[k] = dataY[k] + dataY0[k];
- }
- }
- addCirclesForGraph(circleGroup, dataLayers[i]['name'], dataX, dataY, scaleX, scaleY, getColor(colorMapLayers, i));
- dataY0 = dataY;
+ /**
+ * All all layers on the graph
+ */
+ this.addLayers = function(stack, area, dataLayers) {
+
+ var dataLayerStack = stack(dataLayers);
+
+ var currentObj = this;
+
+ this.graphCanvas.selectAll("path")
+ .data(dataLayerStack)
+ .enter()
+ .append("path")
+ .style("fill", function(d,i) {
+ return currentObj.getColor(i);
+ }).attr("d", function(d) {
+ return area(d.values);
+ })
+ .attr("id", function(d) {
+ return d.name;
+ });
}
- createYAxis(graph, scaleY);
-}
+ /**
+ * Draw all layers-- calls previous function addLayers
+ * It will create its Y axis
+ */
+ this.drawStackLayers = function() {
-/**
-* Add the svg line for this data (dataX, dataY)
-*/
-function addLine(graph, margins, dataX, dataY, scaleX, scaleY, lineColor, lineId) {
- graph.selectAll("path.line")
- .data([dataY])
- .enter()
- .append("svg:path")
- .attr("d", d3.svg.line()
- .x(function(d,i) {
- return scaleX(new Date(dataX[i]));
- })
- .y(function(d) {
- return scaleY(d);
- }))
- .attr("id", lineId)
- .style("stroke", lineColor);
-
- var circleGroup = createCircleGroup(graph, lineId, margins[3], margins[0] );
- addCirclesForGraph(circleGroup, lineId, dataX, dataY, scaleX, scaleY, lineColor);
-}
-
-
-/**
-* Draw all lines
-* It will create its Y axis
-*/
-function drawLines(graph, margins, colorMapLines, linesData, w, h) {
-
- var dataX = linesData[0]["dates"]
- var dataYs = [];
- for (var i = 0; i < linesData.length; i++) { dataYs.push(linesData[i]["values"]); }
-
- var scaleX = getScaleDate(dataX, w);
- var scaleY = getScaleValue(dataYs, h);
-
- for (var k=0; k<dataYs.length; k++) {
- addLine(graph, margins, dataX, dataYs[k], scaleX, scaleY, getColor(colorMapLines, k), linesData[k]['name']);
- }
- createYAxis(graph, scaleY);
- }
-
-
- /**
- * Add the cirles for each point in the graph line
- *
- * This is used for both stacked and non stacked lines
- */
- function addCirclesForGraph(circleGroup, lineId, dataX, dataY, scaleX, scaleY, lineColor) {
- var node = circleGroup.selectAll("circles")
- .data(dataY)
- .enter()
- .append("svg:g");
-
- /* First we add the circle */
- node.append("svg:circle")
- .attr("id", function(d, i) {
- return "circle-" + lineId + "-" + i; })
- .attr("cx", function(d, i) {
- return scaleX(new Date(dataX[i]));
- })
- .attr("cy", function(d, i) {
- return scaleY(d);
- })
- .attr("r", 3)
- .attr("fill", lineColor)
- .attr("value", function(d, i) {
- return d;
- });
-
- /* Second we do another pass and add the overlay text for value */
- node.append("svg:text")
- .attr("x", function(d, i) {
- return scaleX(new Date(dataX[i]));
- })
- .attr("y", function(d, i) {
- return scaleY(d);
- })
- .attr("class", "overlay")
- .attr("display", "none")
- .text(function(d, i) {
- return "value = " + d;
- });
-}
+ var scaleX = this.getScaleDate();
+ var scaleY = this.getYScaleValue(this.data, this.heigth);
-/**
-* Add on the path the name of the line -- not used anymore as we are using external labels
-*/
-function addPathLabel(graph, lineId, positionPercent) {
- graph.append("svg:g")
- .append("text")
- .attr("font-size", "15")
- .append("svg:textPath")
- .attr("xlink:href", "#" + lineId)
- .attr("startOffset", positionPercent)
- .text(function(d) { return lineId; });
- }
-
-/**
-* Create initial canvas on which to draw all graphs
-*/
-function createCanvas(m, w, h) {
- return d3.select("#chartId")
- .append("svg:svg")
- .attr("width", w + m[1] + m[3])
- .attr("height", h + m[0] + m[2]);
-}
-
-/**
-* Create a new group and make the translation to leave room for margins
-*/
-function createCanvasGroup(canvas, translateX, translateY) {
- return canvas
- .append("svg:g")
- .attr("transform", "translate(" + translateX + "," + translateY + ")");
-}
-
-/**
-* Create a new group for the circles-- no translations needed
-*/
-function createCircleGroup(canvas, lineId, translateX, translateY) {
- return canvas.append("svg:g")
- .attr("id", "circles-" + lineId);
-}
+ var stack = d3.layout.stack()
+ .offset("zero")
+ .values(function(d) { return d.values; });
-/**
-* Given a colorMap, extract the k-ieme color
-*
-* The colormap are standard d3 colormap which swicth to new color every 4 colors;
-* in order to maximize the difference among colors we first get colors that are far apart
-*
-*/
-function getColor(colorMap, k) {
- var div = Math.floor(k / 4);
- var mod = k % 4;
- var value = div + 4 * mod;
- return colorMap[value];
-}
-
-/**
-* Create the color map from the d3 palette
-*/
-function createColorMap(palette) {
- var colorMap = {}
- for (var i = 0; i < 20; i++) {
- colorMap[i] = palette(i);
- }
- return colorMap;
-}
-
-/**
-* Add the list label on the 'legend'
-*/
+ var area = this.createLayerArea(scaleX, scaleY);
-function addLabels(linesOrLayers, labelId, colorMap, className) {
-
- var $divLabelLayers = $('<div id=' + labelId +' class=' + className + ' ></div>');
- var $labelList = $('<ul></ul>');
- $divLabelLayers.append($labelList);
-
- $("#legend").append($divLabelLayers);
- for (var i = 0; i < linesOrLayers.length; i++) {
- addLabel($labelList, getColor(colorMap, i), linesOrLayers[i]);
- }
-}
-
-/**
-* Add a given label
-*/
-function addLabel(labelList, color, labelName) {
-
- var $labelListItem = $('<li style="list-style-type: none">');
- var $divLabelListItem = $('<div id=label-"' + labelName + '" class="swatch" style="background-color:' + color + '"></div>');
- var $spanListItemName = $('<span>' + labelName + '</span> ');
-
- $labelListItem.append($divLabelListItem);
- $labelListItem.append($spanListItemName);
-
- labelList.append($labelListItem);
-}
-
-/**
-* Setup the main divs for both legend and main charts
-*
-* It is expected to have a mnain div anchir on the html with id = 'chartAnchor'.
-*/
-function setupDomStructure() {
-
- var $divLegend = $('<div id="legend" class="legend">');
- var $divLegendText = $('<h1>Killbill Data</h1>');
- $divLegend.append($divLegendText);
-
- var $divChart = $('<div id="charts" class="charts">');
- var $spanChart = $('<span id="chartId" class="charts"></span>');
- $divChart.prepend($spanChart);
-
- $("#chartAnchor").append($divLegend);
- $("#chartAnchor").append($divChart);
-}
-
-
-/**
-* Attach handlers to all circles so as to display value
-*/
-function addMouseOverCircleForValue() {
- $('circle').each(function(i) {
-
- var circleGroup = $(this).parent();
- var circleText = circleGroup.find('text').first();
-
- $(this).hover(function() {
- circleText.show();
- }, function() {
- circleText.hide();
- });
- });
-}
-
-/**
-* Draw the dashboard based on the data provided.
-*/
-function drawAll(ajaxLinesData, ajaxLayersData) {
-
-
- var colorMapLines = createColorMap(d3.scale.category20b());
- var colorMapLayers = createColorMap(d3.scale.category20c());
-
- var margins = [80, 80, 20, 80];
- var width = 1000 - margins[1] - margins[3];
- var heigth = 800 - margins[0] - margins[2];
-
- setupDomStructure();
-
- var canvas = createCanvas(margins, width, heigth + (margins[0] + margins[2]) );
-
- var lineCanvas = createCanvasGroup(canvas, margins[3], margins[0]);
-
- var linesDataValues = [];
- for (var i = 0; i < ajaxLinesData.length; i++) { linesDataValues.push(ajaxLinesData[i]["values"]); }
- drawLines(lineCanvas, margins, colorMapLines, ajaxLinesData, width, heigth / 2);
-
- var stackCanvas = createCanvasGroup(canvas, margins[3], (heigth / 2) + 2 * margins[0] );
- drawStackLayers(stackCanvas, margins, colorMapLayers, ajaxLayersData, width, heigth / 2, (heigth + margins[0]));
-
- var dataX = extractKeyOrValueFromDataLayer(ajaxLayersData[0], 'x');
- var scaleX = getScaleDate(dataX, width);
-
- var xAxisCanvaGroup = createCanvasGroup(canvas, margins[3], (heigth / 2) + 2 * margins[0]);
- createXAxis(xAxisCanvaGroup, scaleX, heigth / 2, (heigth + margins[0]));
-
- var lines = []
- for (var i = 0; i < ajaxLinesData.length; i++) { lines.push(ajaxLinesData[i]["name"]) }
- addLabels(lines, "labelsLine", colorMapLines, "labelLines");
-
- var layers = [];
- for (var i = 0; i < ajaxLayersData.length; i++) { layers.push(ajaxLayersData[i]["name"]) }
- addLabels(layers, "labelsLayer" , colorMapLayers, "labelLayers");
-
- addMouseOverCircleForValue();
- }
-
-/**
-* Ajax call to retrieve the data from the server
-*/
-function doGetData(server, port, analyticsPrefix, endpoint, queryParams, fn) {
- var request_url = "http://" + server + ":" + port + analyticsPrefix + endpoint;
- var first = true;
- if (queryParams) {
-
- var queryKeys = Object.keys(queryParams);
- for (var i = 0; i < queryKeys.length; i++) {
- var curKey = queryKeys[i];
- var delim = first ? "?" : "&";
- request_url = request_url + "?" + curKey + "=" + queryParams[curKey]
- first = false;
- }
- }
-
- console.log("request_url " + request_url);
-
- return $.ajax({
- type: "GET",
- contentType: "application/json",
- url: request_url
- }).done(function(data) {
- console.log("Done " + request_url + " with data " + data.length);
- fn(data);
- });
-}
-
-/**
-* Entry point where we specify server and port to retrieve data can call drawlAll()
-*/
-function fetchDataAndDrawAll(server, port) {
-
- $().ready(function() {
-
- var layersData;
- var linesData;
-
- $.when(doGetData(server, port, "/plugins/killbill-analytics", "/planTransitionsOverTime", null, function(data) {
- linesData = data;
- }), doGetData(server, port, "/plugins/killbill-analytics", "/recurringRevenueOverTime", null, function(data) {
- layersData = data;
- })).done(function() {
- console.log( 'I fire once BOTH ajax requests have completed: linesData = ' + linesData.length);
- console.log( 'I fire once BOTH ajax requests have completed: layersData = ' + layersData.length);
- drawAll(linesData, layersData);
- })
- .fail(function() {
- console.log( 'I fire if one or more requests failed.' );
- });
- });
-}
+ this.addLayers(stack, area, this.data);
+
+ var dataX = this.extractKeyOrValueFromDataLayer(this.data[0], 'x');
+ var dataY0 = null;
+ for (var i = 0; i < this.data.length; i++) {
+
+ var circleGroup = this.createCircleGroup(this.data[i]['name']);
+ var dataY = this.extractKeyOrValueFromDataLayer(this.data[i], 'y');
+ if (dataY0) {
+ for (var k = 0; k < dataY.length; k++) {
+ dataY[k] = dataY[k] + dataY0[k];
+ }
+ }
+ this.addCirclesForGraph(circleGroup, this.data[i]['name'], dataX, dataY, scaleX, scaleY, this.getColor(i));
+ dataY0 = dataY;
+ }
+
+ this.createYAxis(scaleY);
+ }
+
+ }
+ killbillGraph.KBLayersGraph.prototype = Object.create(killbillGraph.KBGraph.prototype);
+
+
+
+ /**
+ * KBLayersGraph : Inherits KBGraph abd offers specifities for layered graphs
+ */
+ killbillGraph.KBLinesGraph = function(graphCanvas, data, width, heigth, palette) {
+
+ killbillGraph.KBGraph.call(this, graphCanvas, data, width, heigth, palette);
+
+ /**
+ * Create the 'y' scale for line graphs (non stacked)
+ */
+ this.getScaleValue = function(dataYs, h) {
+ var minValue = 0;
+ var maxValue = 0;
+ for (var i=0; i<dataYs.length; i++) {
+ for (var j = 0; j < dataYs[i].length; j++) {
+ if (dataYs[i][j] < minValue) {
+ minValue = dataYs[i][j];
+ }
+ if (dataYs[i][j] > maxValue) {
+ maxValue = dataYs[i][j];
+ }
+ }
+ }
+ if (minValue > 0) {
+ minValue = 0;
+ }
+ return d3.scale.linear().domain([minValue, maxValue]).range([h, 0]);
+ }
+
+ /**
+ * Add the svg line for this data (dataX, dataY)
+ */
+ this.addLine = function(dataY, scaleX, scaleY, lineColor, lineId) {
+
+ var dataX = this.extractKeyOrValueFromDataLayer(this.data[0], 'x');
+ this.graphCanvas.selectAll("path.line")
+ .data([dataY])
+ .enter()
+ .append("svg:path")
+ .attr("d", d3.svg.line()
+ .x(function(d,i) {
+ return scaleX(new Date(dataX[i]));
+ })
+ .y(function(d) {
+ return scaleY(d);
+ }))
+ .attr("id", lineId)
+ .style("stroke", lineColor);
+
+ var circleGroup = this.createCircleGroup(lineId);
+ this.addCirclesForGraph(circleGroup, lineId, dataX, dataY, scaleX, scaleY, lineColor);
+ }
+
+
+ /**
+ * Draw all lines
+ * It will create its Y axis
+ */
+ this.drawLines = function() {
+
+ var scaleX = this.getScaleDate();
+ var scaleY = this.getYScaleValue(this.data, this.heigth);
+
+ for (var k=0; k<this.data.length; k++) {
+ var dataY = this.extractKeyOrValueFromDataLayer(this.data[k], 'y');
+ this.addLine(dataY, scaleX, scaleY, this.getColor(k), this.data[k]['name']);
+ }
+ this.createYAxis(scaleY);
+ }
+
+ }
+ killbillGraph.KBLinesGraph.prototype = Object.create(killbillGraph.KBGraph.prototype);
+
+
+ killbillGraph.GraphStructure = function() {
+
+ /**
+ * Setup the main divs for both legend and main charts
+ *
+ * It is expected to have a mnain div anchir on the html with id = 'chartAnchor'.
+ */
+ this.setupDomStructure = function() {
+
+ var $divLegend = $('<div id="legend" class="legend">');
+ //var $divLegendText = $('<h1>Killbill Data</h1>');
+ //$divLegend.append($divLegendText);
+
+ var $divChart = $('<div id="charts" class="charts">');
+ var $spanChart = $('<span id="chartId" class="charts"></span>');
+ $divChart.prepend($spanChart);
+
+ $("#chartAnchor").append($divLegend);
+ $("#chartAnchor").append($divChart);
+ }
+
+
+ /**
+ * Create initial canvas on which to draw all graphs
+ */
+ this.createCanvas = function(m, w, h) {
+ return d3.select("#chartId")
+ .append("svg:svg")
+ .attr("width", w + m[1] + m[3])
+ .attr("height", h + m[0] + m[2]);
+ }
+
+
+ /**
+ * Create a new group and make the translation to leave room for margins
+ */
+ this.createCanvasGroup = function(canvas, translateX, translateY) {
+ return canvas
+ .append("svg:g")
+ .attr("transform", "translate(" + translateX + "," + translateY + ")");
+ }
+ };
+
+} (window.killbillGraph = window.killbillGraph || {}, jQuery));
diff --git a/osgi-bundles/bundles/analytics/src/main/resources/static/styles/dashboard.css b/osgi-bundles/bundles/analytics/src/main/resources/static/styles/dashboard.css
index 461f0c0..3bbdc8b 100644
--- a/osgi-bundles/bundles/analytics/src/main/resources/static/styles/dashboard.css
+++ b/osgi-bundles/bundles/analytics/src/main/resources/static/styles/dashboard.css
@@ -13,14 +13,6 @@ display: inline-block;
vertical-align: top;
}
-.labelLines {
- margin-top: 200px;
-}
-
-.labelLayers {
- margin-top: 350px;
-}
-
.charts {
display: inline-block;
position: relative;