Skip to content

Commit 57f3a2e

Browse files
committed
add rename contract and assay rename logic
1 parent 6ef030d commit 57f3a2e

4 files changed

Lines changed: 98 additions & 1 deletion

File tree

src/ARCtrl/ARC.fs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) =
8888
member this.RemoveAssay(assayIdentifier: string) =
8989
let isa =
9090
match this.ISA with
91-
| Some i -> i
91+
| Some i when i.AssayIdentifiers |> Seq.contains assayIdentifier -> i
92+
| Some _ -> failwith "ARC does not contain assay with given name"
9293
| None -> failwith "Cannot remove assay from null ISA value."
9394
let assay = isa.GetAssay(assayIdentifier)
9495
let studies = assay.StudiesRegisteredIn
@@ -105,6 +106,25 @@ type ARC(?isa : ArcInvestigation, ?cwl : CWL.CWL, ?fs : FileSystem.FileSystem) =
105106
]
106107
|> ResizeArray
107108

109+
member this.RenameAssay(oldAssayIdentifier: string, newAssayIdentifier: string) =
110+
let isa =
111+
match this.ISA with
112+
| Some i when i.AssayIdentifiers |> Seq.contains oldAssayIdentifier -> i
113+
| Some _ -> failwith "ARC does not contain assay with given name"
114+
| None -> failwith "Cannot rename assay in null ISA value."
115+
116+
isa.RenameAssay(oldAssayIdentifier,newAssayIdentifier)
117+
let paths = this.FileSystem.Tree.ToFilePaths()
118+
let oldAssayFolderPath = Path.getAssayFolderPath(oldAssayIdentifier)
119+
let newAssayFolderPath = Path.getAssayFolderPath(newAssayIdentifier)
120+
let renamedPaths = paths |> Array.map (fun p -> p.Replace(oldAssayFolderPath,newAssayFolderPath))
121+
this.SetFilePaths(renamedPaths)
122+
[
123+
yield Contract.createRename(oldAssayFolderPath,newAssayFolderPath)
124+
yield! this.GetUpdateContracts()
125+
]
126+
|> ResizeArray
127+
108128
member this.RemoveStudy(studyIdentifier: string) =
109129
let isa =
110130
match this.ISA with

src/Contract/Contract.fs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ type Operation =
6262
| [<CompiledName("DELETE")>] DELETE
6363
| [<CompiledName("READ")>] READ
6464
| [<CompiledName("EXECUTE")>] EXECUTE
65+
| [<CompiledName("RENAME")>] RENAME
6566

6667
[<AttachMembers>]
6768
type Contract =
@@ -79,12 +80,14 @@ type Contract =
7980
[<NamedParams(fromIndex=2)>]
8081
#endif
8182
static member create(op, path, ?dtoType, ?dto) = {Operation= op; Path = path; DTOType = dtoType; DTO = dto}
83+
8284
/// <summary>Create a CREATE contract with all necessary information.</summary>
8385
/// <param name="path">The path relative from ARC root, at which the new file should be created.</param>
8486
/// <param name="dtoType">The file type.</param>
8587
/// <param name="dto">The file data.</param>
8688
/// <returns>Returns a CREATE contract.</returns>
8789
static member createCreate(path, dtoType: DTOType, ?dto: DTO) = {Operation= Operation.CREATE; Path = path; DTOType = Some dtoType; DTO = dto}
90+
8891
/// <summary>Create a UPDATE contract with all necessary information.
8992
///
9093
/// Update contracts will overwrite in case of a string as DTO and will specifically update relevant changes only for spreadsheet files.
@@ -98,6 +101,7 @@ type Contract =
98101
/// <param name="path">The path relative from ARC root, at which the file should be deleted.</param>
99102
/// <returns>Returns a DELETE contract.</returns>
100103
static member createDelete(path) = {Operation= Operation.DELETE; Path = path; DTOType = None; DTO = None}
104+
101105
/// <summary>Create a READ contract with all necessary information.
102106
///
103107
/// Created without DTO, any api user should update the READ contract with the io read result for further api use.
@@ -107,6 +111,7 @@ type Contract =
107111
/// <param name="dtoType">The file type.</param>
108112
/// <returns>Returns a READ contract.</returns>
109113
static member createRead(path, dtoType: DTOType) = {Operation= Operation.READ; Path = path; DTOType = Some dtoType; DTO = None}
114+
110115
/// <summary>Create a EXECUTE contract with all necessary information.
111116
///
112117
/// This contract type is used to communicate cli tool execution.
@@ -117,3 +122,14 @@ type Contract =
117122
static member createExecute(dto: CLITool, ?path: string) =
118123
let path = Option.defaultValue "" path
119124
{Operation= Operation.EXECUTE; Path = path; DTOType = Some DTOType.CLI; DTO = Some <| DTO.CLITool dto}
125+
126+
/// <summary>Create a RENAME contract with all necessary information.
127+
///
128+
/// This contract type is used to communicate file renaming.
129+
///
130+
/// **Note:** The path is the old path, the DTO is the new path.
131+
/// </summary>
132+
/// <param name="oldPath">The old path relative from ARC root.</param>
133+
/// <param name="newPath">The new path relative from ARC root.</param>
134+
/// <returns>Returns a RENAME contract.</returns>
135+
static member createRename(oldPath, newPath) = {Operation= Operation.RENAME; Path = oldPath; DTOType = None; DTO = Some <| DTO.Text newPath}

src/Core/ArcTypes.fs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,6 +1279,32 @@ type ArcInvestigation(identifier : string, ?title : string, ?description : strin
12791279
newInv.RemoveAssay(assayIdentifier)
12801280
newInv
12811281

1282+
/// <summary>
1283+
/// Renames an assay in the whole investigation
1284+
/// </summary>
1285+
/// <param name="oldIdentifier">Identifier of the assay to be renamed</param>
1286+
/// <param name="newIdentifier">Identifier to which the assay should be renamed to</param>
1287+
member this.RenameAssay(oldIdentifier: string, newIdentifier: string) =
1288+
this.Assays
1289+
|> Seq.iter (fun a ->
1290+
if a.Identifier = oldIdentifier then
1291+
a.Identifier <- newIdentifier
1292+
)
1293+
this.Studies
1294+
|> Seq.iter (fun s ->
1295+
s.RegisteredAssayIdentifiers
1296+
|> Seq.iteri (fun i ai ->
1297+
if ai = oldIdentifier then
1298+
s.RegisteredAssayIdentifiers[i] <- newIdentifier
1299+
)
1300+
)
1301+
1302+
static member renameAssay(oldIdentifier: string, newIdentifier: string) =
1303+
fun (inv: ArcInvestigation) ->
1304+
let newInv = inv.Copy()
1305+
newInv.RenameAssay(oldIdentifier,newIdentifier)
1306+
newInv
1307+
12821308
// - Assay API - CRUD //
12831309
member this.SetAssayAt(index: int, assay: ArcAssay) =
12841310
ArcTypesAux.SanityChecks.validateUniqueAssayIdentifier assay.Identifier (this.Assays |> Seq.removeAt index |> Seq.map (fun a -> a.Identifier))

tests/ARCtrl/ARCtrl.Tests.fs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,12 +685,47 @@ let private tests_RemoveAssay = testList "RemoveAssay" [
685685
Expect.equal actual.[3].Operation UPDATE "study 2 contract cmd"
686686
]
687687

688+
let tests_RenameAssay = testList "RenameAssay" [
689+
testCase "not existing" <| fun _ ->
690+
let i = ArcInvestigation("MyInvestigation")
691+
i.InitAssay("OtherAssayName") |> ignore
692+
let arc = ARC(isa = i)
693+
694+
let assayMoveF =
695+
fun () -> arc.RenameAssay("MyOldAssay","MyNewAssay") |> ignore
696+
697+
Expect.throws assayMoveF "Should fail as arc does not contan assay with given name"
698+
testCase "Basic" <| fun _ ->
699+
let i = ArcInvestigation("MyInvestigation")
700+
i.InitAssay("MyOldAssay") |> ignore
701+
let arc = ARC(isa = i)
702+
arc.GetWriteContracts() |> ignore
703+
let contracts = arc.RenameAssay("MyOldAssay","MyNewAssay")
704+
Expect.hasLength contracts 2 "Contract count is wrong"
705+
let renameContract = contracts.[0]
706+
Expect.equal renameContract.Operation Operation.RENAME "Rename contract operation"
707+
Expect.equal "assays/MyOldAssay" renameContract.Path "Rename contract path"
708+
let renameDTO = Expect.wantSome renameContract.DTO "Rename contract dto"
709+
let expectedRenameDTO = DTO.Text "assays/MyNewAssay"
710+
Expect.equal renameDTO expectedRenameDTO "Rename contract dto"
711+
let updateContract = contracts.[1]
712+
Expect.equal updateContract.Operation Operation.UPDATE "Update contract operation"
713+
Expect.equal updateContract.Path "assays/MyNewAssay/isa.assay.xlsx" "Update contract path"
714+
let updateDTO = Expect.wantSome updateContract.DTO "Update contract dto"
715+
Expect.isTrue updateDTO.isSpreadsheet "Update contract dto"
716+
let wb = updateDTO.AsSpreadsheet() :?> FsWorkbook
717+
let updatedAssay = ARCtrl.Spreadsheet.ArcAssay.fromFsWorkbook wb
718+
Expect.equal updatedAssay.Identifier "MyNewAssay" "Update contract Assay Identifier"
719+
]
720+
721+
688722
let main = testList "ARCtrl" [
689723
tests_model
690724
tests_updateFileSystem
691725
tests_read_contracts
692726
tests_writeContracts
693727
tests_updateContracts
694728
tests_RemoveAssay
729+
tests_RenameAssay
695730
payload_file_filters
696731
]

0 commit comments

Comments
 (0)