Skip to content

Commit

Permalink
Make adlc term_binding injector generic.
Browse files Browse the repository at this point in the history
TODO: read in code_systems file.
  • Loading branch information
wolandscat committed May 14, 2024
1 parent b790e42 commit f7b187c
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 66 deletions.
109 changes: 64 additions & 45 deletions apps/adlc/src/main/application.e
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,35 @@ note
adlc [-q] -b <library name> -l [<id_pattern>]
adlc [-q] -b <library name> -d [<id_pattern>]
adlc [-q] -b <library name> [-f <format>] --report [-o <output_dir>]
adlc [-q] -b <library name> --inject_loinc -i <loinc_file>
adlc [-q] -b <library name> --inject_term_bindings <terminology_namespace> -i <terms_file>
adlc [-q] -b <library name> [--flat] [--cfg <file path>] [-f <format>] -a <action> [-o <output_dir>] [<id_pattern>]
OPTIONS:
Options should be prefixed with: '-' or '/'
-q --quiet : suppress verbose feedback, including configuration information on startup (Optional)
--flat : use flat form of archetype[s] for actions, e.g. path extraction etc (Optional)
-s --show_config : show current configuration and defaults
-L --list_rms : generate list of reference models.
-D --display_rms : generate view of reference models user-friendly format
-X --export_rms : export reference models in all available formats (JSON, ODIN, etc)
-l --list_archetypes : generate list of archetypes in current library (use for further processing)
-d --display_archetypes: generate list of archetypes in current library in user-friendly format
-b --library : library to use
<library name>: library name
-f --format : output format for generated files (Optional)
<format>: file formats: json|adl|odin|yaml|xml|csv (default = adl or csv)
--cfg : output default configuration file location (Optional)
<file path>: .cfg file path
-x --export : export matching archetypes in specified format
-r --report : generate reports in specified format
-o --output : output directory to write files to; '.' for current directory
--inject_loinc : read <loinc_file>, which is formatted as {archetype_id,id_code,loinc_code} and
inject bindings from loinc codes to id-codes
-q --quiet : suppress verbose feedback, including configuration information on startup (Optional)
--flat : use flat form of archetype[s] for actions, e.g. path extraction etc (Optional)
-s --show_config : show current configuration and defaults
-L --list_rms : generate list of reference models.
-D --display_rms : generate view of reference models user-friendly format
-X --export_rms : export reference models in all available formats (JSON, ODIN, etc)
-l --list_archetypes : generate list of archetypes in current library (use for further processing)
-d --display_archetypes : generate list of archetypes in current library in user-friendly format
-b --library : library to use
<library name>: library name
-f --format : output format for generated files (Optional)
<format>: file formats: json|adl|odin|yaml|xml|csv (default = adl or csv)
--cfg : output default configuration file location (Optional)
<file path>: .cfg file path
-x --export : export matching archetypes in specified format
-r --report : generate reports in specified format
-o --output : output directory to write files to; '.' for current directory
--inject_term_bindings: read <loinc_file>, which is formatted as {archetype_id,archetype_code,term_code} and
inject bindings from loinc codes to id-codes
-? --help : Display usage information. (Optional)
-? --help : Display usage information. (Optional)
NON-SWITCHED ARGUMENTS:
<id_pattern>: archetype id regex
Expand Down Expand Up @@ -174,8 +174,12 @@ feature -- Commands
elseif opts.report then
generate_library_reports

elseif opts.inject_loinc_bindings then
inject_loinc_bindings
elseif opts.inject_term_bindings and then attached opts.term_bindings_namespace as term_ns then
if code_systems.has (term_ns) then
inject_term_bindings (term_ns)
else
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_terminology_does_not_exist_err, <<term_ns>>))
end
end
end
end
Expand Down Expand Up @@ -275,18 +279,30 @@ feature -- Commands
end
end

Loinc_uri_root: STRING = "http://loinc.org/"
code_systems: HASH_TABLE[STRING, STRING]
-- TODO: for now, a static copy of the file
once
create Result.make(0)
Result.put ("http://loinc.org/", "loinc")
Result.put ("http://snomed.info/id/", "snomed")
Result.put ("http://s2health.org/id/", "s2")
Result.put ("http://openehr.org/id/", "openehr")
Result.put ("http://ucum.org/id/", "ucum")
Result.put ("http://www.nlm.nih.gov/research/umls/rxnorm/", "rxnorm")
end

inject_loinc_bindings
-- Inject LOINC bindings from a file whose structure is
-- {archetype_id,node_id,loinc_code}
inject_term_bindings (term_binding_ns: STRING)
-- Inject terminology bindings from a file whose structure is
-- {archetype_id,node_id,raw_code}
require
code_systems.has (term_binding_ns)
local
last_arch_id, input_file_path: STRING
in_file: PLAIN_TEXT_FILE
a_line, arch_id, id_code, loinc_code: STRING
a_line, arch_id, arch_code, term_code, term_binding_uri_root: STRING
strs: LIST[STRING]
ara: ARCH_LIB_AUTHORED_ARCHETYPE
old_loinc_binding_uri, binding_uri: URI
old_term_binding_uri, binding_uri: URI
diff_arch: AUTHORED_ARCHETYPE
arch_count, inject_new_count, inject_replace_count, inject_ignore_count: INTEGER
save_required: BOOLEAN
Expand All @@ -304,12 +320,15 @@ feature -- Commands
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_invalid_input_file, <<input_file_path>>))
end

report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_loinc_start, <<input_file_path>>))
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_term_bindings_start, <<term_binding_ns, input_file_path>>))

create in_file.make(input_file_path)

create last_arch_id.make_empty
if in_file.exists then
check attached code_systems.item(term_binding_ns) as uri_root then
term_binding_uri_root := uri_root
end
in_file.open_read
from until in_file.end_of_file loop
in_file.read_line
Expand Down Expand Up @@ -344,36 +363,36 @@ feature -- Commands
end

if attached diff_arch then
id_code := strs.i_th (2)
loinc_code := strs.i_th (3)
arch_code := strs.i_th (2)
term_code := strs.i_th (3)

-- now process all the codes for this archetype
create binding_uri.make_from_string (Loinc_uri_root + loinc_code)
if diff_arch.terminology.has_term_binding ({OPENEHR_DEFINITIONS}.Loinc_terminology_id, id_code) then
old_loinc_binding_uri := diff_arch.terminology.term_binding ({OPENEHR_DEFINITIONS}.Loinc_terminology_id, id_code)
if not old_loinc_binding_uri.is_equal(binding_uri) then
diff_arch.terminology.replace_term_binding (binding_uri, {OPENEHR_DEFINITIONS}.Loinc_terminology_id, id_code)
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_loinc_replace_binding, <<{OPENEHR_DEFINITIONS}.Loinc_terminology_id,
old_loinc_binding_uri.as_string, id_code, binding_uri.as_string, arch_id>>))
create binding_uri.make_from_string (term_binding_uri_root + term_code)
if diff_arch.terminology.has_term_binding (term_binding_ns, arch_code) then
old_term_binding_uri := diff_arch.terminology.term_binding (term_binding_ns, arch_code)
if not old_term_binding_uri.is_equal(binding_uri) then
diff_arch.terminology.replace_term_binding (binding_uri, term_binding_ns, arch_code)
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_replace_term_binding, <<term_binding_ns,
old_term_binding_uri.as_string, arch_code, binding_uri.as_string, arch_id>>))
inject_replace_count := inject_replace_count + 1
save_required := True
else
inject_ignore_count := inject_ignore_count + 1
end
elseif diff_arch.terminology.has_id_code (id_code) then
diff_arch.terminology.put_term_binding (binding_uri, {OPENEHR_DEFINITIONS}.Loinc_terminology_id, id_code)
elseif diff_arch.terminology.has_code (arch_code) then
diff_arch.terminology.put_term_binding (binding_uri, term_binding_ns, arch_code)
inject_new_count := inject_new_count + 1
save_required := True
else
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_archetype_node_not_found, <<arch_id, id_code, current_library_name>>))
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_archetype_node_not_found, <<arch_id, arch_code, current_library_name>>))
end
end
end
end

in_file.close

report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_loinc_report, <<inject_new_count.out, inject_replace_count.out, inject_ignore_count.out, arch_count.out>>))
report_std_err (get_msg ({ADL_MESSAGES_IDS}.ec_term_bindings_report, <<inject_new_count.out, term_binding_ns, inject_replace_count.out, inject_ignore_count.out, arch_count.out>>))
end
end
end
Expand Down
28 changes: 20 additions & 8 deletions apps/adlc/src/main/options_processor.e
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ feature -- Definitions
Result.extend (create {ARGUMENT_SWITCH}.make (display_archetypes_switch, get_text (ec_display_archetypes_switch_desc), False, False))
Result.extend (create {ARGUMENT_SWITCH}.make (list_rms_switch, get_text (ec_list_rms_switch_desc), False, False))
Result.extend (create {ARGUMENT_SWITCH}.make (report_switch, get_text (ec_report_switch_desc), False, False))
Result.extend (create {ARGUMENT_SWITCH}.make (loinc_switch, get_text (ec_loinc_switch_desc), False, False))
Result.extend (create {ARGUMENT_SWITCH}.make (export_switch, get_text (ec_export_switch_desc), False, False))

-- switches with arguments
Expand All @@ -68,6 +67,7 @@ feature -- Definitions
Result.extend (create {ARGUMENT_VALUE_SWITCH}.make (output_dir_switch, get_text (ec_output_dir_switch_desc), True, False, output_dir_switch_arg_name, get_text (ec_output_dir_switch_arg_desc), False))
Result.extend (create {ARGUMENT_VALUE_SWITCH}.make (cfg_switch, get_text (ec_cfg_switch_desc), True, False, cfg_switch_arg_name, get_text (ec_cfg_switch_arg_desc), False))
Result.extend (create {ARGUMENT_VALUE_SWITCH}.make (input_file_switch, get_text (ec_input_file_switch_desc), True, False, input_file_switch_arg_name, get_text (ec_input_file_switch_arg_desc), False))
Result.extend (create {ARGUMENT_VALUE_SWITCH}.make (term_bindings_switch, get_text (ec_term_bindings_switch_desc), True, False, term_bindings_switch_arg, get_text (ec_term_bindings_switch_arg_desc), False))

-- valid command line configurations

Expand Down Expand Up @@ -117,12 +117,12 @@ feature -- Definitions
switch_of_name (quiet_switch), switch_of_name (format_switch),
switch_of_name (report_switch), switch_of_name (output_dir_switch)>>, False))

-- LOINC binding injection
-- adlc -b <library name> [-q] --inject_loinc -i <loinc_file>
-- adlc --library <library name> [--quiet] --inject_loinc --input_file <loinc_file>
-- Terminology binding injection
-- adlc -b <library name> [-q] --inject_term_bindings <terminology_name_space> -i <terms_file>
-- adlc --library <library name> [--quiet] --inject_term_bindings --input_file <terms_file>
Result.extend (create {ARGUMENT_GROUP}.make (<< switch_of_name (library_switch),
switch_of_name (quiet_switch),
switch_of_name (loinc_switch),
switch_of_name (term_bindings_switch),
switch_of_name (input_file_switch)>>, False))
end

Expand All @@ -143,7 +143,9 @@ feature -- Definitions

report_switch: STRING = "r|report"
export_switch: STRING = "x|export"
loinc_switch: STRING = "inject_loinc"

term_bindings_switch: STRING = "inject_term_bindings"
term_bindings_switch_arg: STRING = "terminology namespace"

library_switch: STRING = "b|library"
library_switch_arg: STRING = "library name"
Expand Down Expand Up @@ -204,7 +206,7 @@ feature {NONE} -- Initialization
write_to_file_system := has_option (output_dir_switch)
report := has_option (report_switch)
export_archetypes := has_option (export_switch)
inject_loinc_bindings := has_option (loinc_switch)
inject_term_bindings := has_option (term_bindings_switch)
end
end

Expand Down Expand Up @@ -280,6 +282,16 @@ feature -- Access
end
end

term_bindings_namespace: detachable STRING
-- terminology to add bindings for
require
is_successful: is_successful
once
if has_option (term_bindings_switch) and then attached option_of_name (term_bindings_switch) as opt and then opt.has_value then
Result := opt.value
end
end

archetype_id_pattern: STRING
do
if has_non_switched_argument then
Expand Down Expand Up @@ -311,7 +323,7 @@ feature -- Status Report

report: BOOLEAN

inject_loinc_bindings: BOOLEAN
inject_term_bindings: BOOLEAN

export_archetypes: BOOLEAN

Expand Down
12 changes: 7 additions & 5 deletions apps/resources/messages/compiled/adl_messages_db.e
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ feature -- Initialisation

make
do
create message_table.make (958)
create message_table.make (960)
message_table.put ("Terminology initialisation failed; reason: $1", ec_terminology_init_failed)
message_table.put ("Using ADL version $1 for output serialisation", ec_adl_version_warning)
message_table.put ("Validation level STRICT", ec_validation_strict)
Expand Down Expand Up @@ -298,7 +298,6 @@ feature -- Initialisation
message_table.put ("generate list of reference models", ec_list_rms_switch_desc)
message_table.put ("export archetypes", ec_export_switch_desc)
message_table.put ("generate reports", ec_report_switch_desc)
message_table.put ("inject LOINC code bindings", ec_loinc_switch_desc)
message_table.put ("display reference model in user-friendly format", ec_display_rm_switch_desc)
message_table.put ("reference model name", ec_display_rm_switch_arg_desc)
message_table.put ("export reference models in all available formats", ec_export_rms_switch_desc)
Expand All @@ -309,6 +308,8 @@ feature -- Initialisation
message_table.put ("output directory", ec_output_dir_switch_arg_desc)
message_table.put ("input file", ec_input_file_switch_desc)
message_table.put ("input file path", ec_input_file_switch_arg_desc)
message_table.put ("terminology namespace", ec_term_bindings_switch_desc)
message_table.put ("terminology namespace: loinc, snomed, s2, openehr, etc", ec_term_bindings_switch_arg_desc)
message_table.put ("output default configuration file location", ec_cfg_switch_desc)
message_table.put (".cfg file path", ec_cfg_switch_arg_desc)
message_table.put ("library to use", ec_library_switch_desc)
Expand All @@ -328,9 +329,10 @@ feature -- Initialisation
message_table.put ("Could not create output directory '$1'", ec_invalid_output_directory)
message_table.put ("Could not read input file '$1'", ec_invalid_input_file)
message_table.put ("Archetype $1 not validated (run with '-a validate' to see errors)", ec_archetype_not_valid)
message_table.put ("--------- Injecting LOINC bindings from $1 ---------", ec_loinc_start)
message_table.put ("Replacing $1 binding $2 for $3 with $4 in archetype $5", ec_loinc_replace_binding)
message_table.put ("--------- Injected $1 new LOINC codes and replaced $2 in $3 archetypes; ignored $4 codes", ec_loinc_report)
message_table.put ("No terminology with namespace '$1'", ec_terminology_does_not_exist_err)
message_table.put ("--------- Injecting term bindings for $1 from $2 ---------", ec_term_bindings_start)
message_table.put ("Replacing $1 binding $2 for $3 with $4 in archetype $5", ec_replace_term_binding)
message_table.put ("--------- Injected $1 new bindings for $2 and replaced $3 in $4 archetypes; ignored $5 codes", ec_term_bindings_report)
message_table.put ("------------ Archetypes in library '$1 --------------'%N", ec_archs_list_text)
message_table.put ("-----------------------------------------------------%N", ec_archs_list_text_end)
message_table.put ("External tool $1 not found on local system; repository operations limited to local access.%N(Recommendation on Windows: install Git for any platform from https://git-scm.com/)", ec_repository_tool_unavailable)
Expand Down
10 changes: 6 additions & 4 deletions apps/resources/messages/compiled/adl_messages_ids.e
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,6 @@ feature -- Definitions
ec_list_rms_switch_desc: STRING = "list_rms_switch_desc"
ec_export_switch_desc: STRING = "export_switch_desc"
ec_report_switch_desc: STRING = "report_switch_desc"
ec_loinc_switch_desc: STRING = "loinc_switch_desc"
ec_display_rm_switch_desc: STRING = "display_rm_switch_desc"
ec_display_rm_switch_arg_desc: STRING = "display_rm_switch_arg_desc"
ec_export_rms_switch_desc: STRING = "export_rms_switch_desc"
Expand All @@ -294,6 +293,8 @@ feature -- Definitions
ec_output_dir_switch_arg_desc: STRING = "output_dir_switch_arg_desc"
ec_input_file_switch_desc: STRING = "input_file_switch_desc"
ec_input_file_switch_arg_desc: STRING = "input_file_switch_arg_desc"
ec_term_bindings_switch_desc: STRING = "term_bindings_switch_desc"
ec_term_bindings_switch_arg_desc: STRING = "term_bindings_switch_arg_desc"
ec_cfg_switch_desc: STRING = "cfg_switch_desc"
ec_cfg_switch_arg_desc: STRING = "cfg_switch_arg_desc"
ec_library_switch_desc: STRING = "library_switch_desc"
Expand All @@ -313,9 +314,10 @@ feature -- Definitions
ec_invalid_output_directory: STRING = "invalid_output_directory"
ec_invalid_input_file: STRING = "invalid_input_file"
ec_archetype_not_valid: STRING = "archetype_not_valid"
ec_loinc_start: STRING = "loinc_start"
ec_loinc_replace_binding: STRING = "loinc_replace_binding"
ec_loinc_report: STRING = "loinc_report"
ec_terminology_does_not_exist_err: STRING = "terminology_does_not_exist_err"
ec_term_bindings_start: STRING = "term_bindings_start"
ec_replace_term_binding: STRING = "replace_term_binding"
ec_term_bindings_report: STRING = "term_bindings_report"
ec_archs_list_text: STRING = "archs_list_text"
ec_archs_list_text_end: STRING = "archs_list_text_end"
ec_repository_tool_unavailable: STRING = "repository_tool_unavailable"
Expand Down
Loading

0 comments on commit f7b187c

Please sign in to comment.