123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- using FastReport.Data.JsonConnection.JsonParser;
- using FastReport.Utils;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.ComponentModel;
- namespace FastReport.Data.JsonConnection
- {
- /// <summary>
- /// JsonTableDataSource present a json array object
- /// </summary>
- public class JsonTableDataSource : TableDataSource
- {
- #region Private Fields
- private JsonArray _json;
- private bool updateSchema;
- private bool simpleStructure;
- private string tableData;
- #endregion Private Fields
- #region Public Properties
- /// <summary>
- /// Gets or sets value for force update schema on init schema
- /// </summary>
- [Browsable(false)]
- public bool UpdateSchema
- {
- get
- {
- return updateSchema;
- }
- set
- {
- updateSchema = value;
- }
- }
- /// <summary>
- /// Get or sets simplify mode for array types
- /// </summary>
- [Browsable(false)]
- public bool SimpleStructure
- {
- get
- {
- return simpleStructure;
- }
- set
- {
- simpleStructure = value;
- }
- }
- /// <inheritdoc />
- [Browsable(false)]
- public override string TableData
- {
- get
- {
- if (String.IsNullOrEmpty(tableData))
- {
- tableData = Json.ToString();
- }
- return tableData;
- }
- set
- {
- tableData = value;
- }
- }
- #endregion Public Properties
- #region Internal Properties
- internal JsonArray Json
- {
- get
- {
- if (_json == null)
- {
- if (StoreData && !String.IsNullOrEmpty(tableData))
- {
- _json = JsonBase.FromString(tableData) as JsonArray;
- }
- else
- {
- _json = GetJson(Parent, this) as JsonArray;
- }
- if (_json == null)
- _json = new JsonArray();
- }
- return _json;
- }
- set
- {
- _json = value;
- }
- }
- #endregion Internal Properties
- #region Private Properties
- private int CurrentIndex
- {
- get
- {
- if (currentRow is int)
- return (int)currentRow;
- if (CurrentRowNo < Rows.Count)
- {
- object result = Rows[CurrentRowNo];
- if (result is int)
- return (int)result;
- }
- return CurrentRowNo;
- }
- }
- #endregion Private Properties
- #region Public Constructors
- /// <inheritdoc/>
- public JsonTableDataSource()
- {
- DataType = typeof(JsonArray);
- }
- #endregion Public Constructors
- #region Public Methods
- /// <inheritdoc/>
- public override void InitializeComponent()
- {
- base.InitializeComponent();
- Json = null;
- }
- /// <inheritdoc/>
- public override void InitSchema()
- {
- if (Columns.Count == 0 || UpdateSchema && !StoreData)
- {
- if (Connection is JsonDataSourceConnection)
- {
- JsonDataSourceConnection con = Connection as JsonDataSourceConnection;
- InitSchema(this, con.JsonSchema, con.SimpleStructure);
- }
- }
- UpdateSchema = false;
- }
- /// <inheritdoc/>
- public override void LoadData(ArrayList rows)
- {
- Json = null;
- // JSON is calculated property, no problem with null
- if (rows != null && Json != null)
- {
- rows.Clear();
- int count = Json.Count;
- for (int i = 0; i < count; i++)
- {
- rows.Add(i);
- }
- }
- }
- #endregion Public Methods
- #region Internal Methods
- internal static object GetJsonBaseByColumn(Base parentColumn, Column column)
- {
- if (parentColumn is JsonTableDataSource)
- {
- JsonTableDataSource jsonTableDataSource = parentColumn as JsonTableDataSource;
- if (jsonTableDataSource.SimpleStructure)
- {
- if (!String.IsNullOrEmpty(column.PropName))
- {
- var obj = (parentColumn as JsonTableDataSource).Json[(parentColumn as JsonTableDataSource).CurrentIndex];
- return (obj as JsonBase)[column.PropName];
- }
- }
- else
- {
- switch (column.PropName)
- {
- case "item":
- return (parentColumn as JsonTableDataSource).Json[(parentColumn as JsonTableDataSource).CurrentIndex];
- }
- JsonTableDataSource source = column as JsonTableDataSource;
- return source.Json;
- }
- }
- if (parentColumn is Column && !String.IsNullOrEmpty(column.PropName))
- {
- object json = GetJsonBaseByColumn(parentColumn.Parent, parentColumn as Column);
- if (json is JsonBase)
- {
- return (json as JsonBase)[column.PropName];
- }
- }
- return null;
- }
- internal static object GetValueByColumn(Base parentColumn, Column column)
- {
- if (parentColumn is JsonTableDataSource)
- {
- switch (column.PropName)
- {
- case "index":
- return (parentColumn as JsonTableDataSource).CurrentIndex;
- case "array":
- return (parentColumn as JsonTableDataSource).Json;
- }
- }
- object json = GetJsonBaseByColumn(parentColumn, column);
- return json;
- }
- internal static void InitSchema(Column table, JsonSchema schema, bool simpleStructure)
- {
- List<Column> saveColumns = new List<Column>();
- switch (schema.Type)
- {
- case "object":
- foreach (KeyValuePair<string, JsonSchema> kv in schema.Properties)
- {
- if (kv.Value.Type == "object")
- {
- Column c = new Column();
- c.Name = kv.Key;
- c.Alias = kv.Key;
- c.PropName = kv.Key;
- c.DataType = kv.Value.DataType;
- c = UpdateColumn(table, c, saveColumns);
- InitSchema(c, kv.Value, simpleStructure);
- }
- else if (kv.Value.Type == "array")
- {
- Column c = new JsonTableDataSource();
- c.Name = kv.Key;
- c.Alias = kv.Key;
- c.PropName = kv.Key;
- c.DataType = kv.Value.DataType;
- c = UpdateColumn(table, c, saveColumns);
- InitSchema(c, kv.Value, simpleStructure);
- }
- else
- {
- Column c = new Column();
- c.Name = kv.Key;
- c.Alias = kv.Key;
- c.PropName = kv.Key;
- c.DataType = kv.Value.DataType;
- c.SetBindableControlType(c.DataType);
- UpdateColumn(table, c, saveColumns);
- }
- }
- break;
- case "array":
- JsonSchema items = schema.Items;
- bool simpleArray = false;
- if (table is JsonTableDataSource)
- {
- JsonTableDataSource jsonTableDataSource = table as JsonTableDataSource;
- simpleArray = jsonTableDataSource.SimpleStructure =
- simpleStructure & items.Type == "object";
- }
- if (simpleArray)
- {
- // remake schema in simplify mode
- InitSchema(table, items, simpleStructure);
- // and return, no need to clear column data
- // in this case this method has no control to columns
- return;
- }
- {
- Column c = new Column();
- c.Name = "index";
- c.Alias = "index";
- c.PropName = "index";
- c.DataType = typeof(int);
- UpdateColumn(table, c, saveColumns);
- }
- {
- Column c;
- bool iSchema = false;
- if (items.Type == "object")
- {
- c = new Column();
- iSchema = true;
- }
- else if (items.Type == "array")
- {
- c = new JsonTableDataSource();
- iSchema = true;
- }
- else
- {
- c = new Column();
- }
- c.Name = "item";
- c.Alias = "item";
- c.PropName = "item";
- c.DataType = items.DataType;
- c = UpdateColumn(table, c, saveColumns);
- if (iSchema)
- InitSchema(c, items, simpleStructure);
- }
- {
- Column c = new Column();
- c.Name = "array";
- c.Alias = "array";
- c.PropName = "array";
- c.DataType = typeof(JsonBase);
- UpdateColumn(table, c, saveColumns);
- }
- break;
- }
- for (int i = 0; i < table.Columns.Count; i++)
- {
- if (!(table.Columns[i].Calculated || saveColumns.Contains(table.Columns[i])))
- {
- table.Columns.RemoveAt(i);
- i--;
- }
- }
- }
- internal object GetJson(Base parentColumn, Column column)
- {
- if(parentColumn is IJsonProviderSourceConnection)
- {
- return (parentColumn as IJsonProviderSourceConnection).GetJson(this);
- }
- //if (parentColumn is ESDataSourceConnection)
- // parentColumn = (parentColumn as ESDataSourceConnection).GetParentJTDSByName(column.Name);
- if (parentColumn is JsonTableDataSource)
- {
- //if (parentColumn.Parent is ESDataSourceConnection)
- // parentColumn.Parent = (parentColumn.Parent as ESDataSourceConnection).GetParentJTDSByName(parentColumn.Name);
- // Here it’s completely fail,
- // I commented out the code with ElasticSearch,
- // when you bring ElasticSearch into a separate plugin,
- // then this will need to be corrected
- JsonTableDataSource source = parentColumn as JsonTableDataSource;
- if (source.SimpleStructure)
- {
- object parentJson = source.Json[source.CurrentRowNo];
- if (parentJson is JsonBase && !String.IsNullOrEmpty(column.PropName))
- {
- return (parentJson as JsonBase)[column.PropName];
- }
- }
- else
- {
- return source.Json[source.CurrentRowNo] as object;
- }
- }
- else if (parentColumn is Column)
- {
- object parentJson = GetJson(parentColumn.Parent, parentColumn as Column);
- if (parentJson is JsonBase && !String.IsNullOrEmpty(column.PropName))
- {
- return (parentJson as JsonBase)[column.PropName];
- }
- }
- return null;
- }
- #endregion Internal Methods
- #region Protected Methods
- /// <inheritdoc/>
- protected override object GetValue(Column column)
- {
- return GetValueByColumn(column.Parent, column);
- }
- /// <inheritdoc/>
- protected override object GetValue(string alias)
- {
- // TODO TEST
- Column column = this;
- string[] colAliases = alias.Split('.');
- foreach (string colAlias in colAliases)
- {
- column = column.Columns.FindByAlias(colAlias);
- if (column == null)
- return null;
- }
- return GetValueByColumn(column.Parent, column);
- }
- #endregion Protected Methods
- #region Private Methods
- private static Column UpdateColumn(Column table, Column c, List<Column> list)
- {
- foreach (Column child in table.Columns)
- {
- if (child.PropName == c.PropName)
- {
- child.DataType = c.DataType;
- list.Add(child);
- return child;
- }
- }
- table.AddChild(c);
- list.Add(c);
- return c;
- }
- #endregion Private Methods
- /// <inheritdoc/>
- public override void Serialize(FRWriter writer)
- {
- base.Serialize(writer);
- if (SimpleStructure)
- {
- writer.WriteBool("SimpleStructure", SimpleStructure);
- }
- }
- }
- }
|