| | 1 | | using ValidateLib.Metadata.Descriptors; |
| | 2 | | using ValidateLib.Metadata.DialectExtraction; |
| | 3 | | using ValidateLib.Metadata.Validators; |
| | 4 | | using ValidateLib.Results; |
| | 5 | | using ValidateLib.TabularData.AnnotatedTabularDataModel; |
| | 6 | | using ValidateLib.TabularData.Parsing; |
| | 7 | | using ValidateLib.TabularData.Validation.ValidationRules; |
| | 8 | |
|
| | 9 | | namespace ValidateLib.TabularData.Validation |
| | 10 | | { |
| | 11 | | /// <summary> |
| | 12 | | /// Validates table groups. |
| | 13 | | /// Uses <see cref="TabularDataTableValidator"/>. |
| | 14 | | /// </summary> |
| | 15 | | public class TabluarDataTableGroupValidator |
| | 16 | | { |
| 1 | 17 | | private TableGroupDescriptor tableGroupDescriptor { get; set; } |
| 1 | 18 | | protected List<ICellValidationRule>? cellValidationRules { get; set; } = new List<ICellValidationRule>(); |
| 1 | 19 | | protected List<IRowValidationRule>? rowValidationRules { get; set; } = new List<IRowValidationRule>(); |
| 1 | 20 | | public TabluarDataTableGroupValidator(TableGroupDescriptor tableGroup, List<ICellValidationRule>? cellRules = nu |
| | 21 | | { |
| 1 | 22 | | tableGroupDescriptor = tableGroup; |
| 1 | 23 | | rowValidationRules = rowValidationRules; |
| 1 | 24 | | cellValidationRules = cellRules; |
| 1 | 25 | | } |
| | 26 | | /// <summary> |
| | 27 | | /// Validates table group and adds errors and warnings to <paramref name="validationDetails"/>. |
| | 28 | | /// </summary> |
| | 29 | | /// <param name="validationDetails"> where we insert the errors and warnings.</param> |
| | 30 | | public void ValidateTableGroup(ITableGroupValidationDetail validationDetails) |
| | 31 | | { |
| 1 | 32 | | List<Table> tables = PrepareAnnotatedTables(); |
| | 33 | |
|
| 1 | 34 | | if (tableGroupDescriptor.tables is not null && tableGroupDescriptor.tables._value is not null) |
| | 35 | | { |
| 1 | 36 | | for (int i = 0; i < tableGroupDescriptor.tables!._value!.Count; i++) |
| | 37 | | { |
| 1 | 38 | | var validationDetail = validationDetails.TableValidationDetails[i]; |
| 1 | 39 | | if (validationDetail.Errors.Count > 0) continue; |
| 1 | 40 | | var tableDescriptor = tableGroupDescriptor.tables!._value![i]; |
| 1 | 41 | | TabularDataTableValidator tableValidator = new TabularDataTableValidator(tableDescriptor, cellValida |
| 1 | 42 | | tableValidator.ValidateTable(validationDetail, tableDescriptor.table!); |
| | 43 | | } |
| | 44 | | } |
| | 45 | |
|
| 1 | 46 | | var FKRule = new FKReferencedValuesMustMatchValidationRule(); |
| 1 | 47 | | validationDetails.GeneralErrors.AddRange(FKRule.ValidateReferencedValuesFK(tables, tableGroupDescriptor)); |
| 1 | 48 | | } |
| | 49 | |
|
| | 50 | | /// <summary> |
| | 51 | | /// Prepare annotated tables for the table group validation. This steep needs to be done in advance |
| | 52 | | /// because we do not know exactly what columns to save during the CSV parsing during the parsing of |
| | 53 | | /// just one CSV file. |
| | 54 | | /// </summary> |
| | 55 | | /// <returns></returns> |
| | 56 | | public List<Table> PrepareAnnotatedTables() |
| | 57 | | { |
| 1 | 58 | | List<Table> tables = new List<Table>(); |
| 1 | 59 | | if (tableGroupDescriptor.tables is not null && tableGroupDescriptor.tables._value is not null) |
| | 60 | | { |
| 1 | 61 | | foreach (var tableDescriptor in tableGroupDescriptor.tables._value) |
| | 62 | | { |
| 1 | 63 | | CreateAnnotatedTable(tableDescriptor, tables); |
| | 64 | | } |
| 1 | 65 | | SetTheReferencedColumnsToBePartOfFK(); |
| | 66 | | } |
| 1 | 67 | | return tables; |
| | 68 | | } |
| | 69 | |
|
| | 70 | | /// <summary> |
| | 71 | | /// Creates one annotated table. At this point the FK flags of referenced foreign keys are not |
| | 72 | | /// set completely. |
| | 73 | | /// </summary> |
| | 74 | | /// <param name="tableDescriptor"></param> |
| | 75 | | /// <param name="tables"></param> |
| | 76 | | private void CreateAnnotatedTable(TableDescriptor tableDescriptor, List<Table> tables) |
| | 77 | | { |
| 1 | 78 | | var dialect = DialectExtractor.GetDialect(tableDescriptor); |
| 1 | 79 | | var flags = FlagsCreator.ExtractFlagsFromDialectDescriptor(dialect); |
| 1 | 80 | | TabularDataAnnotator tabularDataAnottator = new TabularDataAnnotator(flags); |
| 1 | 81 | | Table table = new Table(); |
| 1 | 82 | | tabularDataAnottator.AnnotateTable(table, tableDescriptor); |
| 1 | 83 | | tabularDataAnottator.CreateAnnotatedColumns(table, tableDescriptor); |
| 1 | 84 | | tableDescriptor.table = table; |
| 1 | 85 | | tables.Add(table); |
| 1 | 86 | | } |
| | 87 | |
|
| | 88 | | /// <summary> |
| | 89 | | /// Iterates over tables and for each one of them checks for the FK descriptor and tries |
| | 90 | | /// to set the referenced columns to be a part of the foreignKey so they would be |
| | 91 | | /// saved during the CSV parsing. |
| | 92 | | /// </summary> |
| | 93 | | private void SetTheReferencedColumnsToBePartOfFK() |
| | 94 | | { |
| | 95 | |
|
| 1 | 96 | | foreach (var tableDescriptor in tableGroupDescriptor!.tables!._value!) |
| | 97 | | { |
| 1 | 98 | | SetReFerencedColumnsForOneTable(tableDescriptor); |
| | 99 | | } |
| | 100 | |
|
| 1 | 101 | | } |
| | 102 | |
|
| | 103 | | /// <summary> |
| | 104 | | /// Iterates over one's table foreign keys (if they have some) and then sets all the |
| | 105 | | /// referenced columns from other tables to be a part of foreign (referenced) key. |
| | 106 | | /// </summary> |
| | 107 | | /// <param name="tableDescriptor"></param> |
| | 108 | | private void SetReFerencedColumnsForOneTable(TableDescriptor tableDescriptor) |
| | 109 | | { |
| 1 | 110 | | if (HasTableFK(tableDescriptor)) |
| | 111 | | { |
| 1 | 112 | | var foreignKeys = tableDescriptor.tableSchema!._value!.foreignKeys!._value!; |
| 1 | 113 | | foreach (var FKDescriptor in foreignKeys) |
| | 114 | | { |
| 1 | 115 | | TableDescriptor referencedTableDescriptor = ForeignKeyValidator.FindReferencedTable(tableGroupDescri |
| 1 | 116 | | Table referencedTable = referencedTableDescriptor.table!; |
| 1 | 117 | | foreach (var column in referencedTable.columns) |
| | 118 | | { |
| 1 | 119 | | if (column.name is null) |
| | 120 | | continue; |
| 1 | 121 | | if (FKDescriptor!.reference!._value!.columnReference!._value!.Contains(column.name)) |
| 1 | 122 | | column.isPartOfForeignKey = true; |
| | 123 | | } |
| | 124 | | } |
| | 125 | |
|
| | 126 | | } |
| 1 | 127 | | } |
| | 128 | |
|
| | 129 | | /// <summary> |
| | 130 | | /// Checks whether a tableDescriptor has some foreign key descriptor. |
| | 131 | | /// </summary> |
| | 132 | | /// <param name="tableDescriptor"></param> |
| | 133 | | /// <returns></returns> |
| | 134 | | private bool HasTableFK(TableDescriptor tableDescriptor) |
| | 135 | | { |
| 1 | 136 | | return tableDescriptor.tableSchema is not null && |
| 1 | 137 | | tableDescriptor.tableSchema._value is not null && |
| 1 | 138 | | tableDescriptor.tableSchema._value.foreignKeys is not null && |
| 1 | 139 | | tableDescriptor.tableSchema._value.foreignKeys._value is not null; |
| | 140 | | } |
| | 141 | | } |
| | 142 | |
|
| | 143 | |
|
| | 144 | | } |