PageRenderTime 84ms CodeModel.GetById 31ms RepoModel.GetById 1ms app.codeStats 0ms

/Ascend.Web/Areas/Dash/Controllers/GoogleVisualization.cs

https://github.com/nicknystrom/ascend
C# | 355 lines | 313 code | 40 blank | 2 comment | 15 complexity | 7c90bb01831a6bea463792a9f03d1b88 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Web.Mvc;
  6. using Newtonsoft.Json;
  7. using Newtonsoft.Json.Converters;
  8. using RedBranch.Hammock;
  9. namespace Ascend.Web.Areas.Dash.Controllers
  10. {
  11. public class GoogleVisualizationTable
  12. {
  13. public GoogleVisualizationTable AddColumn<T>(string id, string label, string format)
  14. {
  15. if (null == Columns)
  16. {
  17. Columns = new List<GoogleVisualizationColumn>();
  18. }
  19. Columns.Add(new GoogleVisualizationColumn {
  20. Id = id,
  21. Label = label,
  22. Pattern = format,
  23. Type = GoogleVisualizationDataType.FromSystemType(typeof(T)),
  24. });
  25. return this;
  26. }
  27. public GoogleVisualizationTable AddRow(params object[] values)
  28. {
  29. return AddRow((IEnumerable<object>)values);
  30. }
  31. public GoogleVisualizationTable AddRow(IEnumerable<object> values)
  32. {
  33. if (null == Columns)
  34. {
  35. throw new InvalidOperationException("You must add columns to this Table before adding Rows.");
  36. }
  37. if (null == Rows)
  38. {
  39. Rows = new List<GoogleVisualizationRow>();
  40. }
  41. var r = new GoogleVisualizationRow();
  42. r.Cells = new List<GoogleVisualizationCell>();
  43. var i = 0;
  44. foreach (var v in values)
  45. {
  46. if (i >= Columns.Count)
  47. {
  48. throw new IndexOutOfRangeException("There are more Cells in this Row than Columns in the Table.");
  49. }
  50. var c= new GoogleVisualizationCell { Value = v, };
  51. if (!String.IsNullOrEmpty(Columns[i].Pattern))
  52. {
  53. c.Format = String.Format(Columns[i].Pattern, c.Value);
  54. }
  55. r.Cells.Add(c);
  56. i++;
  57. }
  58. Rows.Add(r);
  59. return this;
  60. }
  61. [JsonProperty("cols")] public IList<GoogleVisualizationColumn> Columns { get; set; }
  62. [JsonProperty("rows")] public IList<GoogleVisualizationRow> Rows { get; set; }
  63. [JsonProperty("p")] public IDictionary<string, string> Attributes { get; set; }
  64. }
  65. public class GoogleVisualizationColumn
  66. {
  67. [JsonProperty("id")] public string Id { get; set; }
  68. [JsonProperty("type")] public string Type { get; set; }
  69. [JsonProperty("label")] public string Label { get; set; }
  70. [JsonProperty("pattern")] public string Pattern { get; set; }
  71. [JsonProperty("p")] public IDictionary<string, string> Attributes { get; set; }
  72. }
  73. public static class GoogleVisualizationDataType
  74. {
  75. public static string FromSystemType(Type t)
  76. {
  77. switch (Type.GetTypeCode(t))
  78. {
  79. case TypeCode.Boolean: return Boolean;
  80. case TypeCode.String: return String;
  81. case TypeCode.DateTime: return DateTime;
  82. case TypeCode.Int16:
  83. case TypeCode.Int32:
  84. case TypeCode.Int64:
  85. case TypeCode.UInt16:
  86. case TypeCode.UInt32:
  87. case TypeCode.UInt64:
  88. case TypeCode.Single:
  89. case TypeCode.Double:
  90. case TypeCode.Decimal:
  91. case TypeCode.Byte:
  92. case TypeCode.SByte:
  93. return Number;
  94. default:
  95. throw new NotSupportedException("Data type '" + t.Name + "' is not supported by the Google Visualization API.");
  96. }
  97. }
  98. public const string Boolean = "boolean";
  99. public const string Number = "number";
  100. public const string String = "string";
  101. public const string Date = "date";
  102. public const string DateTime = "datetime";
  103. public const string Time = "timeofday";
  104. }
  105. public class GoogleVisualizationRow
  106. {
  107. [JsonProperty("c")] public IList<GoogleVisualizationCell> Cells { get; set; }
  108. [JsonProperty("p")] public IDictionary<string, string> Attributes { get; set; }
  109. }
  110. public struct GoogleVisualizationCell
  111. {
  112. [JsonProperty("v")] public object Value { get; set; }
  113. [JsonProperty("f")] public string Format { get; set; }
  114. [JsonProperty("p")] public IDictionary<string, string> Attributes { get; set; }
  115. }
  116. public class GoogleVisualizationResponse
  117. {
  118. public GoogleVisualizationResponse()
  119. {
  120. }
  121. public GoogleVisualizationResponse(GoogleVisualizationRequest request)
  122. {
  123. Version = request.Version;
  124. RequestId = request.RequestId;
  125. Status = GoogleVisualizationResponseStatus.Ok;
  126. }
  127. public void Error(string reason, string message, string detail)
  128. {
  129. Status = GoogleVisualizationResponseStatus.Error;
  130. Errors = new [] {
  131. new GoogleVisualizationResponseWarning {
  132. Reason = reason,
  133. Message = message,
  134. Details = detail,
  135. },
  136. };
  137. }
  138. public void Warning(string reason, string message, string detail)
  139. {
  140. Status = GoogleVisualizationResponseStatus.Warning;
  141. Warnings = new [] {
  142. new GoogleVisualizationResponseWarning {
  143. Reason = reason,
  144. Message = message,
  145. Details = detail,
  146. },
  147. };
  148. }
  149. [JsonProperty("version")] public string Version { get; set; }
  150. [JsonProperty("reqId")] public int RequestId { get; set; }
  151. [JsonProperty("status")] public string Status { get; set; }
  152. [JsonProperty("warnings")] public GoogleVisualizationResponseWarning[] Warnings { get; set; }
  153. [JsonProperty("errors")] public GoogleVisualizationResponseWarning[] Errors { get; set; }
  154. [JsonProperty("sig")] public string Hash { get; set; }
  155. [JsonProperty("table")] public GoogleVisualizationTable Table { get; set; }
  156. }
  157. public class GoogleVisualizationResponseWarning
  158. {
  159. [JsonProperty("reason")] public string Reason { get; set; }
  160. [JsonProperty("message")] public string Message { get; set; }
  161. [JsonProperty("detailed_message")] public string Details { get; set; }
  162. }
  163. public static class GoogleVisualizationResponeWarningReasons
  164. {
  165. public const string DataTruncated = "data_truncated";
  166. public const string Other = "other";
  167. }
  168. public static class GoogleVisualizationResponeErrorReasons
  169. {
  170. public const string NotModified = "not_modified";
  171. public const string NotAuthenticated = "user_not_authenticated";
  172. public const string UnknownDataSourceId = "unknown_data_source_id";
  173. public const string AccessDenied = "access_denied";
  174. public const string UnsupportedQueryOperation = "unsupported_query_operation";
  175. public const string InvalidQuery = "invalid_query";
  176. public const string InvalidRequest = "invalid_request";
  177. public const string InternalError = "internal_error";
  178. public const string NotSupported = "not_supported";
  179. public const string IllegalFormattingPatterns = "illegal_formatting_patterns";
  180. public const string Other = "other";
  181. }
  182. public static class GoogleVisualizationResponseStatus
  183. {
  184. public const string Ok = "ok";
  185. public const string Warning = "warning";
  186. public const string Error = "error";
  187. }
  188. public enum GoogleVisualizationResponseFormat
  189. {
  190. JSON,
  191. Html,
  192. Csv,
  193. Tsv,
  194. }
  195. public class GoogleVisualizationRequest
  196. {
  197. public string Query { get; set; }
  198. public int RequestId { get; set; }
  199. public string Version { get; set; }
  200. public string Signature { get; set; }
  201. public GoogleVisualizationResponseFormat OutputFormat { get; set; }
  202. public string ResponseHandler { get; set; }
  203. public string OutputFilename { get; set; }
  204. public IDictionary<string, string> Parameters { get; set; }
  205. public static GoogleVisualizationRequest FromRequest(HttpRequestBase request)
  206. {
  207. var r = new GoogleVisualizationRequest();
  208. r.Query = request.QueryString["tq"];
  209. var tqx = request.QueryString["tqx"];
  210. if (!String.IsNullOrEmpty(tqx))
  211. {
  212. tqx.Split(';').Each(x => {
  213. var k = x.Substring(0, x.IndexOf(':'));
  214. var v = x.Substring(k.Length+1);
  215. switch (k)
  216. {
  217. case "reqId": r.RequestId = int.Parse(v); break;
  218. case "version": r.Version = v; break;
  219. case "sig": r.Signature = v; break;
  220. case "out":
  221. switch (v)
  222. {
  223. case "json": r.OutputFormat = GoogleVisualizationResponseFormat.JSON; break;
  224. case "html": r.OutputFormat = GoogleVisualizationResponseFormat.Html; break;
  225. case "csv": r.OutputFormat = GoogleVisualizationResponseFormat.Csv; break;
  226. case "tsv-excel": r.OutputFormat = GoogleVisualizationResponseFormat.Tsv; break;
  227. }
  228. break;
  229. case "responseHandler": r.ResponseHandler = v; break;
  230. case "outFileName": r.OutputFilename = v; break;
  231. default:
  232. (r.Parameters ?? (r.Parameters = new Dictionary<string, string>()))
  233. .Add(k, v);
  234. break;
  235. }
  236. });
  237. }
  238. return r;
  239. }
  240. }
  241. public class GoogleVisualizationResult : ActionResult
  242. {
  243. public GoogleVisualizationResult()
  244. {
  245. }
  246. public GoogleVisualizationResult(HttpRequestBase request)
  247. {
  248. Request = GoogleVisualizationRequest.FromRequest(request);
  249. Response = new GoogleVisualizationResponse(Request);
  250. }
  251. public GoogleVisualizationRequest Request { get; set; }
  252. public GoogleVisualizationResponse Response { get; set; }
  253. public void ExecuteResultJson(ControllerContext context)
  254. {
  255. var r = context.HttpContext.Response;
  256. r.ContentType = "application/json";
  257. // if the request was made with X-DataSource-Auth, use a raw json object,
  258. // otherwise use a jsonp style response
  259. var serializer = new JsonSerializer();
  260. serializer.NullValueHandling = NullValueHandling.Ignore;
  261. serializer.Converters.Add(new JavaScriptDateTimeConverter());
  262. if (null != context.HttpContext.Request.Headers["X-DataSource-Auth"])
  263. {
  264. serializer.Serialize(r.Output, Response);
  265. }
  266. else
  267. {
  268. r.Write(String.IsNullOrEmpty(Request.ResponseHandler)
  269. ? "google.visualization.Query.setResponse"
  270. : Request.ResponseHandler);
  271. r.Write("(");
  272. serializer.Serialize(r.Output, Response);
  273. r.Write(")");
  274. }
  275. }
  276. public void ExecuteResultHtml(ControllerContext context)
  277. {
  278. throw new NotSupportedException("Html output is not yet supported.");
  279. }
  280. public void ExecuteResultCsv(ControllerContext context)
  281. {
  282. var r = context.HttpContext.Response;
  283. r.AddHeader("Content-Disposition", String.Format("attachment; filename={0}_{1:yyyy-MM-dd}.csv", context.RouteData.GetRequiredString("Action"), DateTime.Now));
  284. r.ContentType = "text/csv";
  285. r.Write(String.Join(",", Response.Table.Columns.Select(x => x.Label)));
  286. foreach (var row in Response.Table.Rows)
  287. {
  288. r.Write('\n');
  289. r.Write(String.Join(",", row.Cells.Select(x => Convert.ToString(x.Value))));
  290. }
  291. }
  292. public void ExecuteResultTsv(ControllerContext context)
  293. {
  294. throw new NotSupportedException("Tsv output is not yet supported.");
  295. }
  296. public override void ExecuteResult(ControllerContext context)
  297. {
  298. switch (Request.OutputFormat)
  299. {
  300. case GoogleVisualizationResponseFormat.JSON:
  301. ExecuteResultJson(context);
  302. break;
  303. case GoogleVisualizationResponseFormat.Html:
  304. ExecuteResultHtml(context);
  305. break;
  306. case GoogleVisualizationResponseFormat.Csv:
  307. ExecuteResultCsv(context);
  308. break;
  309. case GoogleVisualizationResponseFormat.Tsv:
  310. ExecuteResultTsv(context);
  311. break;
  312. }
  313. }
  314. }
  315. }