From b335ddcfc97ea873d95320ca343d2bc67ba21641 Mon Sep 17 00:00:00 2001 From: HLWeil Date: Wed, 23 Oct 2024 16:28:27 +0200 Subject: [PATCH 1/4] test and fix ArcTable copy member deep copying ontology annotations --- src/Core/ArcTypes.fs | 5 +- src/Core/Table/ArcTable.fs | 13 +++- src/Core/Table/CompositeHeader.fs | 29 ++++++++ src/Core/Template.fs | 19 +++++- tests/Core/ArcTable.Tests.fs | 106 +++++++++++++++++++++++++++++- 5 files changed, 162 insertions(+), 10 deletions(-) diff --git a/src/Core/ArcTypes.fs b/src/Core/ArcTypes.fs index d1496ded..7431a3e5 100644 --- a/src/Core/ArcTypes.fs +++ b/src/Core/ArcTypes.fs @@ -381,10 +381,7 @@ type ArcAssay(identifier: string, ?measurementType : OntologyAnnotation, ?techno assay member this.Copy() : ArcAssay = - let nextTables = ResizeArray() - for table in this.Tables do - let copy = table.Copy() - nextTables.Add(copy) + let nextTables = this.Tables |> ResizeArray.map (fun c -> c.Copy()) let nextComments = this.Comments |> ResizeArray.map (fun c -> c.Copy()) let nextDataMap = this.DataMap |> Option.map (fun d -> d.Copy()) let nextPerformers = this.Performers |> ResizeArray.map (fun c -> c.Copy()) diff --git a/src/Core/Table/ArcTable.fs b/src/Core/Table/ArcTable.fs index dcd1ee3e..f20e99d3 100644 --- a/src/Core/Table/ArcTable.fs +++ b/src/Core/Table/ArcTable.fs @@ -73,11 +73,18 @@ type ArcTable(name: string, headers: ResizeArray, values: Syste member this.Columns with get() = [|for i = 0 to this.ColumnCount - 1 do this.GetColumn(i)|] - member this.Copy() : ArcTable = + member this.Copy() : ArcTable = + let nextHeaders = this.Headers |> ResizeArray.map (fun h -> h.Copy()) + let nextValues = Dictionary() + this.Values.Keys + |> Seq.iter (fun (ci,ri) -> + let newCell = this.Values.[ci,ri].Copy() + nextValues.Add((ci,ri),newCell) + ) ArcTable.create( this.Name, - ResizeArray(this.Headers), - Dictionary(this.Values) + nextHeaders, + nextValues ) /// Returns a cell at given position if it exists, else returns None. diff --git a/src/Core/Table/CompositeHeader.fs b/src/Core/Table/CompositeHeader.fs index 67c4e268..9f197667 100644 --- a/src/Core/Table/CompositeHeader.fs +++ b/src/Core/Table/CompositeHeader.fs @@ -432,6 +432,35 @@ type CompositeHeader = | ProtocolType | ProtocolREF | ProtocolDescription | ProtocolUri | ProtocolVersion | Performer | Date | Input _ | Output _ -> true | _ -> false + member this.Copy() = + match this with + | Parameter oa -> Parameter (oa.Copy()) + | Factor oa -> Factor (oa.Copy()) + | Characteristic oa -> Characteristic (oa.Copy()) + | Component oa -> Component (oa.Copy()) + | _ -> this + + + + + //| Parameter oa -> $"Parameter [{oa.NameText}]" + //| Factor oa -> $"Factor [{oa.NameText}]" + //| Characteristic oa -> $"Characteristic [{oa.NameText}]" + //| Component oa -> $"Component [{oa.NameText}]" + //| ProtocolType -> "Protocol Type" + //| ProtocolREF -> "Protocol REF" + //| ProtocolDescription -> "Protocol Description" + //| ProtocolUri -> "Protocol Uri" + //| ProtocolVersion -> "Protocol Version" + //| Performer -> "Performer" + //| Date -> "Date" + //| Input io -> io.asInput + //| Output io -> io.asOutput + //| Comment key -> $"Comment [{key}]" + //| FreeText str -> str + + + #if FABLE_COMPILER [] diff --git a/src/Core/Template.fs b/src/Core/Template.fs index 672d5d59..1d2d9e66 100644 --- a/src/Core/Template.fs +++ b/src/Core/Template.fs @@ -1,4 +1,4 @@ -namespace ARCtrl +namespace ARCtrl open Fable.Core open ARCtrl.Helper @@ -68,6 +68,23 @@ type Template(id: System.Guid, table: ArcTable, ?name: string, ?description, ?or member this.StructurallyEquals (other: Template) = this.GetHashCode() = other.GetHashCode() + member this.Copy() : Template = + let nextAuthors = this.Authors |> ResizeArray.map (fun c -> c.Copy()) + let nextRepos = this.EndpointRepositories |> ResizeArray.map (fun c -> c.Copy()) + let nextTags = this.Tags |> ResizeArray.map (fun c -> c.Copy()) + Template.create( + this.Id, + this.Table.Copy(), + this.Name, + this.Description, + this.Organisation, + this.Version, + nextAuthors, + nextRepos, + nextTags, + this.LastUpdated + ) + // custom check override this.Equals other = match other with diff --git a/tests/Core/ArcTable.Tests.fs b/tests/Core/ArcTable.Tests.fs index c95e6ee8..51d3722a 100644 --- a/tests/Core/ArcTable.Tests.fs +++ b/tests/Core/ArcTable.Tests.fs @@ -926,7 +926,7 @@ let private tests_AddColumn_Mutable = ] /// Exemplary tests to check non mutable implementation of mutability bases member function. -let private tests_addColumn_Copy = +let private tests_addColumn = let header_input = CompositeHeader.Input IOType.Source let header_chara = CompositeHeader.Characteristic oa_species let createCells_chara (count) = Array.init count (fun _ -> CompositeCell.createTerm oa_chlamy) @@ -2539,6 +2539,107 @@ let private tests_equality = testList "equality" [ ] ] +let private tests_copy = testList "Copy" [ + testCase "DefaultEquality"<| fun _ -> + let table = create_testTable() + let copy = table.Copy() + Expect.equal table copy "Tables should be equal" + testCase "StructuralEquality" <| fun _ -> + let table = create_testTable() + let copy = table.Copy() + let equals = table.StructurallyEquals(copy) + Expect.isTrue equals "Structural equality should be true" + testCase "ReferenceEquality" <| fun _ -> + let table = create_testTable() + let copy = table.Copy() + let equals = table.ReferenceEquals(copy) + Expect.isFalse equals "Reference equality should be false" + testCase "UpdateInputHeader" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn(CompositeHeader.Input IOType.Sample) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.UpdateHeader(0,CompositeHeader.Input IOType.Data) + Expect.equal (table.Headers.[0]) (CompositeHeader.Input IOType.Sample) "Header of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateParameterHeader" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn(CompositeHeader.Parameter (OntologyAnnotation("OldAnnotation"))) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.UpdateHeader(0,CompositeHeader.Parameter (OntologyAnnotation("NewAnnotation"))) + Expect.equal (table.Headers.[0]) (CompositeHeader.Parameter (OntologyAnnotation("OldAnnotation"))) "Header of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateAnnotationOfParameterHeader" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn(CompositeHeader.Parameter (OntologyAnnotation("OldAnnotation"))) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + match copy.Headers.[0] with + | CompositeHeader.Parameter oa -> oa.Name <- Some "NewAnnotation" + | _ -> Expect.isTrue false "Header not parameter?" + Expect.equal (table.Headers.[0]) (CompositeHeader.Parameter (OntologyAnnotation("OldAnnotation"))) "Header of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateFreetextCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Input IOType.Sample, + [|CompositeCell.FreeText "OldFreetext"|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.SetCellAt(0,0,CompositeCell.FreeText "NewFreetext") + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.FreeText "OldFreetext") "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateTermCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Parameter (OntologyAnnotation("MyParameter")), + [|CompositeCell.createTerm (OntologyAnnotation("OldAnnotation"))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.SetCellAt(0,0,CompositeCell.createTerm (OntologyAnnotation("NewAnnotation"))) + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.createTerm (OntologyAnnotation("OldAnnotation"))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateAnnotationOfTermCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Parameter (OntologyAnnotation("MyParameter")), + [|CompositeCell.createTerm (OntologyAnnotation("OldAnnotation"))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + match copy.GetCellAt(0,0) with + | CompositeCell.Term oa -> oa.Name <- Some "NewAnnotation" + | _ -> Expect.isTrue false "Cell not term?" + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.createTerm (OntologyAnnotation("OldAnnotation"))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateUnitCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Parameter (OntologyAnnotation("MyParameter")), + [|CompositeCell.createUnitized("OldValue",(OntologyAnnotation("OldAnnotation")))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.SetCellAt(0,0,CompositeCell.createUnitized("NewValue",(OntologyAnnotation("NewAnnotation")))) + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.createUnitized("OldValue",(OntologyAnnotation("OldAnnotation")))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateAnnotationOfUnitCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Parameter (OntologyAnnotation("MyParameter")), + [|CompositeCell.createUnitized("OldValue",(OntologyAnnotation("OldAnnotation")))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + match copy.GetCellAt(0,0) with + | CompositeCell.Unitized (v,oa) -> oa.Name <- Some "NewAnnotation" + | _ -> Expect.isTrue false "Cell not unit?" + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.createUnitized("OldValue",(OntologyAnnotation("OldAnnotation")))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" +] let private tests_fillMissing = testList "fillMissing" [ testCase "OntologyAnnotationCopied" <| fun _ -> @@ -2574,7 +2675,7 @@ let main = tests_UpdateCellsBy tests_UpdateColumn tests_AddColumn_Mutable - tests_addColumn_Copy + tests_addColumn tests_AddColumns tests_AddColumnFill tests_RemoveColumn @@ -2591,5 +2692,6 @@ let main = tests_IterColumns tests_GetHashCode tests_equality + tests_copy tests_fillMissing ] \ No newline at end of file From c3ed011ece9c38e874d954e062b897b0a9d985cf Mon Sep 17 00:00:00 2001 From: HLWeil Date: Wed, 23 Oct 2024 16:37:57 +0200 Subject: [PATCH 2/4] add template copy tests --- tests/Core/Template.Tests.fs | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/tests/Core/Template.Tests.fs b/tests/Core/Template.Tests.fs index e59f449a..219b437b 100644 --- a/tests/Core/Template.Tests.fs +++ b/tests/Core/Template.Tests.fs @@ -1,4 +1,4 @@ -module Template.Tests +module Template.Tests open Thoth.Json.Core @@ -182,8 +182,40 @@ let private tests_filters = testList "filters" [ ] ] +let private tests_copy = testList "Copy" [ + testCase "DefaultEquality"<| fun _ -> + let template = create_TestTemplate() + let copy = template.Copy() + Expect.equal template copy "Templates should be equal" + testCase "StructuralEquality" <| fun _ -> + let template = create_TestTemplate() + let copy = template.Copy() + let equals = template.StructurallyEquals(copy) + Expect.isTrue equals "Structural equality should be true" + testCase "ReferenceEquality" <| fun _ -> + let template = create_TestTemplate() + let copy = template.Copy() + let equals = template.ReferenceEquals(copy) + Expect.isFalse equals "Reference equality should be false" + testCase "UpdatePerson" <| fun _ -> + let template = create_TestTemplate() + let copy = template.Copy() + Expect.equal template copy "Templates should be equal before change" + copy.Authors.[0].FirstName <- Some "Jane" + Expect.equal template.Authors.[0].FirstName (Some "John") "Name should not have been updated" + Expect.notEqual copy template "Templates should not be equal after change" + testCase "AddTableColumn" <| fun _ -> + let template = create_TestTemplate() + let copy = template.Copy() + Expect.equal template copy "Templates should be equal before change" + copy.Table.AddColumn(CompositeHeader.Parameter (OntologyAnnotation("VeryImportant"))) + Expect.notEqual copy template "Templates should not be equal after change" +] + + let main = testList "Templates" [ tests_equality tests_HashCode tests_filters + tests_copy ] \ No newline at end of file From d9e4ae4157c19ecaa13be13a690e0115f8120365 Mon Sep 17 00:00:00 2001 From: Lukas Weil Date: Wed, 23 Oct 2024 16:52:03 +0200 Subject: [PATCH 3/4] small cleanup of CompositeHeader --- src/Core/Table/CompositeHeader.fs | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/Core/Table/CompositeHeader.fs b/src/Core/Table/CompositeHeader.fs index 9f197667..b534810d 100644 --- a/src/Core/Table/CompositeHeader.fs +++ b/src/Core/Table/CompositeHeader.fs @@ -439,27 +439,7 @@ type CompositeHeader = | Characteristic oa -> Characteristic (oa.Copy()) | Component oa -> Component (oa.Copy()) | _ -> this - - - - - //| Parameter oa -> $"Parameter [{oa.NameText}]" - //| Factor oa -> $"Factor [{oa.NameText}]" - //| Characteristic oa -> $"Characteristic [{oa.NameText}]" - //| Component oa -> $"Component [{oa.NameText}]" - //| ProtocolType -> "Protocol Type" - //| ProtocolREF -> "Protocol REF" - //| ProtocolDescription -> "Protocol Description" - //| ProtocolUri -> "Protocol Uri" - //| ProtocolVersion -> "Protocol Version" - //| Performer -> "Performer" - //| Date -> "Date" - //| Input io -> io.asInput - //| Output io -> io.asOutput - //| Comment key -> $"Comment [{key}]" - //| FreeText str -> str - - + #if FABLE_COMPILER @@ -494,4 +474,4 @@ type CompositeHeader = static member comment(s:string) = Comment s -#endif \ No newline at end of file +#endif From 68fc64e37032b26e7748e2e545096412f0a3596e Mon Sep 17 00:00:00 2001 From: HLWeil Date: Thu, 24 Oct 2024 11:25:52 +0200 Subject: [PATCH 4/4] add data cell update tests for ArcTable Copy function --- tests/Core/ArcTable.Tests.fs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/Core/ArcTable.Tests.fs b/tests/Core/ArcTable.Tests.fs index 51d3722a..00463345 100644 --- a/tests/Core/ArcTable.Tests.fs +++ b/tests/Core/ArcTable.Tests.fs @@ -2591,6 +2591,30 @@ let private tests_copy = testList "Copy" [ copy.SetCellAt(0,0,CompositeCell.FreeText "NewFreetext") Expect.equal (table.GetCellAt(0,0)) (CompositeCell.FreeText "OldFreetext") "Cell of old table should stay as is" Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateDataCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Input IOType.Data, + [|CompositeCell.Data (Data(name = "OldData"))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + copy.SetCellAt(0,0,CompositeCell.Data (Data(name = "NewData"))) + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.Data (Data(name = "OldData"))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" + testCase "UpdateNameOfDataCell" <| fun _ -> + let table = ArcTable.init("NewTable") + table.AddColumn( + CompositeHeader.Input IOType.Data, + [|CompositeCell.Data (Data(name = "OldData"))|] + ) + let copy = table.Copy() + Expect.equal copy table "Should be equal before change" + match copy.GetCellAt(0,0) with + | CompositeCell.Data d -> d.Name <- Some "NewData" + | _ -> Expect.isTrue false "Cell not data?" + Expect.equal (table.GetCellAt(0,0)) (CompositeCell.Data (Data(name = "OldData"))) "Cell of old table should stay as is" + Expect.notEqual copy table "Should not be equal after change" testCase "UpdateTermCell" <| fun _ -> let table = ArcTable.init("NewTable") table.AddColumn(