-
Notifications
You must be signed in to change notification settings - Fork 2
/
component_generator.clj
78 lines (71 loc) · 3.74 KB
/
component_generator.clj
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
(ns fix.generator.component-generator
(:require [fix.parser.xml-parser :as parser]
[fix.generator.commons :as c]
[taoensso.timbre :refer [info]]))
(defn- assert-component [component]
{:pre [(= (:tag component) :component)]}
component)
(defn- spit-to-file [component-map]
(let [header '(ns fix.definitions.components)
var `(def ~'components ~component-map)]
(spit "src/fix/definitions/components.clj" header)
(spit "src/fix/definitions/components.clj" "\n\n" :append true)
(spit "src/fix/definitions/components.clj" var :append true)))
(defn- flatten-vec-of-vec [arg]
(if (and (sequential? arg) (= (count arg) 1))
(first arg)
(vec arg)))
(defn- extract-ordering [content all-components]
(->> content
(map (fn [elem]
(let [attrs (:attrs elem)
elem-type (:tag elem)
elem-name (:name attrs)
elem-content (:content elem)
elem-tag (c/get-field-tag-by-name (:name attrs))]
(case elem-type
:field (c/build-field attrs elem-content)
:component {:type :component
:required (c/char->boolean (:required attrs))
:name (keyword elem-name)
:ordering [(extract-ordering (:content (c/get-component-by-name all-components elem-name)) all-components)]}
:group {:type :group
:required (c/char->boolean (:required attrs))
:name (keyword elem-name)
:ordering [{:tag (keyword elem-tag)
:required (c/char->boolean (:required attrs))
:type :field}
(extract-ordering elem-content all-components)]}
(throw (IllegalArgumentException. (str "Wrong input: component contains unknown type:" elem-type)))))))
flatten-vec-of-vec))
(defn- extract-definition [content all-components]
(->> content
(map (fn [elem]
(let [attrs (:attrs elem)
elem-type (:tag elem)
elem-name (:name attrs)
elem-content (:content elem)
elem-tag (c/get-field-tag-by-name (:name attrs))]
(case elem-type
:field (c/get-field-tag-by-name (:name attrs))
:component [(extract-definition (:content (c/get-component-by-name all-components elem-name)) all-components)]
:group [(keyword elem-tag)
(extract-definition elem-content all-components)]
(throw (IllegalArgumentException. (str "Wrong input: component contains unknown type:" elem-type)))))))
flatten))
(defn- generate-source-file [components]
(info "Number of components found:" (count components))
(let [gen-components (map
(fn [component]
(assert-component component)
(let [name (get-in component [:attrs :name])
definition (extract-definition (:content component) components)
ordering (extract-ordering (:content component) components)]
{(keyword name) {:ordering ordering
:definition (into #{} definition)}}))
components)]
(spit-to-file (apply merge gen-components))))
(defn -main [& _]
(info "Generating FIX5.0 SP2 COMPONENT sources ... !")
(let [[_ components _] (parser/parse "resources/FIX50SP2_FIXT11_combined.xml")]
(generate-source-file components)))