18using System.Collections;
19using System.Collections.Generic;
22using System.Threading.Tasks;
54 internal class GPALGrid<T> : IGPALGrid<T>
56 private List<List<T>> data;
59 private readonly
object rowLock =
new object();
66 internal bool UseDedupe {
get;
private set; } =
false;
73 public IGPALGrid<T> WithDedupeData(
bool useDedupe =
true)
75 UseDedupe = useDedupe;
84 data =
new List<List<T>>();
109 public IAllowGridActions<T> AddRow(List<T> row)
113 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Row is null in AddRow(List<T>). Skipping addition.",
this, GPALObjectType.Other);
135 internal void Add(List<T> row)
139 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Row is null in AddRow(List<T>). Skipping addition.",
this, GPALObjectType.Other);
145 public IAllowGridActions<T> Add(IGPALGrid<T> grid)
147 foreach (List<T> row
in grid)
180 public IAllowGridActions<T> AddRow(
object anonymousObject)
182 if (anonymousObject ==
null)
184 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Anonymous object is null in AddRow(object). Skipping addition.",
this, GPALObjectType.Other);
189 var values = anonymousObject.GetType()
191 .Select(prop => prop.GetValue(anonymousObject,
null))
197 int expectedColumns = Columns;
198 if (data.Count > 0 && values.Count != expectedColumns)
199 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Anonymous object has [{values.Count}] values, but expected [{expectedColumns}]. Adding row as-is.",
this, GPALObjectType.Other);
203 var row =
new List<T>();
204 foreach (var value
in values)
213 row.Add((T)Convert.ChangeType(value, typeof(T)));
217 GPAL.PublishSimpleEvent(GPALEventType.ERROR, $
"Cannot convert value [{value}] to type [{typeof(T).Name}]. Using default value",
this, GPALObjectType.Other, ex);
255 public IAllowGridActions<T> AddRow(params T[] values)
259 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Values array is null in AddRow(params T[]). Skipping addition.",
this, GPALObjectType.Other);
266 int expectedColumns = Columns;
267 if (data.Count > 0 && values.Length != expectedColumns)
268 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Params array has [{values.Length}] values, but expected [{expectedColumns}]. Adding row as-is.",
this, GPALObjectType.Other);
270 data.Add(
new List<T>(values));
298 public IAllowGridActions<T> DeleteRow(
int rowIdx)
300 if (rowIdx >= 0 && rowIdx < data.Count)
302 data.RemoveAt(rowIdx);
306 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Invalid row index [{rowIdx}] in DeleteRow(int). Row count is [{data.Count}]. Skipping deletion.",
this, GPALObjectType.Other);
334 public IAllowGridActions<T> DeleteRow(RowPosition rowPosition = RowPosition.Last)
340 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Grid is empty in DeleteRow(RowPosition). Skipping deletion.",
this, GPALObjectType.Other);
344 if (rowPosition == RowPosition.First)
350 rowIdx = data.Count - 1;
353 data.RemoveAt(rowIdx);
383 public IAllowGridActions<T> AddColumn(List<T> column)
387 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Column is null in AddColumn. Skipping addition.",
this, GPALObjectType.Other);
391 for (
int i = 0; i < column.Count; i++)
395 data.Add(
new List<T>());
397 data[i].Add(column[i]);
405 public int Rows => data.Count;
417 foreach (var row
in data)
418 count = Math.Max(count, row.Count);
448 public IAllowGridActions<T> AddCell(T value,
int row,
int column)
450 if (row >= 0 && row < Rows && column >= 0 && column < Columns)
452 data[row][column] = value;
456 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Invalid cell coordinates ([{row}], [{column}]) in AddCell. Grid size is [{Rows}]x[{Columns}]. Skipping operation.",
this, GPALObjectType.Other);
478 public T GetCell(
int row,
int column)
480 if (row >= 0 && row < Rows && column >= 0 && column < Columns)
482 return data[row][column];
485 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Invalid cell coordinates ([{row}], [{column}]) in GetCell. Grid size is [{Rows}]x[{Columns}]. Returning default value.",
this, GPALObjectType.Other);
503 public IAllowGridActions<T> Clear()
505 data =
new List<List<T>>();
530 public List<T>
this[
int index]
534 List<T> retVal = index < data.Count && 0 <= index ? data[index] :
new List<T>();
538 if (index >= data.Count || 0 > index)
539 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
540 $
"Row [{index}] was asked for and the grid holds [{data.Count}], so an empty row was answered with",
541 this, GPALObjectType.Other);
547 if (index >= data.Count)
549 for (
int idx = index; idx >= data.Count; idx--)
550 data.Add(
new List<T>());
555 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"Value is null in indexer set at index [{index}]. Setting to empty list.",
this, GPALObjectType.Other);
556 data[index] =
new List<T>();
585 public T
this[
int row,
int column]
587 get {
return GetCell(row, column); }
588 set { AddCell(value, row, column); }
595 public IGPALGrid<T> ToGPALObject()
616 public bool Contains(T value)
620 GPAL.PublishSimpleEvent(GPALEventType.WARNING,
"Value is null in Contains. Returning false.",
this, GPALObjectType.Other);
624 string valueString = value.ToString();
625 foreach (List<T> list
in data)
626 foreach (T item
in list)
627 if (item !=
null && item.ToString().Contains(valueString))
637 public int Count() => data.Count();
643 public IEnumerator<List<T>> GetEnumerator()
645 return data.GetEnumerator();
652 IEnumerator IEnumerable.GetEnumerator()
654 return GetEnumerator();
676 public object Clone()
678 GPALGrid<T> clone =
new GPALGrid<T>();
680 foreach (List<T> row
in data)
682 List<T> clonedRow =
new List<T>();
683 foreach (T item
in row)
685 if (item is ICloneable cloneable)
687 clonedRow.Add((T)cloneable.Clone());
694 clone.AddRow(clonedRow);
706 public IAllowGridActions<T> InputFrom(GPALFile input)
708 FileHelper.TokenizeFile(input);
712 IGPALGrid<string> tokens = ((IGPALFileInternal)input).TokenList[0];
714 data =
new List<List<T>>();
716 foreach (List<string> row
in tokens)
718 List<T> newRow =
new List<T>();
720 foreach (
string cell
in row)
721 newRow.Add(
null == cell ?
default(T) : (T)Convert.ChangeType(cell, typeof(T)));
734 public IAllowGridActions<T> SaveTo(GPALFile output)
736 GPAL.Converter.WithInput(
this).SaveTo(output);
747 public IAllowGridActions<T> InputFrom(IGPALDatabase input)
749 input.SaveTo(out IGPALGrid<string> readGrid);
751 data =
new List<List<T>>();
753 if (
null != readGrid)
754 foreach (List<string> row
in readGrid)
756 List<T> newRow =
new List<T>();
758 foreach (
string cell
in row)
759 newRow.Add(
null == cell ?
default(T) : (T)Convert.ChangeType(cell, typeof(T)));
764 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Read [{data.Count}] rows from the database into the grid.", input, GPALObjectType.Database);
777 public IAllowGridActions<T> SaveTo(IGPALDatabase output)
779 IGPALGrid<string> writeGrid = GPAL.GridForType<
string>();
781 foreach (List<T> row
in data)
783 List<string> newRow =
new List<string>();
785 foreach (T cell
in row)
786 newRow.Add(
null == (
object)cell ?
null : cell.ToString());
788 writeGrid.AddRow(newRow);
791 output.Using(writeGrid).Execute(out
int rowsWritten);
793 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"Wrote [{rowsWritten}] rows from the grid to the database.", output, GPALObjectType.Database);
802 public List<T> ToList()
804 List<T> retVal =
new List<T>();
806 foreach (List<T> row
in data)
807 foreach (T col
in row)