/// <summary> /// Creates a builder of the desired type /// </summary> /// <param name="db">Database id</param> /// <param name="path">Path to PX-file or datatable</param> /// <returns>The created Paxiom model builder</returns> protected static internal PCAxis.Paxiom.IPXModelBuilder CreatePaxiomBuilder(string db, string path) { PCAxis.Paxiom.IPXModelBuilder builder = null; DatabaseInfo dbi = PXWeb.Settings.Current.General.Databases.GetDatabase(db); if (dbi.Type == PCAxis.Web.Core.Enums.DatabaseType.PX) { string fullPath = System.IO.Path.Combine( System.Web.HttpContext.Current.Server.MapPath(Settings.Current.General.Paths.PxDatabasesPath), path); builder = new PCAxis.Paxiom.PXFileBuilder(); builder.SetPath(fullPath); } else { //it seems the incomming path here already is db:tableid . (In the paralell method in SSDHandler.cs it is not) builder = new PCAxis.PlugIn.Sql.PXSQLBuilder(); if (path.Contains(":")) { builder.SetPath(path); } else { builder.SetPath(db + ":" + path); } } return(builder); }
/// <summary> /// Builds a list of Selection-objects for each selection in the JSON request /// </summary> /// <param name="builder">The bulder of the table</param> /// <param name="tableQuery">The table query from the client</param> /// <returns>A list of selection objects</returns> public static List <PCAxis.Paxiom.Selection> BuildSelections(PCAxis.Paxiom.IPXModelBuilder builder, TableQuery tableQuery) { //Check to see that the variable exists int c = builder.Model.Meta.Variables.Where(var => tableQuery.Query.Select(q => q.Code).Contains(var.Code)).ToArray().Length; if (tableQuery.Query.Length > c) { throw new ArgumentException("Variable is not defined"); } var selections = new List <PCAxis.Paxiom.Selection>(); foreach (var variable in builder.Model.Meta.Variables) { PCAxis.Paxiom.Selection selection = new PCAxis.Paxiom.Selection(variable.Code); var query = tableQuery.Query.SingleOrDefault(q => q.Code == variable.Code); if (query != null) { // Process filters if (query.Selection.Filter.ToLower() == "all") // All { selection = QueryHelper.SelectAll(variable, query); } else if (query.Selection.Filter.ToLower() == "top") // Top { selection = QueryHelper.SelectTop(variable, query); } else if (PCAxis.Query.QueryHelper.IsAggregation(query.Selection.Filter)) { selection = QueryHelper.SelectAggregation(variable, query, builder); } else if (query.Selection.Filter.StartsWith("vs:", StringComparison.InvariantCultureIgnoreCase)) { selection = QueryHelper.SelectValueSet(variable, query, builder); } else { // Assume item selection = QueryHelper.SelectItem(variable, query); } } else { // Variable not specified in query if (!variable.Elimination) { selection = PCAxis.Paxiom.Selection.SelectAll(variable); } } selections.Add(selection); } return(selections); }
public static bool ValidateSelection(PCAxis.Paxiom.IPXModelBuilder builder, List <PCAxis.Paxiom.Selection> selections) { //Check that all mandatory variables has at least one value selected var mandatoryVariables = builder.Model.Meta.Variables.Where(v => !v.Elimination); foreach (var v in mandatoryVariables) { var selection = selections.FirstOrDefault(s => s.VariableCode == v.Code); if (selection == null) { return(false); } if (selection.ValueCodes.Count == 0) { return(false); } } return(true); }
/// <summary> /// Returns metadata for the specified table /// </summary> /// <param name="tableName">The table id</param> /// <returns>Metadata for the table</returns> private MetaTable GetTableMeta(HttpContext context, string language, string db, string[] tablePath) { PCAxis.Paxiom.IPXModelBuilder builder = GetPXBuilder(language, db, tablePath); builder.DoNotApplyCurrentValueSet = true; // DoNotApplyCurrentValueSet means the "client that made the request" is an api(, not a GUI) so that // CNMM2.4 property DefaultInGUI (for Valueset/grouping) should not be used builder.SetPreferredLanguage(language); builder.BuildForSelection(); return(new MetaTable { Title = builder.Model.Meta.Title, Variables = builder.Model.Meta.Variables.Select(variable => new MetaVariable { Code = variable.Code, Text = variable.Name, Elimination = variable.Elimination, Time = variable.IsTime, Values = variable.Values.Count > Settings.Current.MaxValues ? null : variable.Values.Select(value => value.Code).ToArray(), ValueTexts = variable.Values.Count > Settings.Current.MaxValues ? null : variable.Values.Select(value => value.Value).ToArray() }).ToArray() }); }
/// <summary> /// Serializes and sends table data back to the client /// </summary> /// <param name="context"></param> private void SendTableData(HttpContext context, string language, string db, string[] tablePath, ResponseBucket cacheResponse) { //// TODO: Limit data size? //string data = ""; //using (var stream = new StreamReader(context.Request.InputStream)) //{ // data = stream.ReadToEnd(); //} var tableQuery = JsonHelper.Deserialize <TableQuery>(cacheResponse.PostData) as TableQuery; if (tableQuery.Response == null || tableQuery.Response.Format == null) { tableQuery.Response = new QueryResponse() { Format = _defaultResponseFormat }; } // Initialize the builder PCAxis.Paxiom.IPXModelBuilder builder = GetPXBuilder(language, db, tablePath); builder.DoNotApplyCurrentValueSet = true; // DoNotApplyCurrentValueSet means the "client that made the request" is an api(, not a GUI) so that // CNMM2.4 property DefaultInGUI (for Valueset/grouping) should not be used builder.SetPreferredLanguage(language); builder.BuildForSelection(); // Process selections List <PCAxis.Paxiom.Selection> selections; try { selections = PCAxisRepository.BuildSelections(builder, tableQuery); } catch (Exception ex) { var message = ex is HttpException ? ex.Message : "Parameter error"; cacheResponse.ResponseData = context.Response.ContentEncoding.GetBytes(Error(message, false)); context.SendJSONError(cacheResponse, 400, true); // Logs usage _usageLogger.Info(String.Format("url={0}, type=error, caller={1}, cached=false, message=Parameter error", context.Request.RawUrl, context.Request.UserHostAddress)); return; } // Check that the number of selected cells do not exceed the limit long cellCount = 1; foreach (var sel in selections) { if (sel.ValueCodes.Count > 0) { cellCount *= sel.ValueCodes.Count; } } if (cellCount > Settings.Current.FetchCellLimit) { Write403Response(context); return; } builder.BuildForPresentation(selections.ToArray()); // Output handling starts here context.Response.Clear(); IWebSerializer serializer = WebSerializerSwitch.GetSerializer(tableQuery.Response.Format); //serializer.Serialize(builder.Model, context.Response); serializer.Serialize(builder.Model, cacheResponse); //context.Response.AddHeader("Content-Type", cacheResponse.ContentType); //context.Response.OutputStream.Write(cacheResponse.ResponseData, 0, cacheResponse.ResponseData.Length); context.Send(cacheResponse, true); //Logs usage _usageLogger.Info(String.Format("url={0}, type=data, caller={3}, cached=false, format={1}, matrix-size={2}", context.Request.RawUrl, tableQuery.Response.Format, builder.Model.Data.MatrixSize, context.Request.UserHostAddress)); }
/// <summary> /// Serializes and sends table data back to the client /// </summary> /// <param name="context"></param> private void SendTableData(HttpContext context, string language, string db, string[] tablePath, ResponseBucket cacheResponse) { //// TODO: Limit data size? //string data = ""; //using (var stream = new StreamReader(context.Request.InputStream)) //{ // data = stream.ReadToEnd(); //} var tableQuery = JsonHelper.Deserialize <TableQuery>(cacheResponse.PostData) as TableQuery; if (tableQuery.Response == null || tableQuery.Response.Format == null) { tableQuery.Response = new QueryResponse() { Format = _defaultResponseFormat }; } // Initialize the builder PCAxis.Paxiom.IPXModelBuilder builder = GetPXBuilder(language, db, tablePath); builder.DoNotApplyCurrentValueSet = true; // DoNotApplyCurrentValueSet means the "client that made the request" is an api(, not a GUI) so that // CNMM2.4 property DefaultInGUI (for Valueset/grouping) should not be used builder.SetPreferredLanguage(language); builder.BuildForSelection(); // Process selections var selections = PCAxisRepository.BuildSelections(builder, tableQuery); // Check that the number of selected cells do not exceed the limit long cellCount = 1; foreach (var sel in selections) { if (sel.ValueCodes.Count > 0) { cellCount *= sel.ValueCodes.Count; } } if (cellCount > Settings.Current.FetchCellLimit) { Write403Response(context); return; } builder.BuildForPresentation(selections.ToArray()); // Output handling starts here context.Response.Clear(); IWebSerializer serializer; switch (tableQuery.Response.Format != null ? tableQuery.Response.Format.ToLower() : null) { case null: case "px": serializer = new PxSerializer(); break; case "csv": serializer = new CsvSerializer(); break; case "json": serializer = new JsonSerializer(); break; case "json-stat": serializer = new JsonStatSeriaizer(); break; case "json-stat2": serializer = new JsonStat2Seriaizer(); break; case "xlsx": serializer = new XlsxSerializer(); break; //case "png": // int? width = tableQuery.Response.GetParamInt("width"); // int? height = tableQuery.Response.GetParamInt("height"); // string encoding = tableQuery.Response.GetParamString("encoding"); // serializer = new ChartSerializer(width, height, encoding); // break; case "sdmx": serializer = new SdmxDataSerializer(); break; default: throw new NotImplementedException("Serialization for " + tableQuery.Response.Format + " is not implemented"); } //serializer.Serialize(builder.Model, context.Response); serializer.Serialize(builder.Model, cacheResponse); //context.Response.AddHeader("Content-Type", cacheResponse.ContentType); //context.Response.OutputStream.Write(cacheResponse.ResponseData, 0, cacheResponse.ResponseData.Length); context.Send(cacheResponse, true); //Logs usage _usageLogger.Info(String.Format("url={0}, type=data, caller={3}, cached=false, format={1}, matrix-size={2}", context.Request.RawUrl, tableQuery.Response.Format, builder.Model.Data.MatrixSize, context.Request.UserHostAddress)); }