diff --git a/src/ARCtrl/ARC.fs b/src/ARCtrl/ARC.fs index b0bebd84..d67ba613 100644 --- a/src/ARCtrl/ARC.fs +++ b/src/ARCtrl/ARC.fs @@ -102,10 +102,10 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = let filteredPaths = paths |> Array.filter (fun p -> p.StartsWith(assayFolderPath) |> not) this.SetFilePaths(filteredPaths) [ - assay.ToDeleteContract() - isa.ToUpdateContract() + yield assay.ToDeleteContract() + yield isa.ToUpdateContract() for s in studies do - s.ToUpdateContract() + yield! s.ToUpdateContract() ] |> ResizeArray @@ -323,7 +323,8 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = /// If datamapFile is set to true, a write contract for the datamap file will be included for each study and assay. /// /// Default: false. - member this.GetWriteContracts () = + member this.GetWriteContracts (?datamapAsFile) = + let datamapAsFile = defaultArg datamapAsFile false //let datamapFile = defaultArg datamapFile false /// Map containing the DTOTypes and objects for the ISA objects. let workbooks = System.Collections.Generic.Dictionary() @@ -337,9 +338,9 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = s.StaticHash <- s.GetLightHashCode() workbooks.Add ( Identifier.Study.fileNameFromIdentifier s.Identifier, - (DTOType.ISA_Study, ArcStudy.toFsWorkbook s) + (DTOType.ISA_Study, ArcStudy.toFsWorkbook(s,datamapSheet = not datamapAsFile)) ) - if s.DataMap.IsSome (*&& datamapFile*) then + if s.DataMap.IsSome && datamapAsFile then let dm = s.DataMap.Value dm.StaticHash <- dm.GetHashCode() workbooks.Add ( @@ -353,8 +354,9 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = a.StaticHash <- a.GetLightHashCode() workbooks.Add ( Identifier.Assay.fileNameFromIdentifier a.Identifier, - (DTOType.ISA_Assay, ArcAssay.toFsWorkbook a)) - if a.DataMap.IsSome (*&& datamapFile*) then + (DTOType.ISA_Assay, ArcAssay.toFsWorkbook(a, datamapSheet = not datamapAsFile)) + ) + if a.DataMap.IsSome && datamapAsFile then let dm = a.DataMap.Value dm.StaticHash <- dm.GetHashCode() workbooks.Add ( @@ -381,7 +383,7 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = /// /// ISA contracts do contain the object data as spreadsheets, while the other contracts only contain the path. /// - member this.GetUpdateContracts () = + member this.GetUpdateContracts (?datamapAsFile) = // Map containing the DTOTypes and objects for the ISA objects. match this.ISA with | None -> // if no ISA is present, return write contracts @@ -403,37 +405,19 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) = for s in inv.Studies do let hash = s.GetLightHashCode() if s.StaticHash = 0 then - yield! s.ToCreateContract(WithFolder = true) - elif s.StaticHash <> hash then - yield s.ToUpdateContract() + yield! s.ToCreateContract(WithFolder = true,?datamapAsFile = datamapAsFile) + else + yield! s.ToUpdateContract(?datamapAsFile = datamapAsFile) s.StaticHash <- hash - - match s.DataMap with - | Some dm when dm.StaticHash = 0 -> - yield dm.ToCreateContractForStudy(s.Identifier) - dm.StaticHash <- dm.GetHashCode() - | Some dm when dm.StaticHash <> dm.GetHashCode() -> - yield dm.ToUpdateContractForStudy(s.Identifier) - dm.StaticHash <- dm.GetHashCode() - | _ -> () // Get Assay contracts for a in inv.Assays do let hash = a.GetLightHashCode() if a.StaticHash = 0 then - yield! a.ToCreateContract(WithFolder = true) - elif a.StaticHash <> hash then - yield a.ToUpdateContract() + yield! a.ToCreateContract(WithFolder = true,?datamapAsFile = datamapAsFile) + else + yield! a.ToUpdateContract(?datamapAsFile = datamapAsFile) a.StaticHash <- hash - - match a.DataMap with - | Some dm when dm.StaticHash = 0 -> - yield dm.ToCreateContractForAssay(a.Identifier) - dm.StaticHash <- dm.GetHashCode() - | Some dm when dm.StaticHash <> dm.GetHashCode() -> - yield dm.ToUpdateContractForAssay(a.Identifier) - dm.StaticHash <- dm.GetHashCode() - | _ -> () |] diff --git a/src/Contract/ArcAssay.fs b/src/Contract/ArcAssay.fs index 6104d008..2d13a5e8 100644 --- a/src/Contract/ArcAssay.fs +++ b/src/Contract/ArcAssay.fs @@ -20,23 +20,49 @@ module AssayContractExtensions = type ArcAssay with - member this.ToCreateContract (?WithFolder) = + member this.ToCreateContract (?WithFolder, ?datamapAsFile) = let withFolder = defaultArg WithFolder false + let dataMapAsFile = defaultArg datamapAsFile false let path = Identifier.Assay.fileNameFromIdentifier this.Identifier - let c = Contract.createCreate(path, DTOType.ISA_Assay, DTO.Spreadsheet (this |> ArcAssay.toFsWorkbook)) + let dto = DTO.Spreadsheet (ArcAssay.toFsWorkbook(this, datamapSheet = not dataMapAsFile)) + let c = Contract.createCreate(path, DTOType.ISA_Assay, dto) [| if withFolder then let folderFS = FileSystemTree.createAssaysFolder([|FileSystemTree.createAssayFolder this.Identifier|]) for p in folderFS.ToFilePaths(false) do - if p <> path && p <> "assays/.gitkeep" then Contract.createCreate(p, DTOType.PlainText) - c + if p <> path && p <> "assays/.gitkeep" then + yield Contract.createCreate(p, DTOType.PlainText) + match this.DataMap with + | Some dm -> + dm.StaticHash <- dm.GetHashCode() + if dataMapAsFile then + yield dm.ToCreateContractForAssay(this.Identifier) + | _ -> () + yield c |] - member this.ToUpdateContract () = + member this.ToUpdateContract (?datamapAsFile) = + let datamapAsFile = defaultArg datamapAsFile false let path = Identifier.Assay.fileNameFromIdentifier this.Identifier - let c = Contract.createUpdate(path, DTOType.ISA_Assay, DTO.Spreadsheet (this |> ArcAssay.toFsWorkbook)) - c + let hash = this.GetLightHashCode() + let datamapHasChanged = + match this.DataMap with + | Some dm -> + let hc = dm.GetHashCode() <> dm.StaticHash + dm.StaticHash <- dm.GetHashCode() + hc + | _ -> false + let createAssayContract() = + let dto = DTO.Spreadsheet (ArcAssay.toFsWorkbook(this, datamapSheet = not datamapAsFile)) + Contract.createUpdate(path, DTOType.ISA_Assay, dto) + [| + if hash <> this.StaticHash || (datamapHasChanged && not datamapAsFile) then + createAssayContract() + if datamapHasChanged && datamapAsFile then + this.DataMap.Value.ToUpdateContractForAssay(this.Identifier) + + |] member this.ToDeleteContract () = let path = getAssayFolderPath(this.Identifier) @@ -49,7 +75,7 @@ module AssayContractExtensions = static member toCreateContract (assay: ArcAssay,?WithFolder) : Contract [] = assay.ToCreateContract(?WithFolder = WithFolder) - static member toUpdateContract (assay: ArcAssay) : Contract = + static member toUpdateContract (assay: ArcAssay) : Contract [] = assay.ToUpdateContract() static member tryFromReadContract (c:Contract) = diff --git a/src/Contract/ArcStudy.fs b/src/Contract/ArcStudy.fs index 57526bea..42fc331c 100644 --- a/src/Contract/ArcStudy.fs +++ b/src/Contract/ArcStudy.fs @@ -20,23 +20,48 @@ module StudyContractExtensions = type ArcStudy with - member this.ToCreateContract (?WithFolder) = + member this.ToCreateContract (?WithFolder, ?datamapAsFile) = let withFolder = defaultArg WithFolder false + let dataMapAsFile = defaultArg datamapAsFile false let path = Identifier.Study.fileNameFromIdentifier this.Identifier - let c = Contract.createCreate(path, DTOType.ISA_Study, DTO.Spreadsheet (this |> ArcStudy.toFsWorkbook)) + let dto = DTO.Spreadsheet (ArcStudy.toFsWorkbook(this, datamapSheet = not dataMapAsFile)) + let c = Contract.createCreate(path, DTOType.ISA_Study, dto) [| if withFolder then let folderFS = FileSystemTree.createStudiesFolder ([|FileSystemTree.createStudyFolder this.Identifier|]) for p in folderFS.ToFilePaths(false) do - if p <> path && p <> "studies/.gitkeep" then Contract.createCreate(p, DTOType.PlainText) - c + if p <> path && p <> "studies/.gitkeep" then yield Contract.createCreate(p, DTOType.PlainText) + match this.DataMap with + | Some dm -> + dm.StaticHash <- dm.GetHashCode() + if dataMapAsFile then + yield dm.ToCreateContractForStudy(this.Identifier) + | _ -> () + yield c |] - member this.ToUpdateContract () = + member this.ToUpdateContract (?datamapAsFile) = + let datamapAsFile = defaultArg datamapAsFile false let path = Identifier.Study.fileNameFromIdentifier this.Identifier - let c = Contract.createUpdate(path, DTOType.ISA_Study, DTO.Spreadsheet (this |> ArcStudy.toFsWorkbook)) - c + let hash = this.GetLightHashCode() + let datamapHasChanged = + match this.DataMap with + | Some dm -> + let hc = dm.GetHashCode() <> dm.StaticHash + dm.StaticHash <- dm.GetHashCode() + hc + | _ -> false + let createStudyContract() = + let dto = DTO.Spreadsheet (ArcStudy.toFsWorkbook(this, datamapSheet = not datamapAsFile)) + Contract.createUpdate(path, DTOType.ISA_Study, dto) + [| + if hash <> this.StaticHash || (datamapHasChanged && not datamapAsFile) then + createStudyContract() + if datamapHasChanged && datamapAsFile then + this.DataMap.Value.ToUpdateContractForStudy(this.Identifier) + + |] member this.ToDeleteContract () = let path = getStudyFolderPath(this.Identifier) @@ -49,7 +74,7 @@ module StudyContractExtensions = static member toCreateContract (study: ArcStudy, ?WithFolder) : Contract [] = study.ToCreateContract(?WithFolder = WithFolder) - static member toUpdateContract (study: ArcStudy) : Contract = + static member toUpdateContract (study: ArcStudy) : Contract [] = study.ToUpdateContract() static member tryFromReadContract (c:Contract) = diff --git a/tests/ARCtrl/ARCtrl.Tests.fs b/tests/ARCtrl/ARCtrl.Tests.fs index 1ae71f6b..d1bd353d 100644 --- a/tests/ARCtrl/ARCtrl.Tests.fs +++ b/tests/ARCtrl/ARCtrl.Tests.fs @@ -163,7 +163,7 @@ let private tests_read_contracts = testList "read_contracts" [ (Array.create 2 (CompositeCell.createFreeText UpdateAssayWithStudyProtocol.description)) "Description value was not taken correctly" ) - testCase "SimpleISA_WithDataset" (fun _ -> + testCase "SimpleISA_WithDatamap" (fun _ -> let contracts = Array.append simpleISAContracts [|SimpleISA.Assay.proteomeDatamapContract|] let arc = ARC() @@ -226,13 +226,13 @@ let private tests_writeContracts = testList "write_contracts" [ Expect.exists contracts (fun c -> c.Path = "assays/MyAssay/isa.assay.xlsx" && c.DTOType.IsSome && c.DTOType.Value = Contract.DTOType.ISA_Assay) "assay file exisiting but has wrong DTO type" ) - testCase "assayWithDatamap" (fun _ -> + testCase "assayWithDatamap_AsFile" (fun _ -> let inv = ArcInvestigation("MyInvestigation", "BestTitle") let a = inv.InitAssay("MyAssay") let dm = DataMap.init() a.DataMap <- Some dm let arc = ARC(isa = inv) - let contracts = arc.GetWriteContracts() + let contracts = arc.GetWriteContracts(datamapAsFile = true) let contractPathsString = contracts |> Array.map (fun c -> c.Path) |> String.concat ", " Expect.equal contracts.Length 10 $"Should contain more contracts as base folders but contained: {contractPathsString}" @@ -463,7 +463,7 @@ let private tests_updateContracts = testList "update_contracts" [ let contracts = arc.GetUpdateContracts() Expect.equal contracts.Length 0 "Should contain no contracts as there are no changes" ) - testCase "simpleISA_Datamap_Changed" (fun _ -> + testCase "simpleISA_Datamap_Changed_AsFile" (fun _ -> let arc = ARC() let readContracts = Array.append simpleISAContracts [|SimpleISA.Assay.proteomeDatamapContract|] arc.SetISAFromContracts readContracts @@ -472,10 +472,26 @@ let private tests_updateContracts = testList "update_contracts" [ let dm = Expect.wantSome (isa.GetAssay(SimpleISA.Assay.proteomeIdentifer).DataMap) "Assay should have datamap" dm.GetDataContext(1).Name <- Some "Hello" - let contracts = arc.GetUpdateContracts() + let contracts = arc.GetUpdateContracts(datamapAsFile = true) Expect.equal contracts.Length 1 $"Should contain only assay datamap change contract" let expectedPath = Identifier.Assay.datamapFileNameFromIdentifier SimpleISA.Assay.proteomeIdentifer Expect.equal contracts.[0].Path expectedPath "Should be the assay datamap file" + let nextContracts = arc.GetUpdateContracts(datamapAsFile = true) + Expect.equal nextContracts.Length 0 "Should contain no contracts as there are no changes" + ) + testCase "simpleISA_Datamap_Changed_AsSheet" (fun _ -> + let arc = ARC() + let readContracts = Array.append simpleISAContracts [|SimpleISA.Assay.proteomeDatamapContract|] + arc.SetISAFromContracts readContracts + let isa = arc.ISA.Value + + let dm = Expect.wantSome (isa.GetAssay(SimpleISA.Assay.proteomeIdentifer).DataMap) "Assay should have datamap" + dm.GetDataContext(1).Name <- Some "Hello" + + let contracts = arc.GetUpdateContracts() + Expect.equal contracts.Length 1 $"Should contain only assay datamap change contract" + let expectedPath = Identifier.Assay.fileNameFromIdentifier SimpleISA.Assay.proteomeIdentifer + Expect.equal contracts.[0].Path expectedPath "Should be the assay file, as datamap is contained in assay" let nextContracts = arc.GetUpdateContracts() Expect.equal nextContracts.Length 0 "Should contain no contracts as there are no changes" )