Files
spark/src/DataStreamSuite/DataStreamCore/BlueData/BlueTableImmutable.cs
T

99 lines
3.2 KiB
C#

#nullable enable
namespace Bts.DataStreamCore;
using BCG;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
// I would have named this ImmutableBlueTable, but that was already taken.
public class BlueTableImmutable : IBlueRowCollection, IImmutableRowCollection {
readonly ImmutableDictionary<int, IBlueRow> rows;
public BlueTableImmutable(IBlueTableSchema schema)
: this(schema, ImmutableDictionary<int, IBlueRow>.Empty) { }
public BlueTableImmutable(IBlueTableSchema schema, ImmutableDictionary<int, IBlueRow> rows) {
this.schema = schema;
this.rows = rows;
}
public int Count => rows.Count;
public bool IsSynchronized => false;
public IBlueTableSchema schema { get; }
public object SyncRoot => this;
public IBlueRow this[int id] => rows[id];
public bool containsID(int id) =>
rows.ContainsKey(id);
public void CopyTo(Array array, int index) {
foreach (var r in rows.Values) {
array.SetValue(r, index++);
}
}
public IEnumerator GetEnumerator() =>
rows.Values.GetEnumerator();
public DataPacketBuilder ToDataPacketBuilder() =>
new(this);
public class DataPacketBuilder {
readonly IBlueTableSchema schema;
readonly ImmutableDictionary<int, IBlueRow>.Builder table;
readonly ImmutableDictionary<int, IBlueRow>.Builder added =
ImmutableDictionary<int, IBlueRow>.Empty.ToBuilder();
readonly ImmutableDictionary<int, IBlueRow>.Builder removed =
ImmutableDictionary<int, IBlueRow>.Empty.ToBuilder();
public DataPacketBuilder(BlueTableImmutable table) {
schema = table.schema;
this.table = table.rows.ToBuilder();
}
public void AddOrUpdate(IBlueRow row, IEqualityComparer<IBlueRow>? comparer = null) {
var id = row.Id();
if (table.TryGetValue(id, out var orig)) {
if (comparer?.Equals(row, orig) ?? false) {
// No op: This row was already in the table (according to 'comparer').
// Remove it from 'added' and 'removed'.
added.Remove(id);
removed.Remove(id);
return;
}
// Change op: A row with this id was already in the table,
// but its values have changed (according to 'comparer').
removed[id] = orig;
}
added[id] = row;
}
public void Remove(int id) {
added.Remove(id);
if (table.TryGetValue(id, out var orig)) {
removed[id] = orig;
}
}
public DataPacket ToDataPacket(bool reset = true) {
table.RemoveRange(removed.Keys);
table.AddRange(added);
var newRows = new BlueTableImmutable(schema, table.ToImmutable());
var addedRows = new BlueTableImmutable(schema, added.ToImmutable());
var removedRows = new BlueTableImmutable(schema, removed.ToImmutable());
if (reset) {
added.Clear();
removed.Clear();
}
return new(newRows, addedRows, removedRows);
}
public BlueTableImmutable ToImmutable() =>
new(schema, table.ToImmutable());
}
}