7
7
import de .medizininformatikinitiative .torch .model .management .ResourceAttribute ;
8
8
import de .medizininformatikinitiative .torch .model .management .ResourceBundle ;
9
9
import de .medizininformatikinitiative .torch .model .management .ResourceGroup ;
10
- import org .hl7 .fhir .r4 .model .Resource ;
11
10
import org .slf4j .Logger ;
12
11
import org .slf4j .LoggerFactory ;
13
- import reactor .core .publisher .Flux ;
14
12
15
13
import javax .annotation .Nullable ;
16
14
import java .util .ArrayList ;
15
+ import java .util .Collections ;
17
16
import java .util .List ;
18
17
import java .util .Map ;
19
18
import java .util .Objects ;
22
21
23
22
public class ReferenceHandler {
24
23
private static final Logger logger = LoggerFactory .getLogger (ReferenceHandler .class );
25
- private final ProfileMustHaveChecker profileMustHaveChecker ;
24
+ private final ResourceGroupValidator resourceGroupValidator ;
26
25
27
26
28
- public ReferenceHandler (ProfileMustHaveChecker profileMustHaveChecker ) {
29
- this .profileMustHaveChecker = profileMustHaveChecker ;
27
+ public ReferenceHandler (ResourceGroupValidator resourceGroupValidator ) {
28
+ this .resourceGroupValidator = resourceGroupValidator ;
30
29
31
30
}
32
31
33
- private static Flux < List <ResourceGroup >> checkReferenceViolatesMustHave (ReferenceWrapper referenceWrapper , List <ResourceGroup > list , ResourceBundle processingBundle ) {
32
+ private static List <ResourceGroup > checkReferenceViolatesMustHave (ReferenceWrapper referenceWrapper , List <ResourceGroup > list , ResourceBundle processingBundle ) throws MustHaveViolatedException {
34
33
ResourceAttribute referenceAttribute = referenceWrapper .toResourceAttributeGroup ();
35
34
if (referenceWrapper .refAttribute ().mustHave () && list .isEmpty ()) {
36
35
processingBundle .setResourceAttributeInValid (referenceAttribute );
37
- return Flux . error ( new MustHaveViolatedException (
36
+ throw new MustHaveViolatedException (
38
37
"MustHave condition violated: No valid references were resolved for " + referenceWrapper .references ()
39
- ));
38
+ );
39
+ }
40
+ if (referenceWrapper .references ().isEmpty ()) {
41
+ return List .of ();
40
42
}
41
43
processingBundle .setResourceAttributeValid (referenceAttribute );
42
- return Flux . just ( list ) ;
44
+ return list ;
43
45
}
44
46
45
47
/**
@@ -49,47 +51,57 @@ private static Flux<List<ResourceGroup>> checkReferenceViolatesMustHave(Referenc
49
51
* @param groupMap cache containing all known attributeGroups
50
52
* @return newly added ResourceGroups to be processed
51
53
*/
52
- public Flux <ResourceGroup > handleReferences (List <ReferenceWrapper > references ,
54
+ public List <ResourceGroup > handleReferences (List <ReferenceWrapper > references ,
53
55
@ Nullable PatientResourceBundle patientBundle ,
54
56
ResourceBundle coreBundle ,
55
- Map <String , AnnotatedAttributeGroup > groupMap ) throws MustHaveViolatedException {
57
+ Map <String , AnnotatedAttributeGroup > groupMap ) {
56
58
ResourceBundle processingBundle = (patientBundle != null ) ? patientBundle .bundle () : coreBundle ;
57
59
ResourceGroup parentGroup = new ResourceGroup (references .getFirst ().resourceId (), references .getFirst ().groupId ());
58
60
59
- List <ReferenceWrapper > unprocessedReferences = filterUnprocessedReferences (references , processingBundle );
60
- Set <ResourceGroup > knownGroups = processingBundle .getKnownResourceGroups ();
61
- return Flux .fromIterable (unprocessedReferences )
62
- .concatMap (ref -> handleReference (ref , patientBundle , coreBundle , groupMap ).doOnNext (
63
- resourceGroupList -> {
64
- ResourceAttribute referenceAttribute = ref .toResourceAttributeGroup ();
65
- resourceGroupList .forEach (resourceGroup -> processingBundle .addAttributeToChild (referenceAttribute , resourceGroup ));
61
+ try {
62
+ List <ReferenceWrapper > unprocessedReferences = filterUnprocessedReferences (references , processingBundle );
63
+ Set <ResourceGroup > knownGroups = processingBundle .getKnownResourceGroups ();
64
+ return unprocessedReferences .stream ()
65
+ // map each reference to a list of ResourceGroups
66
+ .map (ref -> {
67
+ List <ResourceGroup > resourceGroupList ;
68
+ try {
69
+ resourceGroupList = handleReference (ref , patientBundle , coreBundle , groupMap );
70
+ } catch (MustHaveViolatedException e ) {
71
+ processingBundle .addResourceGroupValidity (parentGroup , false );
72
+ return Collections .<ResourceGroup >emptyList ();
66
73
}
67
- ))
68
- .collectList ()
69
- .flatMapMany (results -> Flux .fromIterable (results .stream ()
70
- .flatMap (List ::stream )
71
- .toList ()))
72
- .filter (group -> !knownGroups .contains (group ))
73
- .onErrorResume (MustHaveViolatedException .class , e -> {
74
- processingBundle .addResourceGroupValidity (parentGroup , false );
75
- logger .warn ("MustHaveViolatedException occurred. Stopping resource processing: {}" , e .getMessage ());
76
- return Flux .empty ();
77
- });
74
+ ResourceAttribute referenceAttribute = ref .toResourceAttributeGroup ();
75
+ // side effect: add attribute to each resource group
76
+ resourceGroupList .forEach (rg -> processingBundle .addAttributeToChild (referenceAttribute , rg ));
77
+ return resourceGroupList ;
78
+ })
79
+ .flatMap (List ::stream )
80
+ .filter (group -> !knownGroups .contains (group ))
81
+ .toList ();
82
+ } catch (MustHaveViolatedException e ) {
83
+ processingBundle .addResourceGroupValidity (parentGroup , false );
84
+ logger .warn ("MustHaveViolatedException occurred. Stopping resource processing: {}" , e .getMessage ());
85
+ return List .of ();
86
+ }
78
87
}
79
88
80
89
/**
81
90
* Handles a ReferenceWrapper by resolving its references and updating the processing bundle.
82
91
*
92
+ * <p>
93
+ * Checks if referenceAttribute
94
+ *
83
95
* @param referenceWrapper The reference wrapper to handle.
84
96
* @param patientBundle The patient bundle being updated, if present.
85
97
* @param coreBundle to be updated and queried, that contains a centrally shared concurrent HashMap.
86
98
* @param groupMap Map of attribute groups for validation.
87
99
* @return A Flux emitting a list of ResourceGroups corresponding to the resolved references.
88
100
*/
89
- public Flux < List <ResourceGroup > > handleReference (ReferenceWrapper referenceWrapper ,
90
- @ Nullable PatientResourceBundle patientBundle ,
91
- ResourceBundle coreBundle ,
92
- Map <String , AnnotatedAttributeGroup > groupMap ) {
101
+ public List <ResourceGroup > handleReference (ReferenceWrapper referenceWrapper ,
102
+ @ Nullable PatientResourceBundle patientBundle ,
103
+ ResourceBundle coreBundle ,
104
+ Map <String , AnnotatedAttributeGroup > groupMap ) throws MustHaveViolatedException {
93
105
94
106
ResourceBundle processingBundle = patientBundle != null ? patientBundle .bundle () : coreBundle ;
95
107
@@ -104,45 +116,14 @@ public Flux<List<ResourceGroup>> handleReference(ReferenceWrapper referenceWrapp
104
116
})
105
117
.filter (Objects ::nonNull )
106
118
.filter (Optional ::isPresent )
107
- .flatMap (resource -> collectValidGroups (referenceWrapper , groupMap , resource .get (), processingBundle ).stream ())
119
+ .flatMap (resource -> resourceGroupValidator . collectValidGroups (referenceWrapper , groupMap , resource .get (), processingBundle ).stream ())
108
120
.toList ();
109
121
110
122
// Now run your must-have validation and wrap in Flux
111
123
return checkReferenceViolatesMustHave (referenceWrapper , allValidGroups , processingBundle );
112
124
}
113
125
114
126
115
- /**
116
- * Collects all valid resourceGroups for the currently processed ResourceBundle.
117
- * <p> For a given reference and resource checks if already a valid group in processingBundle.
118
- * If resourceGroups not assigned yet, executes filter, musthave (Without References) and profile checks.
119
- *
120
- * @param groupMap known attribute groups
121
- * @param resource Resource to be checked
122
- * @param processingBundle bundle that is currently processed
123
- * @return ResourceGroup if previously unknown and assignable to the group.
124
- */
125
- private List <ResourceGroup > collectValidGroups (ReferenceWrapper referenceWrapper , Map <String , AnnotatedAttributeGroup > groupMap , Resource resource , ResourceBundle processingBundle ) {
126
- return referenceWrapper .refAttribute ().linkedGroups ().stream ()
127
- .map (groupId -> {
128
- ResourceGroup resourceGroup = new ResourceGroup (ResourceUtils .getRelativeURL (resource ), groupId );
129
- Boolean isValid = processingBundle .isValidResourceGroup (resourceGroup );
130
- if (isValid == null ) {
131
- AnnotatedAttributeGroup group = groupMap .get (groupId );
132
- boolean fulfilled = profileMustHaveChecker .fulfilled (resource , group );
133
- if (group .compiledFilter () != null ) {
134
- fulfilled = fulfilled && group .compiledFilter ().test (resource );
135
- }
136
- logger .trace ("Group {} for Reference: {}" , groupId , fulfilled );
137
- isValid = fulfilled ;
138
- processingBundle .addResourceGroupValidity (resourceGroup , isValid );
139
- }
140
- return isValid ? resourceGroup : null ;
141
- })
142
- .filter (Objects ::nonNull )
143
- .toList ();
144
- }
145
-
146
127
/**
147
128
* Iterates over the references to find unprocessed reference wrappers.
148
129
*
@@ -163,19 +144,15 @@ private List<ReferenceWrapper> filterUnprocessedReferences(List<ReferenceWrapper
163
144
164
145
Boolean isValid = processingBundle .resourceAttributeValidity ().get (resourceAttribute );
165
146
processingBundle .addAttributeToParent (resourceAttribute , parentGroup );
166
- if (Boolean . TRUE . equals ( isValid ) ) {
167
- // Already valid, skip
147
+ if (isValid == null ) {
148
+ uncheckedReferences . add ( reference );
168
149
} else {
169
- if (Boolean .FALSE .equals (isValid )) {
170
- if (reference .refAttribute ().mustHave ()) {
171
- processingBundle .addResourceGroupValidity (parentGroup , false );
172
- throw new MustHaveViolatedException (
173
- "Must-have attribute violated for reference: " + reference + " in group: " + parentGroup );
174
- }
175
-
176
- } else {
177
- uncheckedReferences .add (reference );
150
+ if (!isValid && reference .refAttribute ().mustHave ()) {
151
+ processingBundle .addResourceGroupValidity (parentGroup , false );
152
+ throw new MustHaveViolatedException (
153
+ "Must-have attribute violated for reference: " + reference + " in group: " + parentGroup );
178
154
}
155
+
179
156
}
180
157
}
181
158
return uncheckedReferences ;
0 commit comments