Skip to content

Commit

Permalink
🔀 Merge pull request #123 from nfdi4plants/bugfixes
Browse files Browse the repository at this point in the history
Update study & assay delete
  • Loading branch information
omaus authored Mar 24, 2022
2 parents a58c742 + b6f7a9a commit 9dfc755
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 90 deletions.
46 changes: 38 additions & 8 deletions src/ArcCommander/APIs/AssayAPI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -372,21 +372,51 @@ module AssayAPI =
investigation
|> Investigation.toFile investigationFilePath

/// Deletes assay folder and underlying file structure of given assay.
/// Deletes an assay's folder and underlying file structure from the ARC.
let delete (arcConfiguration : ArcConfiguration) (assayArgs : Map<string,Argument>) =

let log = Logging.createLogger "AssayDeleteLog"

log.Info("Start Assay Delete")

let assayIdentifier = getFieldValueByName "AssayIdentifier" assayArgs
let isForced = (containsFlag "Force" assayArgs)

let assayFolder =
AssayConfiguration.tryGetFolderPath assayIdentifier arcConfiguration
|> Option.get
let identifier = getFieldValueByName "AssayIdentifier" assayArgs

let assayFolderPath = AssayConfiguration.getFolderPath identifier arcConfiguration

/// Standard files that should be always present in an assay.
let standard = [|
IsaModelConfiguration.getAssayFilePath identifier arcConfiguration
|> Path.truncateFolderPath identifier
yield!
AssayConfiguration.getFilePaths identifier arcConfiguration
|> Array.map (Path.truncateFolderPath identifier)
yield!
AssayConfiguration.getSubFolderPaths identifier arcConfiguration
|> Array.map (
fun p -> Path.Combine(p, ".gitkeep")
>> Path.truncateFolderPath identifier
)
|]

/// Actual files found.
let allFiles =
Directory.GetFiles(assayFolderPath, "*", SearchOption.AllDirectories)
|> Array.map (Path.truncateFolderPath identifier)

/// A check if there are no files in the folder that are not standard.
let isStandard = Array.forall (fun t -> Array.contains t standard) allFiles

match isForced, isStandard with
| true, _
| false, true ->
try Directory.Delete(assayFolderPath, true) with
| err -> log.Error($"Cannot delete assay:\n {err.ToString()}")
| _ ->
log.Error "Assay contains user-specific files. Deletion aborted."
log.Info "Run the command with `--force` to force deletion."

if System.IO.Directory.Exists(assayFolder) then
System.IO.Directory.Delete(assayFolder, true)

/// Remove an assay from the ARC by both unregistering it from the investigation file and removing its folder with the underlying file structure.
let remove (arcConfiguration : ArcConfiguration) (assayArgs : Map<string,Argument>) =
Expand Down
45 changes: 37 additions & 8 deletions src/ArcCommander/APIs/StudyAPI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,9 @@ module StudyAPI =

let studyFilePath = IsaModelConfiguration.getStudyFilePath studyIdentifier arcConfiguration

let studyFolderPath = (Directory.GetParent studyFilePath).FullName

let study = {study with FileName = Some (IsaModelConfiguration.getStudyFileName studyIdentifier arcConfiguration)}

log.Trace "Create study directory and file"


if StudyFolder.exists arcConfiguration studyIdentifier then
log.Error($"Study folder with identifier {studyIdentifier} already exists.")
Expand Down Expand Up @@ -238,19 +235,51 @@ module StudyAPI =
init arcConfiguration studyArgs
register arcConfiguration studyArgs

/// Deletes the study file from the ARC.
/// Deletes a study's folder and underlying file structure from the ARC.
let delete (arcConfiguration : ArcConfiguration) (studyArgs : Map<string,Argument>) =

let log = Logging.createLogger "StudyDeleteLog"

log.Info("Start Study Delete")

let isForced = (containsFlag "Force" studyArgs)

let identifier = getFieldValueByName "Identifier" studyArgs

let studyFilePath = IsaModelConfiguration.getStudyFileName identifier arcConfiguration
let studyFolderPath = StudyConfiguration.getFolderPath identifier arcConfiguration

/// Standard files that should always be present in a study.
let standard = [|
IsaModelConfiguration.getStudyFilePath identifier arcConfiguration
|> Path.truncateFolderPath identifier
yield!
StudyConfiguration.getFilePaths identifier arcConfiguration
|> Array.map (Path.truncateFolderPath identifier)
yield!
StudyConfiguration.getSubFolderPaths identifier arcConfiguration
|> Array.map (
fun p -> Path.Combine(p, ".gitkeep")
>> Path.truncateFolderPath identifier
)
|]

/// Actual files found.
let allFiles =
Directory.GetFiles(studyFolderPath, "*", SearchOption.AllDirectories)
|> Array.map (Path.truncateFolderPath identifier)

/// A check if there are no files in the folder that are not standard.
let isStandard = Array.forall (fun t -> Array.contains t standard) allFiles

try File.Delete studyFilePath with
| err -> log.Error($"Couldn't delete study file:\n {err.ToString()}")
match isForced, isStandard with
| true, _
| false, true ->
try Directory.Delete(studyFolderPath, true) with
| err -> log.Error($"Cannot delete study:\n {err.ToString()}")
| _ ->
log.Error "Study contains user-specific files. Deletion aborted."
log.Info "Run the command with `--force` to force deletion."


/// Unregisters an existing study from the ARC's investigation file.
let unregister (arcConfiguration : ArcConfiguration) (studyArgs : Map<string,Argument>) =
Expand Down Expand Up @@ -779,7 +808,7 @@ module StudyAPI =
| Some publications ->
// TODO : Remove the "Some" when the
match API.Publication.tryGetByDoi doi publications with
| Some publication ->
| Some publication ->
ArgumentProcessing.Prompt.createIsaItemQuery editor
(List.singleton >> Publications.toRows None)
(Publications.fromRows None 1 >> fun (_,_,_,items) -> items.Head)
Expand Down
30 changes: 19 additions & 11 deletions src/ArcCommander/ArcConfiguration.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ type ArcConfiguration =
IsaModel : Map<string,string>
Assay : Map<string,string>
Workflow : Map<string,string>
Study : Map<string,string>
Study : Map<string,string>
Run : Map<string,string>
}

Expand Down Expand Up @@ -118,6 +118,14 @@ type ArcConfiguration =
|]
|> Seq.collect (Map.toSeq >> Seq.map snd)


/// Functions for working with paths.
module Path =

/// Takes a folder's path and returns the part of the path after a name.
let truncateFolderPath (name : string) (folderPath : string) = folderPath.Split name |> Array.last


/// Functions for retrieving general settings from the configuration.
module GeneralConfiguration =

Expand Down Expand Up @@ -211,7 +219,6 @@ module IsaModelConfiguration =
| [|assayIdentifier; fn |] when fn = name -> Some assayIdentifier
| [|assayIdentifier; _ |] -> None
| _ -> None


/// Returns the relative path of the assay file if it exists. Else returns None.
let tryGetAssayFileName assayIdentifier (configuration : ArcConfiguration) =
Expand Down Expand Up @@ -271,12 +278,6 @@ module IsaModelConfiguration =
tryGetStudyFilePath identifier configuration
|> Option.get

/// Returns the full path of the study files located in the arc root folder.
let findStudyFilePaths (configuration : ArcConfiguration) =
let workDir = Map.find "workdir" configuration.General
Directory.GetFiles(workDir)
|> Array.filter (fun s -> s.EndsWith "_isa.study.xlsx")

/// Returns the study identifiers of the study files located in the arc root folder.
let findStudyIdentifiers (configuration : ArcConfiguration) =
let workDir = Map.find "workdir" configuration.General
Expand All @@ -302,6 +303,7 @@ module IsaModelConfiguration =
tryGetInvestigationFilePath configuration
|> Option.get


/// Functions for retrieving Assay related information from the configuration.
module AssayConfiguration =

Expand Down Expand Up @@ -368,6 +370,12 @@ module AssayConfiguration =
/// Functions for retrieving Study related information from the configuration.
module StudyConfiguration =

/// Returns the full path of the study files located in the arc root folder.
let findFilePaths (configuration : ArcConfiguration) =
let workDir = Map.find "workdir" configuration.General
Directory.GetFiles(workDir)
|> Array.filter (fun s -> s.EndsWith "_isa.study.xlsx")

/// Returns the full path of the files associated with the study.
let getFilePaths assayIdentifier configuration =
let workDir = Map.find "workdir" configuration.General
Expand All @@ -379,16 +387,16 @@ module StudyConfiguration =
|> splitValues
|> Array.map (fun v ->
Path.Combine([|workDir; r; assayIdentifier; v|])
)
)
| _ -> [||]

/// Returns the full path of the study folder if it exists. Else returns None.
/// Returns the full path of the study's folder if it exists. Else returns None.
let tryGetFolderPath assayIdentifier configuration =
let workDir = Map.find "workdir" configuration.General
Map.tryFind "rootfolder" configuration.Study
|> Option.map (fun r -> Path.Combine([|workDir; r; assayIdentifier|]))

/// Returns the full path of the study folder.
/// Returns the full path of the study's folder.
let getFolderPath assayIdentifier configuration =
tryGetFolderPath assayIdentifier configuration
|> Option.get
Expand Down
46 changes: 27 additions & 19 deletions src/ArcCommander/CLIArguments/AssayArgs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

open Argu

/// CLI arguments for empty assay initialization
/// CLI arguments for empty assay initialization.
type AssayInitArgs =
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of string
| [<Unique>] MeasurementType of measurement_type : string
Expand All @@ -25,10 +25,18 @@ type AssayInitArgs =
| TechnologyTypeTermSourceREF _ -> "Identifies the controlled vocabulary or ontology that this term comes from. The Source REF has to match one of the Term Source Names declared in the Ontology Source Reference section."
| TechnologyPlatform _ -> "Manufacturer and platform name, e.g. Bruker AVANCE"

/// CLI arguments for deleting assay file structure
type AssayDeleteArgs = AssayInitArgs
/// CLI arguments for deleting assay file structure.
type AssayDeleteArgs =
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of string
| [<Unique>] Force

interface IArgParserTemplate with
member this.Usage =
match this with
| AssayIdentifier _ -> "Identifier of the assay, will be used as name of the root folder of the new assay folder structure"
| Force -> "Forces deletion of all subfolders and -files, no matter if they are user-specific or not"

/// CLI arguments for updating existing assay metadata
/// CLI arguments for updating existing assay metadata.
type AssayUpdateArgs =
| [<AltCommandLine("-s")>][<Unique>] StudyIdentifier of string
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of string
Expand Down Expand Up @@ -57,7 +65,7 @@ type AssayUpdateArgs =
| ReplaceWithEmptyValues _ -> "This flag can be used to delete fields from the assay. If this flag is not set, only these fields for which a value was given will be updated."
| AddIfMissing _ -> "If this flag is set, a new assay will be registered with the given parameters, if it did not previously exist"

/// CLI arguments for interactively editing existing assay metadata
/// CLI arguments for interactively editing existing assay metadata.
type AssayEditArgs =
| [<AltCommandLine("-s")>][<Unique>] StudyIdentifier of study_identifier : string
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of assay_identifier : string
Expand All @@ -68,7 +76,7 @@ type AssayEditArgs =
| StudyIdentifier _ -> "Identifier of the study in which the assay is registered"
| AssayIdentifier _ -> "Identifier of the assay of interest"

/// CLI arguments for registering existing assay metadata
/// CLI arguments for registering existing assay metadata.
type AssayRegisterArgs =
| [<AltCommandLine("-s")>][<Unique>] StudyIdentifier of string
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of string
Expand All @@ -79,10 +87,10 @@ type AssayRegisterArgs =
| StudyIdentifier _ -> "Name of the study in which the assay is situated"
| AssayIdentifier _ -> "Name of the assay of interest"

/// CLI arguments for unregistering existing assay metadata from investigation file
/// CLI arguments for unregistering existing assay metadata from investigation file.
type AssayUnregisterArgs = AssayEditArgs

/// CLI arguments for initializing and subsequently registering assay metadata
/// CLI arguments for initializing and subsequently registering assay metadata.
// Same arguments as `register` because all metadata fields that can be updated can also be set while registering a new assay
type AssayAddArgs =
| [<AltCommandLine("-s")>][<Unique>] StudyIdentifier of string
Expand All @@ -108,10 +116,10 @@ type AssayAddArgs =
| TechnologyTypeTermSourceREF _ -> "Identifies the controlled vocabulary or ontology that this term comes from. The Source REF has to match one of the Term Source Names declared in the Ontology Source Reference section."
| TechnologyPlatform _ -> "Manufacturer and platform name, e.g. Bruker AVANCE"

/// CLI arguments for assay removal
type AssayRemoveArgs = AssayEditArgs
/// CLI arguments for assay removal.
type AssayRemoveArgs = AssayDeleteArgs

/// CLI arguments for assay move between studies
/// CLI arguments for assay move between studies.
type AssayMoveArgs =
| [<Mandatory>][<AltCommandLine("-s")>][<Unique>] StudyIdentifier of study_identifier : string
| [<Mandatory>][<AltCommandLine("-a")>][<Unique>] AssayIdentifier of assay_identifier : string
Expand All @@ -124,10 +132,10 @@ type AssayMoveArgs =
| AssayIdentifier _ -> "Name of the assay of interest"
| TargetStudyIdentifier _ -> "Target study to which the assay should be moved"

/// CLI arguments for getting the values of a specific assay
/// CLI arguments for getting the values of a specific assay.
type AssayShowArgs = AssayEditArgs

/// CLI arguments for exporting a specific assay to json
/// CLI arguments for exporting a specific assay to json.
type AssayExportArgs =
| [<AltCommandLine("-s")>][<Unique>] StudyIdentifier of study_identifier : string
| [<AltCommandLine("-a")>][<Unique>] AssayIdentifier of assay_identifier : string
Expand All @@ -142,10 +150,10 @@ type AssayExportArgs =
| Output _ -> "Path to which the json should be exported. Only written to the cli output if no path given"
| ProcessSequence _ -> "If this flag is set, the return value of this assay will be its list of processes"

/// CLI arguments for assay contacts
/// CLI arguments for assay contacts.
module AssayContacts =

/// CLI arguments for updating existing person metadata
/// CLI arguments for updating existing person metadata.
type PersonUpdateArgs =
| [<Mandatory>][<AltCommandLine("-s")>][<Unique>] AssayIdentifier of string
| [<Mandatory>][<AltCommandLine("-l")>][<Unique>] LastName of last_name : string
Expand Down Expand Up @@ -182,7 +190,7 @@ module AssayContacts =
| ReplaceWithEmptyValues _ -> "This flag can be used to delete fields from the assay. If this flag is not set, only these fields for which a value was given will be updated."
| AddIfMissing _ -> "If this flag is set, a new person will be registered with the given parameters, if it did not previously exist"

/// CLI arguments for interactively editing existing person metadata
/// CLI arguments for interactively editing existing person metadata.
type PersonEditArgs =
| [<Mandatory>][<AltCommandLine("-s")>][<Unique>] StudyIdentifier of string
| [<Mandatory>][<AltCommandLine("-l")>][<Unique>] LastName of last_name : string
Expand All @@ -197,7 +205,7 @@ module AssayContacts =
| FirstName _ -> "The first name of a person associated with the assay"
| MidInitials _ -> "The middle initials of a person associated with the assay"

/// CLI arguments for registering person metadata
/// CLI arguments for registering person metadata.
type PersonRegisterArgs =
| [<Mandatory>][<AltCommandLine("-s")>][<Unique>] AssayIdentifier of string
| [<Mandatory>][<AltCommandLine("-l")>][<Unique>] LastName of last_name : string
Expand Down Expand Up @@ -231,10 +239,10 @@ module AssayContacts =
| RolesTermSourceREF _ -> "Identifies the controlled vocabulary or ontology that this term comes from. The Source REF has to match one of the Term Source Names declared in the Ontology Source Reference section."


/// CLI arguments for person removal
/// CLI arguments for person removal.
// Same arguments as `edit` because all metadata fields needed for identifying the person also have to be used when editing
type PersonUnregisterArgs = PersonEditArgs

/// CLI arguments for getting person
/// CLI arguments for getting person.
// Same arguments as `edit` because all metadata fields needed for identifying the person also have to be used when editing
type PersonShowArgs = PersonEditArgs
Loading

0 comments on commit 9dfc755

Please sign in to comment.