Refacoring data pipeline
This commit is contained in:
+113
-1
@@ -4,7 +4,8 @@ interface
|
||||
|
||||
uses
|
||||
System.SysUtils,
|
||||
System.TypInfo;
|
||||
System.TypInfo,
|
||||
Myc.Data.Pipeline;
|
||||
|
||||
type
|
||||
TDataRecord = record
|
||||
@@ -110,6 +111,40 @@ type
|
||||
property Layout: TLayout read FLayout;
|
||||
end;
|
||||
|
||||
TDataRecordLayoutHelper = record helper for TDataRecord.TLayout
|
||||
function FieldAsRecord<T>(const Name: String): TConverter<T, TDataRecord>;
|
||||
function FieldOfRecord<T>(const Name: String): TConverter<TDataRecord, T>;
|
||||
end;
|
||||
|
||||
type
|
||||
TRecordMapping = record
|
||||
Layout: TDataRecord.TLayout;
|
||||
Fields: array of record
|
||||
FromField, ToField: String
|
||||
end;
|
||||
end;
|
||||
|
||||
// Factory for creating specific converter instances.
|
||||
TRecordConverter = record
|
||||
class function DataMapping(
|
||||
const Inputs: TArray<TRecordMapping>;
|
||||
const Output: TDataRecord.TLayout
|
||||
): TConverter<TArray<TDataRecord>, TDataRecord>; static;
|
||||
|
||||
class function JoinRecords(
|
||||
const TargetLayout: TDataRecord.TLayout;
|
||||
const Mapping: TArray<TRecordMapping>;
|
||||
const Producers: TArray<TProducer<TDataRecord>>
|
||||
): TConverter<TArray<TDataRecord>, TDataRecord>; static;
|
||||
end;
|
||||
|
||||
TDataRecordHelper = record helper for TArray<TProducer<TDataRecord>>
|
||||
function JoinRecords(
|
||||
const TargetLayout: TDataRecord.TLayout;
|
||||
const Mapping: TArray<TRecordMapping>
|
||||
): TProducer<TDataRecord>; experimental;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
@@ -569,4 +604,81 @@ begin
|
||||
Result := not (A = B);
|
||||
end;
|
||||
|
||||
function TDataRecordLayoutHelper.FieldAsRecord<T>(const Name: String): TConverter<T, TDataRecord>;
|
||||
begin
|
||||
var layout := Self;
|
||||
var idx := IndexOf(Name);
|
||||
Result :=
|
||||
TConverter<T, TDataRecord>.CreateConverter(
|
||||
function(const Value: T): TDataRecord
|
||||
begin
|
||||
Result := TDataRecord.Create(layout);
|
||||
Result.SetValue(idx, Value);
|
||||
end
|
||||
);
|
||||
end;
|
||||
|
||||
function TDataRecordLayoutHelper.FieldOfRecord<T>(const Name: String): TConverter<TDataRecord, T>;
|
||||
begin
|
||||
var idx := IndexOf(Name);
|
||||
Result := TConverter<TDataRecord, T>.CreateConverter(function(const Value: TDataRecord): T begin Value.GetValue(idx, Result); end);
|
||||
end;
|
||||
|
||||
class function TRecordConverter.DataMapping(
|
||||
const Inputs: TArray<TRecordMapping>;
|
||||
const Output: TDataRecord.TLayout
|
||||
): TConverter<TArray<TDataRecord>, TDataRecord>;
|
||||
var
|
||||
Idxs: array of array of record
|
||||
FromIdx, ToIdx: Integer
|
||||
end;
|
||||
begin
|
||||
SetLength(Idxs, Length(Inputs));
|
||||
for var i := 0 to High(Idxs) do
|
||||
begin
|
||||
SetLength(Idxs[i], Length(Inputs[i].Fields));
|
||||
for var j := 0 to High(Idxs[i]) do
|
||||
begin
|
||||
Idxs[i][j].FromIdx := Inputs[i].Layout.IndexOf(Inputs[i].Fields[j].FromField);
|
||||
Idxs[i][j].ToIdx := Output.IndexOf(Inputs[i].Fields[j].ToField);
|
||||
end;
|
||||
end;
|
||||
|
||||
Result :=
|
||||
TConverter<TArray<TDataRecord>, TDataRecord>.CreateConverter(
|
||||
function(const Inputs: TArray<TDataRecord>): TDataRecord
|
||||
begin
|
||||
Result := TDataRecord.Create(Output);
|
||||
for var i := 0 to High(Idxs) do
|
||||
for var j := 0 to High(Idxs[i]) do
|
||||
Result.CopyValue(Inputs[i], Idxs[i][j].FromIdx, Idxs[i][j].ToIdx);
|
||||
end
|
||||
);
|
||||
end;
|
||||
|
||||
class function TRecordConverter.JoinRecords(
|
||||
const TargetLayout: TDataRecord.TLayout;
|
||||
const Mapping: TArray<TRecordMapping>;
|
||||
const Producers: TArray<TProducer<TDataRecord>>
|
||||
): TConverter<TArray<TDataRecord>, TDataRecord>;
|
||||
begin
|
||||
var RecProvider := TConverter.Join<TDataRecord>(jmAll, Producers);
|
||||
|
||||
Result := TRecordConverter.DataMapping(Mapping, TargetLayout);
|
||||
|
||||
RecProvider.Chain(Result.Consumer);
|
||||
end;
|
||||
|
||||
function TDataRecordHelper.JoinRecords(
|
||||
const TargetLayout: TDataRecord.TLayout;
|
||||
const Mapping: TArray<TRecordMapping>
|
||||
): TProducer<TDataRecord>;
|
||||
begin
|
||||
var map := TRecordConverter.DataMapping(Mapping, TargetLayout);
|
||||
|
||||
TConverter.Join<TDataRecord>(jmAll, Self).Chain(map.Consumer);
|
||||
|
||||
Result := map.Producer;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user