Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Template copy and test+fix deepcopying of ArcTable #463

Merged
merged 4 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/Core/ArcTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
Expand Down
13 changes: 10 additions & 3 deletions src/Core/Table/ArcTable.fs
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,18 @@ type ArcTable(name: string, headers: ResizeArray<CompositeHeader>, 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<int*int,CompositeCell>()
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.
Expand Down
11 changes: 10 additions & 1 deletion src/Core/Table/CompositeHeader.fs
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,15 @@ 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())
Freymaurer marked this conversation as resolved.
Show resolved Hide resolved
| _ -> this


#if FABLE_COMPILER

[<CompiledName("component")>]
Expand Down Expand Up @@ -465,4 +474,4 @@ type CompositeHeader =

static member comment(s:string) = Comment s

#endif
#endif
19 changes: 18 additions & 1 deletion src/Core/Template.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace ARCtrl
namespace ARCtrl

open Fable.Core
open ARCtrl.Helper
Expand Down Expand Up @@ -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
Expand Down
130 changes: 128 additions & 2 deletions tests/Core/ArcTable.Tests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -2539,6 +2539,131 @@ 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 "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(
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 _ ->
Expand Down Expand Up @@ -2574,7 +2699,7 @@ let main =
tests_UpdateCellsBy
tests_UpdateColumn
tests_AddColumn_Mutable
tests_addColumn_Copy
tests_addColumn
tests_AddColumns
tests_AddColumnFill
tests_RemoveColumn
Expand All @@ -2591,5 +2716,6 @@ let main =
tests_IterColumns
tests_GetHashCode
tests_equality
tests_copy
tests_fillMissing
]
34 changes: 33 additions & 1 deletion tests/Core/Template.Tests.fs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Template.Tests
module Template.Tests

open Thoth.Json.Core

Expand Down Expand Up @@ -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
]
Loading