Skip to content

Commit d6fbdad

Browse files
authored
Issue #2377 - update ConstraintGenerator (#2389)
* Issue #2377 - update ConstraintGenerator Signed-off-by: John T.E. Timm <[email protected]>
1 parent 5f1c25b commit d6fbdad

File tree

5 files changed

+5993
-33
lines changed

5 files changed

+5993
-33
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
/*
2+
* (C) Copyright IBM Corp. 2021
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
package com.ibm.fhir.ig.carin.bb.test;
8+
9+
import static org.testng.Assert.assertTrue;
10+
11+
import java.io.InputStream;
12+
import java.util.List;
13+
14+
import org.testng.annotations.Test;
15+
16+
import com.ibm.fhir.model.annotation.Constraint;
17+
import com.ibm.fhir.model.format.Format;
18+
import com.ibm.fhir.model.parser.FHIRParser;
19+
import com.ibm.fhir.model.resource.StructureDefinition;
20+
import com.ibm.fhir.profile.ConstraintGenerator;
21+
22+
public class C4BBPatientConstraintGeneratorTest {
23+
@Test
24+
public void testConstraintGenerator() throws Exception {
25+
InputStream in = C4BBPatientConstraintGeneratorTest.class.getClassLoader().getResourceAsStream("JSON/StructureDefinition-C4BB-Patient.json");
26+
FHIRParser parser = FHIRParser.parser(Format.JSON);
27+
StructureDefinition profile = parser.parse(in);
28+
ConstraintGenerator generator = new ConstraintGenerator(profile);
29+
List<Constraint> constraints = generator.generate();
30+
assertTrue(hasConstraint(constraints, "meta.where(lastUpdated.exists() and profile.where($this = 'http://hl7.org/fhir/us/carin-bb/StructureDefinition/C4BB-Patient|1.0.0').count() = 1).exists()"));
31+
}
32+
33+
public boolean hasConstraint(List<Constraint> constraints, String expr) {
34+
for (Constraint constraint : constraints) {
35+
if (constraint.expression().equals(expr)) {
36+
return true;
37+
}
38+
}
39+
return false;
40+
}
41+
}

conformance/fhir-ig-carin-bb/src/test/resources/JSON/StructureDefinition-C4BB-Patient.json

+5,908
Large diffs are not rendered by default.

fhir-path/src/main/java/com/ibm/fhir/path/evaluator/FHIRPathEvaluator.java

+1-9
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,10 @@
3131
import static com.ibm.fhir.path.util.FHIRPathUtil.hasStringValue;
3232
import static com.ibm.fhir.path.util.FHIRPathUtil.hasSystemValue;
3333
import static com.ibm.fhir.path.util.FHIRPathUtil.hasTemporalValue;
34-
import static com.ibm.fhir.path.util.FHIRPathUtil.isCodedElementNode;
3534
import static com.ibm.fhir.path.util.FHIRPathUtil.isFalse;
3635
import static com.ibm.fhir.path.util.FHIRPathUtil.isQuantityNode;
3736
import static com.ibm.fhir.path.util.FHIRPathUtil.isSingleton;
38-
import static com.ibm.fhir.path.util.FHIRPathUtil.isStringElementNode;
39-
import static com.ibm.fhir.path.util.FHIRPathUtil.isStringValue;
4037
import static com.ibm.fhir.path.util.FHIRPathUtil.isTypeCompatible;
41-
import static com.ibm.fhir.path.util.FHIRPathUtil.isUriElementNode;
4238
import static com.ibm.fhir.path.util.FHIRPathUtil.singleton;
4339
import static com.ibm.fhir.path.util.FHIRPathUtil.unescape;
4440

@@ -793,11 +789,7 @@ public Collection<FHIRPathNode> visitMembershipExpression(FHIRPathParser.Members
793789

794790
switch (operator) {
795791
case "in":
796-
if ((isCodedElementNode(left) || isStringElementNode(left) || isUriElementNode(left)) && isStringValue(right)) {
797-
// For backwards compatibility per: https://jira.hl7.org/projects/FHIR/issues/FHIR-26605
798-
FHIRPathFunction memberOfFunction = FHIRPathFunction.registry().getFunction("memberOf");
799-
result = memberOfFunction.apply(evaluationContext, left, Collections.singletonList(right));
800-
} else if (left.isEmpty()) {
792+
if (left.isEmpty()) {
801793
result = empty();
802794
} else if (right.containsAll(left)) {
803795
result = SINGLETON_TRUE;

fhir-path/src/test/java/com/ibm/fhir/path/test/MemberOfFunctionTest.java

+23-23
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* (C) Copyright IBM Corp. 2019, 2020
2+
* (C) Copyright IBM Corp. 2019, 2021
33
*
44
* SPDX-License-Identifier: Apache-2.0
55
*/
@@ -118,7 +118,7 @@ public void testMemberOfFunction6() throws Exception {
118118
Assert.assertEquals(result, SINGLETON_FALSE);
119119
}
120120

121-
@Test
121+
@Test(enabled = false)
122122
public void testMemberOfFunction7() throws Exception {
123123
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
124124

@@ -254,14 +254,14 @@ public void testMemberOfFunction17() throws Exception {
254254

255255
Assert.assertEquals(result, SINGLETON_FALSE);
256256
}
257-
257+
258258
@Test
259259
public void testMemberOfFunction18() throws Exception {
260260
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
261261
Collection<FHIRPathNode> result = evaluator.evaluate(Code.of(ENGLISH_US), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
262262
Assert.assertEquals(result, SINGLETON_TRUE);
263263
}
264-
264+
265265
@Test
266266
public void testMemberOfFunction19() throws Exception {
267267
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -279,7 +279,7 @@ public void testMemberOfFunction20() throws Exception {
279279
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
280280
Assert.assertEquals(result, SINGLETON_TRUE);
281281
}
282-
282+
283283
@Test
284284
public void testMemberOfFunction21() throws Exception {
285285
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -290,7 +290,7 @@ public void testMemberOfFunction21() throws Exception {
290290
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
291291
Assert.assertEquals(result, SINGLETON_FALSE);
292292
}
293-
293+
294294
@Test
295295
public void testMemberOfFunction22() throws Exception {
296296
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -314,7 +314,7 @@ public void testMemberOfFunction23() throws Exception {
314314
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
315315
Assert.assertEquals(result, SINGLETON_TRUE);
316316
}
317-
317+
318318
@Test
319319
public void testMemberOfFunction24() throws Exception {
320320
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -327,7 +327,7 @@ public void testMemberOfFunction24() throws Exception {
327327
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
328328
Assert.assertEquals(result, SINGLETON_FALSE);
329329
}
330-
330+
331331
@Test
332332
public void testMemberOfFunction25() throws Exception {
333333
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -351,7 +351,7 @@ public void testMemberOfFunction26() throws Exception {
351351
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
352352
Assert.assertEquals(result, SINGLETON_TRUE);
353353
}
354-
354+
355355
@Test
356356
public void testMemberOfFunction27() throws Exception {
357357
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -362,7 +362,7 @@ public void testMemberOfFunction27() throws Exception {
362362
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
363363
Assert.assertEquals(result, SINGLETON_FALSE);
364364
}
365-
365+
366366
@Test
367367
public void testMemberOfFunction28() throws Exception {
368368
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -373,28 +373,28 @@ public void testMemberOfFunction28() throws Exception {
373373
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
374374
Assert.assertEquals(result, SINGLETON_FALSE);
375375
}
376-
376+
377377
@Test
378378
public void testMemberOfFunction29() throws Exception {
379379
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
380380
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of(ENGLISH_US), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
381381
Assert.assertEquals(result, SINGLETON_TRUE);
382382
}
383-
383+
384384
@Test
385385
public void testMemberOfFunction30() throws Exception {
386386
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
387387
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of("invalidLanguageCode"), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
388388
Assert.assertEquals(result, SINGLETON_FALSE);
389389
}
390-
390+
391391
@Test
392392
public void testMemberOfFunction31() throws Exception {
393393
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
394394
Collection<FHIRPathNode> result = evaluator.evaluate(Code.of(UNITS_PER_LITER), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
395395
Assert.assertEquals(result, SINGLETON_TRUE);
396396
}
397-
397+
398398
@Test
399399
public void testMemberOfFunction32() throws Exception {
400400
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -412,7 +412,7 @@ public void testMemberOfFunction33() throws Exception {
412412
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
413413
Assert.assertEquals(result, SINGLETON_TRUE);
414414
}
415-
415+
416416
@Test
417417
public void testMemberOfFunction34() throws Exception {
418418
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -423,7 +423,7 @@ public void testMemberOfFunction34() throws Exception {
423423
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
424424
Assert.assertEquals(result, SINGLETON_FALSE);
425425
}
426-
426+
427427
@Test
428428
public void testMemberOfFunction35() throws Exception {
429429
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -447,7 +447,7 @@ public void testMemberOfFunction36() throws Exception {
447447
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
448448
Assert.assertEquals(result, SINGLETON_TRUE);
449449
}
450-
450+
451451
@Test
452452
public void testMemberOfFunction37() throws Exception {
453453
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -460,7 +460,7 @@ public void testMemberOfFunction37() throws Exception {
460460
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
461461
Assert.assertEquals(result, SINGLETON_FALSE);
462462
}
463-
463+
464464
@Test
465465
public void testMemberOfFunction38() throws Exception {
466466
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -484,7 +484,7 @@ public void testMemberOfFunction39() throws Exception {
484484
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
485485
Assert.assertEquals(result, SINGLETON_TRUE);
486486
}
487-
487+
488488
@Test
489489
public void testMemberOfFunction40() throws Exception {
490490
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -495,7 +495,7 @@ public void testMemberOfFunction40() throws Exception {
495495
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
496496
Assert.assertEquals(result, SINGLETON_FALSE);
497497
}
498-
498+
499499
@Test
500500
public void testMemberOfFunction41() throws Exception {
501501
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
@@ -506,21 +506,21 @@ public void testMemberOfFunction41() throws Exception {
506506
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
507507
Assert.assertEquals(result, SINGLETON_FALSE);
508508
}
509-
509+
510510
@Test
511511
public void testMemberOfFunction42() throws Exception {
512512
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
513513
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of(UNITS_PER_LITER), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
514514
Assert.assertEquals(result, SINGLETON_TRUE);
515515
}
516-
516+
517517
@Test
518518
public void testMemberOfFunction43() throws Exception {
519519
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
520520
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of("invalid ucum code"), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
521521
Assert.assertEquals(result, SINGLETON_FALSE);
522522
}
523-
523+
524524
@Test
525525
public void testMemberOfFunction44() throws Exception {
526526
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();

fhir-profile/src/main/java/com/ibm/fhir/profile/ConstraintGenerator.java

+20-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,14 @@ private String generatePatternValueConstraint(Node node, boolean discriminator)
521521
sb.append(cardinality(node, sb.toString()));
522522
}
523523
} else if (pattern.is(Uri.class)) {
524-
sb.append(identifier).append(" = '").append(pattern.as(Uri.class).getValue()).append("'");
524+
if (isSlice(elementDefinition) && hasDiscriminatorPath(elementDefinition, "$this")) {
525+
sb.append(identifier).append(".where($this = '").append(pattern.as(Uri.class).getValue()).append("')");
526+
if (!discriminator) {
527+
sb.append(cardinality(node, sb.toString()));
528+
}
529+
} else {
530+
sb.append(identifier).append(" = '").append(pattern.as(Uri.class).getValue()).append("'");
531+
}
525532
} else if (pattern.is(Code.class)) {
526533
sb.append(identifier).append(" = '").append(pattern.as(Code.class).getValue()).append("'");
527534
}
@@ -797,6 +804,18 @@ private boolean hasConstraint(Node node) {
797804
return false;
798805
}
799806

807+
private boolean hasDiscriminatorPath(ElementDefinition slice, String path) {
808+
ElementDefinition sliceDefinition = getSliceDefinition(slice);
809+
if (sliceDefinition != null) {
810+
Slicing slicing = sliceDefinition.getSlicing();
811+
List<String> paths = slicing.getDiscriminator().stream()
812+
.map(discriminator -> discriminator.getPath().getValue())
813+
.collect(Collectors.toList());
814+
return paths.size() == 1 && path.equals(paths.get(0));
815+
}
816+
return false;
817+
}
818+
800819
private boolean hasExtensionConstraint(ElementDefinition elementDefinition) {
801820
List<Type> types = getTypes(elementDefinition);
802821

0 commit comments

Comments
 (0)