1
1
defmodule HL7 do
2
2
@ moduledoc """
3
- Utility functions to load HL7 files as local streams.
3
+ Functions to manipulate and query HL7 documents -- plus a way to handle HL7 file streams.
4
4
"""
5
5
6
6
defstruct segments: [ ]
@@ -108,9 +108,17 @@ defmodule HL7 do
108
108
@ doc ~S"""
109
109
Creates an HL7 struct from HL7 data (accepting text, lists or the deprecated `HL7.Message` struct).
110
110
"""
111
- @ spec new! ( hl7_list_data ( ) | String . t ( ) | HL7.Message . t ( ) ) :: t ( )
111
+ @ spec new! ( hl7_list_data ( ) | String . t ( ) | HL7.Message . t ( ) | [ segment ( ) ] ) :: t ( )
112
112
def new! ( segments ) when is_list ( segments ) do
113
- segments = Enum . map ( segments , fn segment -> to_map ( % { } , 0 , segment ) end )
113
+ segments =
114
+ Enum . map (
115
+ segments ,
116
+ fn
117
+ segment when is_list ( segment ) -> to_map ( % { } , 0 , segment )
118
+ % { 0 => _ } = segment -> segment
119
+ end
120
+ )
121
+
114
122
% __MODULE__ { segments: segments }
115
123
end
116
124
@@ -136,40 +144,31 @@ defmodule HL7 do
136
144
end
137
145
138
146
def put ( segment_data , % Path { } = path , value ) do
139
- segment_data
140
- |> cap_nested_input_map ( )
141
- |> do_put ( path , value )
142
- |> uncap_nested_output_map ( )
147
+ segment_data |> do_put ( path , value )
143
148
end
144
149
145
150
def update ( % HL7 { segments: segments } = hl7 , % Path { } = path , default , fun ) do
146
151
% HL7 { hl7 | segments: update ( segments , path , default , fun ) }
147
152
end
148
153
149
154
def update ( segment_data , path , default , fun ) do
150
- segment_data
151
- |> cap_nested_input_map ( )
152
- |> do_put ( path , { default , fun } )
153
- |> uncap_nested_output_map ( )
155
+ segment_data |> do_put ( path , { default , fun } )
154
156
end
155
157
156
158
def update! ( % HL7 { segments: segments } = hl7 , % Path { } = path , fun ) do
157
159
% HL7 { hl7 | segments: update! ( segments , path , fun ) }
158
160
end
159
161
160
162
def update! ( segment_data , path , fun ) do
161
- segment_data
162
- |> cap_nested_input_map ( )
163
- |> do_put ( path , { fun } )
164
- |> uncap_nested_output_map ( )
163
+ segment_data |> do_put ( path , { fun } )
165
164
end
166
165
167
166
def get_segments ( % HL7 { segments: segments } ) do
168
- uncap_nested_output_map ( segments )
167
+ segments
169
168
end
170
169
171
170
def set_segments ( % HL7 { } = hl7 , segments ) do
172
- % HL7 { hl7 | segments: cap_nested_input_map ( segments ) }
171
+ % HL7 { hl7 | segments: segments }
173
172
end
174
173
175
174
@ doc ~S"""
@@ -252,7 +251,6 @@ defmodule HL7 do
252
251
data
253
252
|> do_get ( path )
254
253
|> maybe_truncate ( path )
255
- |> uncap_nested_output_map ( )
256
254
end
257
255
258
256
@ doc """
@@ -266,7 +264,6 @@ defmodule HL7 do
266
264
@ spec chunk_by_lead_segment ( t ( ) | [ segment ( ) ] , String . t ( ) , Keyword . t ( ) ) :: [ [ segment ( ) ] ]
267
265
def chunk_by_lead_segment ( segments , segment_name , options \\ [ ] ) do
268
266
do_chunk_by_segment ( segments , segment_name )
269
- |> uncap_nested_output_map ( )
270
267
|> maybe_keep_prefix_segments ( ! ! options [ :keep_prefix_segments ] )
271
268
end
272
269
@@ -279,11 +276,11 @@ defmodule HL7 do
279
276
end
280
277
281
278
def to_list ( map_data ) when is_list ( map_data ) do
282
- Enum . map ( map_data , fn segment_map -> do_to_list ( cap_nested_input_map ( segment_map ) ) end )
279
+ Enum . map ( map_data , fn segment_map -> do_to_list ( segment_map ) end )
283
280
end
284
281
285
282
def to_list ( map_data ) when is_map ( map_data ) do
286
- do_to_list ( cap_nested_input_map ( map_data ) )
283
+ do_to_list ( map_data )
287
284
end
288
285
289
286
@ doc """
@@ -325,46 +322,8 @@ defmodule HL7 do
325
322
326
323
# internals
327
324
328
- defp get_max_index ( % { __max_index__: max_index } ) do
329
- max_index
330
- end
331
-
332
325
defp get_max_index ( data ) when is_map ( data ) do
333
- data |> Map . keys ( ) |> Enum . max ( ) |> max ( 1 )
334
- end
335
-
336
- defp cap_map ( map , index ) do
337
- Map . put ( map , :__max_index__ , max ( map [ :__max_index__ ] || 1 , index ) )
338
- end
339
-
340
- defp cap_nested_input_map ( % { __max_index__: _ } = data ) do
341
- Map . new ( data , fn { k , v } -> { k , cap_nested_input_map ( v ) } end )
342
- end
343
-
344
- defp cap_nested_input_map ( data ) when is_map ( data ) do
345
- max_index = data |> Map . keys ( ) |> Enum . max ( ) |> max ( 1 )
346
-
347
- data
348
- |> Map . put ( :__max_index__ , max_index )
349
- |> Map . new ( fn { k , v } -> { k , cap_nested_input_map ( v ) } end )
350
- end
351
-
352
- defp cap_nested_input_map ( data ) do
353
- data
354
- end
355
-
356
- defp uncap_nested_output_map ( data ) when is_map ( data ) do
357
- data
358
- |> Map . delete ( :__max_index__ )
359
- |> Map . new ( fn { k , v } -> { k , uncap_nested_output_map ( v ) } end )
360
- end
361
-
362
- defp uncap_nested_output_map ( data ) when is_list ( data ) do
363
- Enum . map ( data , & uncap_nested_output_map / 1 )
364
- end
365
-
366
- defp uncap_nested_output_map ( data ) do
367
- data
326
+ data |> Map . keys ( ) |> Enum . max ( ) |> max ( 0 )
368
327
end
369
328
370
329
defp to_map ( value ) when is_binary ( value ) do
@@ -375,8 +334,8 @@ defmodule HL7 do
375
334
to_map ( % { } , 1 , value )
376
335
end
377
336
378
- defp to_map ( acc , index , [ ] ) do
379
- Map . put ( acc , :__max_index__ , index - 1 )
337
+ defp to_map ( acc , index , [ h ] ) do
338
+ Map . put ( acc , index , to_map ( h ) )
380
339
end
381
340
382
341
defp to_map ( acc , index , [ h | t ] ) do
@@ -392,7 +351,7 @@ defmodule HL7 do
392
351
end
393
352
394
353
def do_to_list ( hl7_map_data ) do
395
- do_to_list ( [ ] , hl7_map_data , hl7_map_data [ :__max_index__ ] )
354
+ do_to_list ( [ ] , hl7_map_data , get_max_index ( hl7_map_data ) )
396
355
end
397
356
398
357
defp do_to_list ( acc , % { 0 => _ } = hl7_map_data , index ) when index > - 1 do
@@ -440,10 +399,6 @@ defmodule HL7 do
440
399
|> Enum . reverse ( )
441
400
end
442
401
443
- defp get_value_at_index ( % { __max_index__: max_index } = _segment_data , i ) when i > max_index do
444
- nil
445
- end
446
-
447
402
defp get_value_at_index ( nil , _ ) do
448
403
nil
449
404
end
@@ -461,16 +416,16 @@ defmodule HL7 do
461
416
end
462
417
463
418
defp get_value_at_index ( segment_data , i ) do
464
- Map . get ( segment_data , i , "" )
419
+ max_index = get_max_index ( segment_data )
420
+ if i > max_index , do: nil , else: Map . get ( segment_data , i , "" )
465
421
end
466
422
467
- defp ensure_map ( data , index ) when is_binary ( data ) or is_nil ( data ) do
423
+ defp ensure_map ( data ) when is_binary ( data ) or is_nil ( data ) do
468
424
% { 1 => data }
469
- |> Map . put ( :__max_index__ , max ( 1 , index ) )
470
425
end
471
426
472
- defp ensure_map ( data , index ) when is_map ( data ) do
473
- cap_map ( data , index )
427
+ defp ensure_map ( data ) when is_map ( data ) do
428
+ data
474
429
end
475
430
476
431
defp maybe_truncate ( segment_data , % Path { truncate: true } ) do
@@ -495,23 +450,23 @@ defmodule HL7 do
495
450
end
496
451
497
452
defp resolve_placement_value ( _field_data = nil , { default , _fun } , _path ) do
498
- default |> cap_nested_input_map ( )
453
+ default
499
454
end
500
455
501
456
defp resolve_placement_value ( field_data , { _default , fun } , _path ) do
502
- fun . ( field_data ) |> cap_nested_input_map ( )
457
+ fun . ( field_data )
503
458
end
504
459
505
460
defp resolve_placement_value ( _field_data = nil , { _fun } , path ) do
506
461
raise KeyError , message: "HL7.Path #{ inspect ( path ) } could not be found"
507
462
end
508
463
509
464
defp resolve_placement_value ( field_data , { fun } , _path ) do
510
- fun . ( field_data ) |> cap_nested_input_map ( )
465
+ fun . ( field_data )
511
466
end
512
467
513
468
defp resolve_placement_value ( _field_data , value , _path ) do
514
- value |> cap_nested_input_map ( )
469
+ value
515
470
end
516
471
517
472
defp do_get ( % HL7 { } = hl7 , % Path { } = path ) do
@@ -658,7 +613,6 @@ defmodule HL7 do
658
613
659
614
defp do_put_in_segment ( segment_data , value , % { field: f } = path ) do
660
615
Map . put ( segment_data , f , do_put_in_field ( segment_data [ f ] , value , path ) )
661
- |> cap_map ( f )
662
616
end
663
617
664
618
defp do_put_in_field ( field_data , value , % { repetition: "*" , component: nil } = path ) do
@@ -668,38 +622,31 @@ defmodule HL7 do
668
622
defp do_put_in_field ( field_data , value , % { repetition: "*" } = path ) do
669
623
1 .. get_max_index ( field_data )
670
624
|> Map . new ( fn i ->
671
- { i , do_put_in_repetition ( ensure_map ( field_data [ i ] , i ) , value , path ) }
625
+ { i , do_put_in_repetition ( ensure_map ( field_data [ i ] ) , value , path ) }
672
626
end )
673
- |> Map . put ( :__max_index__ , field_data [ :__max_index__ ] )
674
627
end
675
628
676
629
defp do_put_in_field ( field_data , value , % { repetition: r } = path ) do
677
- field_map = ensure_map ( field_data , r )
678
-
630
+ field_map = ensure_map ( field_data )
679
631
Map . put ( field_map , r , do_put_in_repetition ( field_map [ r ] , value , path ) )
680
- |> cap_map ( r )
681
632
end
682
633
683
634
defp do_put_in_repetition ( repetition_data , value , % { component: nil } = path ) do
684
635
resolve_placement_value ( repetition_data , value , path )
685
636
end
686
637
687
638
defp do_put_in_repetition ( repetition_data , value , % { component: c } = path ) do
688
- repetition_map = ensure_map ( repetition_data , c )
689
-
639
+ repetition_map = ensure_map ( repetition_data )
690
640
Map . put ( repetition_map , c , do_put_in_component ( repetition_map [ c ] , value , path ) )
691
- |> cap_map ( c )
692
641
end
693
642
694
643
defp do_put_in_component ( component_data , value , % { subcomponent: nil } = path ) do
695
644
resolve_placement_value ( component_data , value , path )
696
645
end
697
646
698
647
defp do_put_in_component ( subcomponent_data , value , % { subcomponent: s } = path ) do
699
- subcomponent_map = ensure_map ( subcomponent_data , s )
700
-
648
+ subcomponent_map = ensure_map ( subcomponent_data )
701
649
Map . put ( subcomponent_map , s , resolve_placement_value ( subcomponent_map [ s ] , value , path ) )
702
- |> cap_map ( s )
703
650
end
704
651
705
652
defp do_label ( segment_data , % Path { } = output_param ) do
@@ -772,3 +719,10 @@ defimpl Inspect, for: HL7 do
772
719
end
773
720
end
774
721
end
722
+
723
+ defimpl String.Chars , for: HL7 do
724
+ @ spec to_string ( HL7 . t ( ) ) :: String . t ( )
725
+ def to_string ( % HL7 { } = hl7 ) do
726
+ hl7 |> HL7 . to_list ( ) |> HL7.Message . raw ( ) |> Map . get ( :raw )
727
+ end
728
+ end
0 commit comments