AggregateExpressionPair.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. using System;
  2. using System.Collections.Generic;
  3. namespace FastReport.AdvMatrix
  4. {
  5. internal class AggregateExpressionPairList : List<AggregateExpressionPair>
  6. {
  7. private AdvMatrixObject matrix;
  8. public AggregateExpressionPair Find(string aggregateName, string expression)
  9. {
  10. foreach (AggregateExpressionPair item in this)
  11. {
  12. if (item.AggregateName == aggregateName && item.Expression == expression)
  13. return item;
  14. }
  15. return null;
  16. }
  17. public AggregateExpressionPair Add(string aggregateName, string expression)
  18. {
  19. AggregateExpressionPair result = new AggregateExpressionPair(matrix, aggregateName, expression);
  20. Add(result);
  21. return result;
  22. }
  23. public AggregateExpressionPair AddUnique(string aggregateName, string expression)
  24. {
  25. AggregateExpressionPair result = Find(aggregateName, expression);
  26. if (result != null)
  27. return result;
  28. return Add(aggregateName, expression);
  29. }
  30. public AggregateExpressionPair AddUnique(AggregateExpressionPair ag)
  31. {
  32. AggregateExpressionPair result = Find(ag.AggregateName, ag.Expression);
  33. if (result != null)
  34. return result;
  35. Add(ag);
  36. return ag;
  37. }
  38. public AggregateExpressionPairList(AdvMatrixObject matrix)
  39. {
  40. this.matrix = matrix;
  41. }
  42. }
  43. internal class AggregateExpressionPair
  44. {
  45. private AdvMatrixObject matrix;
  46. private CellDataStorage storage;
  47. public string AggregateName { get; private set; }
  48. public string Expression { get; private set; }
  49. private string ToStringLiteral(string text)
  50. {
  51. return "\"" + text.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"";
  52. }
  53. public string ToAggregateCall()
  54. {
  55. return matrix.Name + ".Data.Context.GetAggregate(" + ToStringLiteral(AggregateName) + ", " + ToStringLiteral(Expression) + ")";
  56. }
  57. public override string ToString()
  58. {
  59. return AggregateName + "(" + Expression + ")";
  60. }
  61. public void ProcessDataRow(int columnIndex, int rowIndex, object value)
  62. {
  63. storage.AddValue(columnIndex, rowIndex, value);
  64. }
  65. public object GetValue(int columnIndex, int rowIndex)
  66. {
  67. object value = storage.GetValue(columnIndex, rowIndex);
  68. if (value != null && storage.AggregateType == typeof(UserAggregate))
  69. value = matrix.Report.InvokeMethod(AggregateName, new object[] { value });
  70. return value;
  71. }
  72. public void Merge(int sourceColumnIndex, int sourceRowIndex, int targetColumnIndex, int targetRowIndex)
  73. {
  74. storage.Merge(sourceColumnIndex, sourceRowIndex, targetColumnIndex, targetRowIndex);
  75. }
  76. public void ClearData()
  77. {
  78. storage.Clear();
  79. }
  80. public AggregateExpressionPair(AdvMatrixObject matrix, string aggregateName, string expression)
  81. {
  82. this.matrix = matrix;
  83. AggregateName = aggregateName;
  84. Expression = expression;
  85. Type aggregateType = Aggregates.Find(aggregateName);
  86. if (aggregateType == null)
  87. aggregateType = typeof(UserAggregate);
  88. storage = new CellDataStorage(aggregateType);
  89. }
  90. private class CellDataStorage
  91. {
  92. // array of array: the simplest and most efficient way to store dense matrix data
  93. private List<List<AggregateBase>> rows;
  94. internal Type AggregateType { get; private set; }
  95. private AggregateBase GetCell(int columnIndex, int rowIndex, bool create)
  96. {
  97. if (rowIndex >= rows.Count)
  98. {
  99. if (!create)
  100. return null;
  101. // append rows if row index is out of bounds
  102. int delta = rowIndex - rows.Count + 1;
  103. for (int i = 0; i < delta; i++)
  104. {
  105. rows.Add(new List<AggregateBase>());
  106. }
  107. }
  108. List<AggregateBase> row = rows[rowIndex];
  109. if (columnIndex >= row.Count)
  110. {
  111. if (!create)
  112. return null;
  113. // append columns if column index is out of bounds
  114. int delta = columnIndex - row.Count + 1;
  115. for (int i = 0; i < delta; i++)
  116. {
  117. row.Add(null);
  118. }
  119. }
  120. AggregateBase aggregate = row[columnIndex];
  121. if (aggregate == null)
  122. {
  123. if (!create)
  124. return null;
  125. // initial state - the cell is empty. Create aggregate instance
  126. aggregate = Activator.CreateInstance(AggregateType) as AggregateBase;
  127. row[columnIndex] = aggregate;
  128. }
  129. return aggregate;
  130. }
  131. public void Clear()
  132. {
  133. rows.Clear();
  134. }
  135. public void AddValue(int columnIndex, int rowIndex, object value)
  136. {
  137. // do not put null values to the matrix!
  138. if (value == null || value == DBNull.Value)
  139. return;
  140. AggregateBase aggregate = GetCell(columnIndex, rowIndex, true);
  141. aggregate.AddValue(value);
  142. }
  143. public object GetValue(int columnIndex, int rowIndex)
  144. {
  145. AggregateBase aggregate = GetCell(columnIndex, rowIndex, false);
  146. if (aggregate == null)
  147. return null;
  148. return aggregate.GetValue();
  149. }
  150. public void Merge(int sourceColumnIndex, int sourceRowIndex, int targetColumnIndex, int targetRowIndex)
  151. {
  152. AggregateBase sourceAggr = GetCell(sourceColumnIndex, sourceRowIndex, false);
  153. AggregateBase targetAggr = GetCell(targetColumnIndex, targetRowIndex, true);
  154. targetAggr.Merge(sourceAggr);
  155. }
  156. public CellDataStorage(Type aggregateType)
  157. {
  158. AggregateType = aggregateType;
  159. rows = new List<List<AggregateBase>>();
  160. }
  161. }
  162. }
  163. }