OpenEISGvizHelper.java
/*
* This file is part of WattDepot.
*
* Copyright (C) 2015 Cam Moore
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.wattdepot.extension.openeis.util;
import com.google.visualization.datasource.base.DataSourceException;
import com.google.visualization.datasource.base.TypeMismatchException;
import com.google.visualization.datasource.datatable.ColumnDescription;
import com.google.visualization.datasource.datatable.DataTable;
import com.google.visualization.datasource.datatable.TableRow;
import com.google.visualization.datasource.datatable.value.ValueType;
import com.google.visualization.datasource.render.JsonRenderer;
import org.wattdepot.common.domainmodel.InterpolatedValue;
import org.wattdepot.common.domainmodel.InterpolatedValueList;
import org.wattdepot.extension.openeis.domainmodel.XYInterpolatedValuesWithAnalysis;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Map;
/**
* GvizHelper - Utility class that handles Google Visualization using the Google Visualization
* Datasource library.
* <p/>
* * @see <a
* href="http://code.google.com/apis/chart/interactive/docs/dev/implementing_data_source.html">Google
* Visualization Datasource API</a>
*
* @author Cam Moore
*/
public class OpenEISGvizHelper extends org.wattdepot.common.util.GvizHelper {
/**
* @param resource server resource object
* @param tqxString gviz tqx query string, i.e., request id
* @param tqString gviz tq query string, selectable fields
* @return gviz response
*/
public static String getDailyGvizResponse(Object resource, String tqxString, String tqString) {
DataTable table = null;
if (resource instanceof InterpolatedValueList) {
InterpolatedValueList list = (InterpolatedValueList) resource;
table = getRow24HourPerDayDataTable(list);
StringBuilder sb = new StringBuilder();
sb.append("google.visualization.Query.setResponse");
String reqId = null;
if (tqxString != null) {
String[] tqxArray = tqxString.split(";");
for (String s : tqxArray) {
if (s.contains("reqId")) {
reqId = s.substring(s.indexOf(":") + 1, s.length());
}
}
}
String tableString = JsonRenderer.renderDataTable(table, true, true, true).toString();
if (list.getMissingData().size() > 0) {
sb.append("({status:'warning',");
}
else {
sb.append("({status:'ok',");
}
if (reqId != null) {
sb.append("reqId:'" + reqId + "',");
}
if (list.getMissingData().size() > 0) {
sb.append("warnings:[");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
for (InterpolatedValue v : list.getMissingData()) {
sb.append("{reason: 'missing data " + df.format(v.getStart()) + " to " + df.format(v.getEnd()) + "'},");
}
if (sb.length() > 0) {
sb.substring(0, sb.length() - 1);
}
sb.append("],");
}
sb.append("table:" + tableString + "});");
return sb.toString();
}
return getGvizResponseFromDataTable(table, tqxString/*, tqString*/);
}
/**
* Returns a DataTable representing a line graph who's x values are the percentage.
*
* @param valueList The values.
* @return The DataTable suitable for a line graph.
*/
public static DataTable getPercentageDataTable(InterpolatedValueList valueList) {
DataTable data = new DataTable();
ArrayList<InterpolatedValue> values = valueList.getInterpolatedValues();
if (!values.isEmpty()) {
data.addColumn(new ColumnDescription("Percent", ValueType.NUMBER, "Percent"));
data.addColumn(new ColumnDescription("Power", ValueType.NUMBER, "W"));
int count = 0;
int size = values.size();
for (InterpolatedValue v : values) {
TableRow row = new TableRow();
row.addCell((100.0 * count++) / size);
row.addCell(v.getValue());
try {
data.addRow(row);
}
catch (TypeMismatchException e) {
e.printStackTrace();
}
}
}
return data;
}
/**
* Returns the daily DataTable based upon one value per hour.
*
* @param valueList The hourly values.
* @return The DataTable with a row per day an 24 hourly entries.
*/
public static DataTable getRow24HourPerDayDataTable(InterpolatedValueList valueList) {
DataTable data = new DataTable();
DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
// Sets up the columns requested by any SELECT in the datasource query
ArrayList<InterpolatedValue> values = valueList.getInterpolatedValues();
if (!values.isEmpty()) {
int numDays = values.size() / 24;
data.addColumn(
new ColumnDescription("Date", ValueType.TEXT, "Date"));
for (int i = 0; i < 24; i++) {
data.addColumn(
new ColumnDescription("Hour" + i, ValueType.NUMBER, "" + i));
}
for (int j = 0; j < numDays; j++) {
TableRow row = new TableRow();
row.addCell(df.format(values.get(j * 24).getStart())); // hour
for (int k = 0; k < 24; k++) {
Double value = values.get(j * 24 + k).getValue();
if (value != null) {
row.addCell(value);
}
}
try {
data.addRow(row);
}
catch (TypeMismatchException e) {
e.printStackTrace();
}
}
}
return data;
}
/**
* @param resource server resource object
* @param tqxString gviz tqx query string, i.e., request id
* @param tqString gviz tq query string, selectable fields
* @return gviz response
*/
public static String getPercentageGvizResponse(Object resource, String tqxString, String tqString) {
DataTable table = null;
if (resource instanceof InterpolatedValueList) {
InterpolatedValueList list = (InterpolatedValueList) resource;
table = getPercentageDataTable(list);
StringBuilder sb = new StringBuilder();
sb.append("google.visualization.Query.setResponse");
String reqId = null;
if (tqxString != null) {
String[] tqxArray = tqxString.split(";");
for (String s : tqxArray) {
if (s.contains("reqId")) {
reqId = s.substring(s.indexOf(":") + 1, s.length());
}
}
}
String tableString = JsonRenderer.renderDataTable(table, true, true, true).toString();
if (list.getMissingData().size() > 0) {
sb.append("({status:'warning',");
}
else {
sb.append("({status:'ok',");
}
if (reqId != null) {
sb.append("reqId:'" + reqId + "',");
}
if (list.getMissingData().size() > 0) {
sb.append("warnings:[");
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
for (InterpolatedValue v : list.getMissingData()) {
sb.append("{reason: 'missing data " + df.format(v.getStart()) + " to " + df.format(v.getEnd()) + "'},");
}
sb.substring(0, sb.length() - 1);
sb.append("],");
}
sb.append("table:" + tableString + "});");
return sb.toString();
}
return null;
}
/**
* @param resource server resource object
* @param tqxString gviz tqx query string, i.e., request id
* @param tqString gviz tq query string, selectable fields
* @return gviz response
*/
public static String getGvizResponse(Object resource, String tqxString, String tqString) {
if (resource instanceof XYInterpolatedValuesWithAnalysis) {
XYInterpolatedValuesWithAnalysis analysis = (XYInterpolatedValuesWithAnalysis) resource;
try {
DataTable table = getDataTable(analysis.getDataPoints());
StringBuilder sb = new StringBuilder();
sb.append("google.visualization.Query.setResponse");
String reqId = null;
if (tqxString != null) {
String[] tqxArray = tqxString.split(";");
for (String s : tqxArray) {
if (s.contains("reqId")) {
reqId = s.substring(s.indexOf(":") + 1, s.length());
}
}
}
String tableString = JsonRenderer.renderDataTable(table, true, true, true).toString();
if (analysis.getAnalysis().entrySet().size() > 0) {
sb.append("({status:'warning',");
}
else {
sb.append("({status:'ok',");
}
if (reqId != null) {
sb.append("reqId:'" + reqId + "',");
}
sb.append("warnings:[");
boolean added = false;
DecimalFormat df = new DecimalFormat("0.00");
for (Map.Entry e : analysis.getAnalysis().entrySet()) {
added = true;
sb.append("{reason:'" + e.getKey() + ": " + df.format(e.getValue()) + "'},");
}
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
for (InterpolatedValue v : analysis.getDataPoints().getMissingData()) {
added = true;
sb.append("{reason: 'missing data " + dateFormat.format(v.getStart()) + " to " + dateFormat.format(v.getEnd()) + "'},");
}
if (added) {
sb.substring(0, sb.length() - 1);
}
sb.append("],");
sb.append("table:" + tableString + "});");
return sb.toString();
}
catch (DataSourceException e) {
return getGvizDataErrorResponse(e);
}
}
else {
return org.wattdepot.common.util.GvizHelper.getGvizResponse(resource, tqxString, tqString);
}
}
/**
* Returns the google visualization query string to create a benchmark column chart.
*
* @param mList The list of values, the first value is the benchmark.
* @param tqxString gviz tqx query string, i.e., request id
* @param tqString gviz tq query string, selectable fields
* @return gviz response
*/
public static String getBenchmarkGvizResponse(InterpolatedValueList mList, String tqxString, String tqString) {
try {
return getGvizResponseFromDataTable(getColumnDataTable(mList), tqxString);
}
catch (DataSourceException e) {
e.printStackTrace();
}
return null;
}
/**
* Returns the DataTable suitable for a Column chart.
*
* @param mList The data.
* @return The DataTable for a column chart.
* @throws DataSourceException if there is a problem.
*/
private static DataTable getColumnDataTable(InterpolatedValueList mList) throws DataSourceException {
DataTable table = new DataTable();
// Sets up the columns requested by any SELECT in the datasource query
ArrayList<InterpolatedValue> values = mList.getInterpolatedValues();
if (!values.isEmpty()) {
String type = values.get(0).getMeasurementType().getUnits();
table.addColumn(new ColumnDescription("Value", ValueType.TEXT, "Interval"));
table.addColumn(new ColumnDescription(type, ValueType.NUMBER, type));
boolean once = true;
SimpleDateFormat format = new SimpleDateFormat("MM/dd/YY");
for (InterpolatedValue value : values) {
TableRow row = new TableRow();
String label = "";
if (once) {
label = "Baseline: ";
once = false;
}
row.addCell(label + format.format(value.getStart()) + " - " + format.format(value.getEnd()));
if (value.getValue() != null) {
row.addCell(value.getValue());
}
table.addRow(row);
}
}
return table;
}
}