-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6e82589
commit a782b3e
Showing
5 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
(ns python-generator.profile-extractor | ||
(:require [cheshire.core] [clojure.string :as str])) | ||
|
||
|
||
(defn filter-base [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(not (and (contains? % :from) (contains? % :to)))) | ||
(filter #(not (contains? % :derivation))) | ||
(filter #(not (contains? % :base))) | ||
(filter #(contains? % :elements)) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc {} :base) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
(defn filter-element [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(str/includes? (or (:base %) "") "Element")) | ||
(filter #(not (str/includes? (or (:base %) "") "BackboneElement"))) | ||
(filter #(not (str/includes? (or (:base %) "") "ElementDefinition"))) | ||
(filter #(contains? % :elements)) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc (reduce-keys :accumulator) :element) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
(defn filter-backbone-element [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(str/includes? (or (:base %) "") "/BackboneElement")) | ||
(filter #(= "specialization" (:derivation %))) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc (reduce-keys :accumulator) :backbone-element) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
(defn filter-domain-resource [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(str/includes? (or (:base %) "") "/DomainResource")) | ||
(filter #(= "specialization" (:derivation %))) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc (reduce-keys :accumulator) :domain-resource) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
(defn filter-resource [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(str/includes? (or (:base %) "") "/Resource")) | ||
(filter #(= "specialization" (:derivation %))) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc (reduce-keys :accumulator) :resource) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
(defn filter-constraint [reduce-keys] | ||
(->> (reduce-keys :structures) | ||
(filter #(= "constraint" (:derivation %))) | ||
(filter #(not (= "hl7.fhir.r4.core#4.0.1/Extension" (:base %)))) | ||
(map (fn [item] [(item :fqn) item])) | ||
(into {}) | ||
(assoc (reduce-keys :accumulator) :constraint) | ||
(hash-map :structures (reduce-keys :structures) :accumulator))) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
(ns python-generator.profile-helpers | ||
(:require | ||
[python-generator.extractor] | ||
[cheshire.core] | ||
[taoensso.nippy :as nippy] | ||
[clojure.java.io :as io] | ||
[clojure.string :as str])) | ||
|
||
|
||
;; TODO: do not hardcode | ||
(def elements #{"HumanName" "Signature" "Range" "Coding" "Attachment" "BackboneElement" "Address" "Money" "Period" "Expression" "TriggerDefinition" "Contributor" "Identifier" "Extension" "Quantity" "RelatedArtifact" "Ratio" "UsageContext" "ContactPoint" "Narrative" "Meta" "SampledData" "Annotation" "Reference" "CodeableConcept" "ContactDetail" "ParameterDefinition" "DataRequirement"}) | ||
(def backbone-elements #{"Population" "Timing" "MarketingStatus" "SubstanceAmount" "ProductShelfLife" "ProdCharacteristic" "Dosage" "ElementDefinition"}) | ||
(def primitives-string #{"dateTime" "xhtml" "Distance" "time" "date" "string" "uuid" "oid" "id" "Dosage" "Duration" "instant" "Count" "decimal" "code" "base64Binary" "unsignedInt" "url" "markdown" "uri" "positiveInt" "canonical" "Age" "Timing"}) | ||
|
||
(defn uppercase-first-letter [string] | ||
(str (str/upper-case (first string)) (subs string 1))) | ||
|
||
(defn escape-keyword [word] | ||
(if (.contains #{"class", "from", "assert", "global", "for", "import"} word) (str word "_") word)) | ||
|
||
(defn string-interpolation [left, right, string] | ||
(str left, string, right)) | ||
|
||
(defn wrap-vector [string] | ||
(string-interpolation "list[", "]", string)) | ||
|
||
(defn wrap-optional [string] | ||
(string-interpolation "Optional[", "]", string)) | ||
|
||
(defn get-resource-name [reference] | ||
(last (str/split (str reference) #"/"))) | ||
|
||
(defn get-type [name type] | ||
(cond | ||
(= type "BackboneElement") (str "" (uppercase-first-letter name)) | ||
(= type "boolean") "bool" | ||
(= type "integer") "int" | ||
(= type "") "str" | ||
(.contains primitives-string type) "str" | ||
:else (or type "str"))) | ||
|
||
(defn derive-basic-type [name element] | ||
(get-type name (get-resource-name (:type element)))) | ||
|
||
(defn append-default-none [string] (str string " = None")) | ||
(defn append-default-vector [string] (str string " = []")) | ||
|
||
(defn transform-element [name element required] | ||
(->> (derive-basic-type name element) | ||
((if (:array element) wrap-vector str)) | ||
((if (and (not required) (not (:array element))) wrap-optional str)) | ||
((if (and (not required) (not (:array element))) append-default-none str)) | ||
((if (and (not required) (:array element)) append-default-vector str)))) | ||
|
||
(defn elements-to-vector [definition] | ||
(->> (seq (:elements definition)) | ||
(filter (fn [[_, v]] (not (contains? v :choices)))))) | ||
|
||
(defn get-parent [base-reference] | ||
(->> (get-resource-name base-reference) | ||
(string-interpolation "(" ")"))) | ||
|
||
(defn collect-types [parent_name, required, [k, v]] | ||
(hash-map :name (escape-keyword (name k)) :base parent_name :value (transform-element (str parent_name "_" (uppercase-first-letter (name k))) v (.contains required (name k))))) | ||
|
||
(defn resolve-backbone-elements [[k, v]] | ||
(if (= (get-resource-name (:type v)) "BackboneElement") (vector k, v) (vector))) | ||
|
||
(defn get-typings-and-imports [parent_name, required, data] | ||
(reduce (fn [acc, item] | ||
(hash-map :elements (conj (:elements acc) (collect-types parent_name required item)) | ||
:backbone-elements (conj (:backbone-elements acc) (resolve-backbone-elements item)))) | ||
(hash-map :elements [] :backbone-elements []) data)) | ||
|
||
(defn parse-ndjson-gz [path] | ||
(with-open [rdr (-> path | ||
(io/input-stream) | ||
(java.util.zip.GZIPInputStream.) | ||
(io/reader))] | ||
(->> rdr | ||
line-seq | ||
(mapv (fn [json-row] | ||
(cheshire.core/parse-string json-row keyword)))))) | ||
|
||
(defn parse-nippy [path] | ||
(->> (io/file path) | ||
(nippy/thaw-from-file))) | ||
|
||
(defn side-effect-map [method, list] (doall (map method list))) | ||
|
||
(defn create-on-missing [dir] | ||
(when-not (.exists (io/file dir)) (.mkdir (io/file dir)))) | ||
|
||
(defn write-to-file [directory, filename, text] | ||
(create-on-missing directory) | ||
(with-open [writer (io/writer (io/file directory (str filename ".py")))] (.write writer text))) | ||
|
||
;; (get-resource-name filename) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
(ns python-generator.profile-parser | ||
(:require | ||
[python-generator.profile-extractor :as ext] | ||
[python-generator.profile-helpers :as help] | ||
[python-generator.profile-resources :as gen] | ||
[cheshire.core] | ||
[clojure.string :as str])) | ||
|
||
;; (str parent_name "_" (help/uppercase-first-letter (name property_name))) | ||
|
||
(defn compile-backbone [parent_name property_name definition] | ||
(let [name "NaMe" | ||
data (help/get-typings-and-imports name (or (:required definition) []) (help/elements-to-vector definition)) | ||
backbone-elements (filter (fn [item] (> (count item) 0)) (:backbone-elements data))] | ||
(conj data (hash-map :backbone-elements (if (= (count backbone-elements) 0) [] (map (fn [[k, v]] (compile-backbone name k v)) backbone-elements)))))) | ||
|
||
(defn test [name data] | ||
(->> (filter (fn [item] (> (count item) 0)) (:backbone-elements data)) | ||
(map (fn [[k, v]] (compile-backbone name k v))) | ||
(hash-map :backbone-elements) | ||
(conj data))) | ||
|
||
|
||
|
||
;; (helpers/get-resource-name (:type definition)) | ||
|
||
(defn attach-parent-data [parent a context child] | ||
(if (nil? parent) child (conj child (hash-map :elements (concat (get-in context [:classes parent a :elements]) (:elements child)))))) | ||
|
||
(defn compile-elements [property parent context] | ||
(->> (map (fn [[name definition]] | ||
(->> (help/elements-to-vector definition) | ||
(help/get-typings-and-imports (:type definition) (or (:required definition) [])) | ||
(test "ktulh-ftagn") | ||
(attach-parent-data parent (:base definition) context) | ||
(conj (hash-map :name name :source (:base definition))) | ||
(hash-map name))) (property (:accumulator context))) | ||
#_(apply merge))) | ||
|
||
|
||
(defn group-by [ig] | ||
(->> (ext/filter-base ig) | ||
(ext/filter-element) | ||
(ext/filter-resource) | ||
(ext/filter-backbone-element) | ||
(ext/filter-domain-resource) | ||
(ext/filter-constraint))) | ||
|
||
(defn c-base [context] | ||
(->> context | ||
(compile-elements :base nil) | ||
(hash-map :base) | ||
(hash-map :classes) | ||
(conj context))) | ||
|
||
(defn c-resource [context] | ||
(->> context | ||
(compile-elements :resource :base) | ||
(hash-map :resource) | ||
(conj (:classes context)) | ||
(hash-map :classes) | ||
(conj context))) | ||
|
||
(defn c-domain-resource [context] | ||
(->> context | ||
(compile-elements :domain-resource :resource) | ||
(hash-map :domain-resource) | ||
(conj (:classes context)) | ||
(hash-map :classes) | ||
(conj context))) | ||
|
||
(defn c-constraint [context] | ||
(->> context | ||
(compile-elements :constraint :domain-resource) | ||
(hash-map :constraint) | ||
(conj (:classes context)) | ||
(hash-map :classes) | ||
(conj context))) | ||
|
||
(defn compile [context] | ||
(->> context | ||
(c-base) | ||
(c-resource) | ||
(c-domain-resource) | ||
(c-constraint))) | ||
|
||
(defn compile-profiles [] | ||
(->> (hash-map :structures (help/parse-ndjson-gz "/Users/gena.razmakhnin/Documents/aidbox-sdk-js/fhir-schema/hl7.fhir.r4.core#4.0.1/package.ndjson.gz")) | ||
(group-by) | ||
(compile) | ||
(:classes) | ||
(:domain-resource))) | ||
|
||
(compile-profiles) | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
;; (filter (fn [item] (:elements item)) [{:elements {:a {:type 1} :b {:type 2} :c {:type 2}}}]) | ||
|
||
#_(->> (helpers/parse-ndjson-gz "/Users/gena.razmakhnin/Documents/aidbox-python-tooklit/fhir-schema/hl7.fhir.r4.core#4.0.1_package.ndjson.gz") | ||
(filter #(= "constraint" (:derivation %))) | ||
(filter (fn [item] ())) | ||
(filter (fn [item] | ||
(some | ||
(fn [[_ value]] (and (= "hl7.fhir.r4.core#4.0.1/CodeableConcept" (:type value)) (contains? value :binding))) | ||
(:elements item))))) | ||
|
||
;; (map (fn [[key value]] key) {"hello" 3 "hello2" 3}) | ||
;; (type (hash-map "hello" 3 "hello2" 3)) | ||
;; ((hash-map "hello" 1 "hello2" 2) "hello2") | ||
|
||
#_(->> (helpers/parse-nippy "/Users/gena.razmakhnin/Documents/aidbox-python-tooklit/fhir-schema/hl7.fhir.r4.core#4.0.1_terminology-index.nippy") | ||
#_(:valuesets) | ||
(:codesystems) | ||
#_(map (fn [[key value]] value)) | ||
#_(filter (fn [[key value]] (= key "http://terminology.hl7.org/CodeSystem/v2-0334"))) | ||
((fn [map] (map "http://loinc.org")))) | ||
|
||
;; (map (fn [item] (print item))) | ||
;; (keyword "http://hl7.org/fhir/supplydelivery-status") | ||
;; (keyword "http://hl7.org/fhir/ValueSet/ldlcholesterol-codes") | ||
|
||
|
||
;; :fhirVersions ["4.0.1"] | ||
;; :name "hl7.fhir.r4.core" | ||
;; :type "fhir.core" | ||
;; :version "4.0.1" | ||
;; :dependencies [] | ||
|
||
;; :fhirVersions ["4.0.1"] | ||
;; :name "hl7.fhir.us.core" | ||
;; :type "IG" | ||
;; :version "5.0.1" | ||
;; :dependencies [":hl7.fhir.r4.core#4.0.1" ":hl7.terminology.r4#3.1.0" ":hl7.fhir.uv.bulkdata#2.0.0" ":hl7.fhir.uv.smart-app-launch#2.0.0" ":us.nlm.vsac#0.7.0" ":hl7.fhir.uv.sdc#3.0.0"] | ||
|
||
;; :fhirVersions ["4.0.1"] | ||
;; :name "hl7.fhir.us.mcode" | ||
;; :type "IG" | ||
;; :version "3.0.0" | ||
;; :dependencies [":hl7.fhir.r4.core#4.0.1" ":hl7.terminology.r4#5.3.0" ":hl7.fhir.us.core#5.0.1" ":hl7.fhir.uv.genomics-reporting#2.0.0" ":hl7.fhir.uv.extensions#1.0.0"] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
(ns python-generator.profile-resources | ||
(:require | ||
[cheshire.core] | ||
[clojure.string :as str] | ||
[python-generator.extractor :as extractors] | ||
[python-generator.profile-helpers :as help])) | ||
|
||
(defn filter-backbone-elements [data] | ||
(filter (fn [item] (> (count item) 0)) (:backbone-elements data))) | ||
|
||
(defn compile-backbone [parent_name property_name definition] | ||
(let [name (str parent_name "_" (help/uppercase-first-letter (name property_name))) | ||
data (help/get-typings-and-imports name (or (:required definition) []) (help/elements-to-vector definition)) | ||
backbone-elements (filter-backbone-elements data)] | ||
(->> (str (clojure.string/join "\n" (:elements data)) "\n\n") | ||
(str "class " name "(BackboneElement):\n") | ||
(str (if (= (count backbone-elements) 0) (str) (str/join (map (fn [[k, v]] (str (compile-backbone name k v))) backbone-elements))))))) | ||
|
||
(defn test [name data] | ||
(->> (filter (fn [item] (> (count item) 0)) (:backbone-elements data)) | ||
(map (fn [[k, v]] (str (compile-backbone name k v)))) | ||
(str/join))) | ||
|
||
(defn combine-file [definition, data] | ||
(->> (str (clojure.string/join "\n" (:elements data)) "\n\n") | ||
(str "class " (help/get-resource-name (:type definition)) (help/get-parent (:base definition)) ":\n") | ||
#_(str (test (help/get-resource-name (:type definition)) data)) | ||
#_(str "from ..base import *\n\n") | ||
#_(str "from typing import Optional\n"))) | ||
|
||
(defn compile-single-class [directory] | ||
(fn [[_ definition]] | ||
(->> (help/elements-to-vector definition) | ||
(help/get-typings-and-imports (help/get-resource-name (:type definition)) (or (:required definition) [])) | ||
#_(combine-file definition) | ||
#_(str/join)))) | ||
|