diff --git a/src/CWL/ARCtrl.CWL.fsproj b/src/CWL/ARCtrl.CWL.fsproj
index b709cf8c..6db6da17 100644
--- a/src/CWL/ARCtrl.CWL.fsproj
+++ b/src/CWL/ARCtrl.CWL.fsproj
@@ -8,6 +8,30 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nfdi4plants
+ ARC helper functions for Common workflow language.
+ MIT
+ logo.png
+ ARC F# FSharp dotnet .Net bioinformatics biology fable-library datascience dataplant nfdi metadata
+ https://github.com/nfdi4plants/ARCtrl/tree/main/src/CWL
+ https://github.com/nfdi4plants/ARCtrl
+ git
+
diff --git a/src/CWL/Decode.fs b/src/CWL/Decode.fs
new file mode 100644
index 00000000..5f494a0b
--- /dev/null
+++ b/src/CWL/Decode.fs
@@ -0,0 +1,185 @@
+namespace ARCtrl.CWL
+
+open YAMLicious
+
+module Decode =
+
+ let outputBindingGlobDecoder: (YAMLiciousTypes.YAMLElement -> OutputBinding) =
+ Decode.object (fun get ->
+ let glob = get.Optional.Field "glob" Decode.string
+ { Glob = glob }
+ )
+
+ let outputBindingDecoder: (YAMLiciousTypes.YAMLElement -> OutputBinding) =
+ Decode.object(fun get ->
+ let outputBinding = get.Required.Field "outputBinding" outputBindingGlobDecoder
+ outputBinding
+ )
+
+ let cwlArrayTypeDecoder: (YAMLiciousTypes.YAMLElement -> CWLType) =
+ Decode.object (fun get ->
+ let items = get.Required.Field "items" Decode.string
+ match items with
+ | "File" -> Array (File (FileInstance ()))
+ | "Directory" -> Array (Directory (DirectoryInstance ()))
+ | "Dirent" -> Array (Dirent { Entry = ""; Entryname = None; Writable = None })
+ | "string" -> Array String
+ | "int" -> Array Int
+ | "long" -> Array Long
+ | "float" -> Array Float
+ | "double" -> Array Double
+ | "boolean" -> Array Boolean
+ | _ -> failwith "Invalid CWL type"
+ )
+
+ let cwlTypeDecoder: (YAMLiciousTypes.YAMLElement -> CWLType) =
+ Decode.object (fun get ->
+ let cwlType =
+ get.Required.Field
+ "type"
+ (
+ fun value ->
+ match value with
+ | YAMLElement.Value v | YAMLElement.Object [YAMLElement.Value v] -> Some v.Value
+ | YAMLElement.Object o -> None
+ | _ -> failwith "Unexpected YAMLElement"
+ )
+ match cwlType with
+ | Some t ->
+ match t with
+ | "File" -> File (FileInstance ())
+ | "Directory" -> Directory (DirectoryInstance ())
+ | "Dirent" -> Dirent { Entry = ""; Entryname = None; Writable = None }
+ | "string" -> String
+ | "int" -> Int
+ | "long" -> Long
+ | "float" -> Float
+ | "double" -> Double
+ | "boolean" -> Boolean
+ | "File[]" -> Array (File (FileInstance ()))
+ | "Directory[]" -> Array (Directory (DirectoryInstance ()))
+ | "Dirent[]" -> Array (Dirent { Entry = ""; Entryname = None; Writable = None })
+ | "string[]" -> Array String
+ | "int[]" -> Array Int
+ | "long[]" -> Array Long
+ | "float[]" -> Array Float
+ | "double[]" -> Array Double
+ | "boolean[]" -> Array Boolean
+ | "stdout" -> Stdout
+ | "null" -> Null
+ | _ -> failwith "Invalid CWL type"
+ | None ->
+ let cwlTypeArray = get.Required.Field "type" cwlArrayTypeDecoder
+ cwlTypeArray
+ )
+
+ let outputArrayDecoder: (YAMLiciousTypes.YAMLElement -> Output[]) =
+ Decode.object (fun get ->
+ let dict = get.Overflow.FieldList []
+ [|
+ for key in dict.Keys do
+ let value = dict.[key]
+ let outputBinding = outputBindingDecoder value
+ let cwlType = cwlTypeDecoder value
+ { Name = key; Type = cwlType; OutputBinding = Some outputBinding }
+ |]
+ )
+
+ let outputsDecoder: (YAMLiciousTypes.YAMLElement -> Output[]) =
+ Decode.object (fun get ->
+ let outputs = get.Required.Field "outputs" outputArrayDecoder
+ outputs
+ )
+
+ let requirementArrayDecoder: (YAMLiciousTypes.YAMLElement -> Requirement[]) =
+ Decode.array
+ (
+ Decode.object (fun get ->
+ let cls = get.Required.Field "class" Decode.string
+ match cls with
+ | "InlineJavascriptRequirement" -> InlineJavascriptRequirement
+ | "SchemaDefRequirement" -> SchemaDefRequirement [||]
+ | "DockerRequirement" ->
+ let dockerReq = {
+ DockerPull = get.Optional.Field "dockerPull" Decode.string
+ DockerFile = Some ""
+ DockerImageId = get.Optional.Field "dockerImageId" Decode.string
+ }
+ DockerRequirement dockerReq
+ | "SoftwareRequirement" -> SoftwareRequirement [||]
+ | "InitialWorkDirRequirement" -> InitialWorkDirRequirement [||]
+ | "EnvVarRequirement" -> EnvVarRequirement {EnvName = ""; EnvValue = ""}
+ | "ShellCommandRequirement" -> ShellCommandRequirement
+ | "ResourceRequirement" -> ResourceRequirement (ResourceRequirementInstance())
+ | "NetworkAccess" -> NetworkAccessRequirement
+
+ )
+ )
+
+ let requirementsDecoder: (YAMLiciousTypes.YAMLElement -> Requirement[]) =
+ Decode.object (fun get ->
+ let requirements = get.Required.Field "requirements" requirementArrayDecoder
+ requirements
+ )
+
+ let hintsDecoder: (YAMLiciousTypes.YAMLElement -> Requirement[]) =
+ Decode.object (fun get ->
+ let requirements = get.Required.Field "hints" requirementArrayDecoder
+ requirements
+ )
+
+ let inputBindingDecoder: (YAMLiciousTypes.YAMLElement -> InputBinding option) =
+ Decode.object(fun get ->
+ let outputBinding =
+ get.Optional.Field
+ "inputBinding"
+ (
+ Decode.object (fun get' ->
+ {
+ Prefix = get'.Optional.Field "prefix" Decode.string
+ Position = get'.Optional.Field "position" Decode.int
+ ItemSeparator = get'.Optional.Field "itemSeparator" Decode.string
+ Separate = get'.Optional.Field "separate" Decode.bool
+ }
+ )
+ )
+ outputBinding
+ )
+
+ let inputArrayDecoder: (YAMLiciousTypes.YAMLElement -> Input[]) =
+ Decode.object (fun get ->
+ let dict = get.Overflow.FieldList []
+ [|
+ for key in dict.Keys do
+ let value = dict.[key]
+ let inputBinding = inputBindingDecoder value
+ let cwlType = cwlTypeDecoder value
+ { Name = key; Type = cwlType; InputBinding = inputBinding }
+ |]
+ )
+
+ let inputsDecoder: (YAMLiciousTypes.YAMLElement -> Input[]) =
+ Decode.object (fun get ->
+ let outputs = get.Required.Field "inputs" inputArrayDecoder
+ outputs
+ )
+
+ let decodeAll =
+ let yamlCWL = Decode.read exampleCWL
+ CWL(
+ cwlVersion = Decode.object (fun get -> get.Required.Field "cwlVersion" Decode.string) yamlCWL,
+ cls =
+ Decode.object (fun get ->
+ match get.Required.Field "class" Decode.string with
+ | "Workflow" -> Workflow
+ | "CommandLineTool" -> CommandLineTool
+ | "ExpressionTool" -> ExpressionTool
+ | _ -> failwith "Invalid class"
+ ) yamlCWL
+ ,
+ outputs = outputsDecoder yamlCWL,
+ inputs = inputsDecoder yamlCWL,
+ //baseCommand = Decode.object (fun get -> get.Optional.Field "baseCommand" (Decode.array Decode.string)) yamlCWL,
+ requirements = requirementsDecoder yamlCWL,
+ hints = hintsDecoder yamlCWL
+ )
\ No newline at end of file
diff --git a/src/CWL/Encode.fs b/src/CWL/Encode.fs
new file mode 100644
index 00000000..e69de29b