aboutsummaryrefslogtreecommitdiff
path: root/lib/configuration/of_json.ml
blob: f9171b93dec8b9bfd19b2b1e16d65672578da18e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
open StdLabels
module Table = ImportDataTypes.Table
module Path = ImportDataTypes.Path
module Expression = ImportExpression.T

open Ppx_yojson_conv_lib.Yojson_conv.Primitives

let current_syntax = 1

let rec expression_of_yojson :
    (Yojson.Safe.t -> 'a) -> Yojson.Safe.t -> 'a Expression.t =
 fun f expr ->
  match expr with
  | `Null -> Empty
  | `List l -> Concat (List.map ~f:(expression_of_yojson f) l)
  | `String s as json -> (
      try Path (f json) with
      | _ -> Literal s)
  | `Assoc [ (fn, `List [ `List l1; `List l2 ]) ]
    when String.equal "counter" (String.lowercase_ascii fn) ->
      Window
        ( Expression.Counter,
          List.map ~f:(expression_of_yojson f) l1,
          List.map ~f:(expression_of_yojson f) l2 )
  | `Assoc [ (fn, `List [ expr1; `List l2; `List l3 ]) ]
    when String.equal "previous" (String.lowercase_ascii fn) ->
      Window
        ( Expression.Previous (expression_of_yojson f expr1),
          List.map ~f:(expression_of_yojson f) l2,
          List.map ~f:(expression_of_yojson f) l3 )
  | `Assoc [ (fn, `List l) ] when String.equal "nvl" (String.lowercase_ascii fn)
    -> Nvl (List.map ~f:(expression_of_yojson f) l)
  | `Assoc [ (fn, `List l) ] ->
      Function
        (String.lowercase_ascii fn, List.map ~f:(expression_of_yojson f) l)
  | json -> (
      try Path (f json) with
      | _ ->
          let str_json = Yojson.Safe.pretty_to_string json in
          raise
            (ImportErrors.JsonError { json = str_json; element = "Expression" })
      )

type 'a expression = 'a Expression.t
type column = Path.column

let column_of_yojson : Yojson.Safe.t -> int = function
  | `Int i -> i
  | `String s -> ImportCSV.Csv.column_of_string s
  | _ -> raise (Invalid_argument "column")

let yojson_of_column i = `String (ImportCSV.Csv.column_to_string i)

type path = Syntax.Path.t = {
  alias : string option; [@default None] [@yojson_drop_default ( = )]
  (* External file to load, when the information is missing, load in
          the current file *)
  column : column;
}
[@@deriving of_yojson]

let path_of_yojson : Yojson.Safe.t -> path = function
  | `String s ->
      Scanf.sscanf s ":%s@.%s" (fun table column ->
          if String.equal column "" then
            { alias = None; column = ImportCSV.Csv.column_of_string table }
          else
            {
              alias = Some table;
              column = ImportCSV.Csv.column_of_string column;
            })
  | other -> path_of_yojson other

let yojson_of_path : path -> Yojson.Safe.t =
 fun { alias; column } ->
  let table =
    match alias with
    | None -> ""
    | Some table -> String.cat table "."
  in

  `String
    (String.concat ~sep:""
       [ ":"; table; ImportCSV.Csv.column_to_string column ])

type table = Table.t = {
  file : string;
  tab : int; [@default 1] [@yojson_drop_default ( = )]
  name : string;
}
[@@deriving of_yojson]

type extern = {
  source : string option; [@default None] [@yojson_drop_default ( = )]
  intern_key : column expression;
  target : table;
  extern_key : column expression;
  allow_missing : bool; [@default false] [@yojson_drop_default ( = )]
  match_rule : string option; [@default None] [@yojson_drop_default ( = )]
}
[@@deriving of_yojson]

type syntax_v1_extern = Syntax.extern

let syntax_v1_extern_of_yojson yojson =
  let e = extern_of_yojson yojson in
  let intern_key : path Expression.t =
    Expression.map e.intern_key ~f:(fun column ->
        Syntax.Path.{ column; alias = e.source })
  in
  Syntax.
    {
      extern_key = e.extern_key;
      intern_key;
      target = e.target;
      allow_missing = e.allow_missing;
      match_rule = e.match_rule;
    }

type predicate = unit

let predicate_of_yojson _ = ()
let yojson_of_predicate () = `Null

type t = Syntax.t = {
  version : int; [@default current_syntax]
  source : table;
  externals : syntax_v1_extern list; [@default []]
  columns : path expression list;
  filters : path expression list; [@default []] [@yojson_drop_default ( = )]
  sort : path expression list; [@default []] [@yojson_drop_default ( = )]
  uniq : path expression list; [@default []] [@yojson_drop_default ( = )]
}
[@@deriving of_yojson]