Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #2377 - update ConstraintGenerator #2389

Merged
merged 3 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* (C) Copyright IBM Corp. 2021
*
* SPDX-License-Identifier: Apache-2.0
*/

package com.ibm.fhir.ig.carin.bb.test;

import static org.testng.Assert.assertTrue;

import java.io.InputStream;
import java.util.List;

import org.testng.annotations.Test;

import com.ibm.fhir.model.annotation.Constraint;
import com.ibm.fhir.model.format.Format;
import com.ibm.fhir.model.parser.FHIRParser;
import com.ibm.fhir.model.resource.StructureDefinition;
import com.ibm.fhir.profile.ConstraintGenerator;

public class C4BBPatientConstraintGeneratorTest {
@Test
public void testConstraintGenerator() throws Exception {
InputStream in = C4BBPatientConstraintGeneratorTest.class.getClassLoader().getResourceAsStream("JSON/StructureDefinition-C4BB-Patient.json");
FHIRParser parser = FHIRParser.parser(Format.JSON);
StructureDefinition profile = parser.parse(in);
ConstraintGenerator generator = new ConstraintGenerator(profile);
List<Constraint> constraints = generator.generate();
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()"));
}

public boolean hasConstraint(List<Constraint> constraints, String expr) {
for (Constraint constraint : constraints) {
if (constraint.expression().equals(expr)) {
return true;
}
}
return false;
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,10 @@
import static com.ibm.fhir.path.util.FHIRPathUtil.hasStringValue;
import static com.ibm.fhir.path.util.FHIRPathUtil.hasSystemValue;
import static com.ibm.fhir.path.util.FHIRPathUtil.hasTemporalValue;
import static com.ibm.fhir.path.util.FHIRPathUtil.isCodedElementNode;
import static com.ibm.fhir.path.util.FHIRPathUtil.isFalse;
import static com.ibm.fhir.path.util.FHIRPathUtil.isQuantityNode;
import static com.ibm.fhir.path.util.FHIRPathUtil.isSingleton;
import static com.ibm.fhir.path.util.FHIRPathUtil.isStringElementNode;
import static com.ibm.fhir.path.util.FHIRPathUtil.isStringValue;
import static com.ibm.fhir.path.util.FHIRPathUtil.isTypeCompatible;
import static com.ibm.fhir.path.util.FHIRPathUtil.isUriElementNode;
import static com.ibm.fhir.path.util.FHIRPathUtil.singleton;
import static com.ibm.fhir.path.util.FHIRPathUtil.unescape;

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

switch (operator) {
case "in":
if ((isCodedElementNode(left) || isStringElementNode(left) || isUriElementNode(left)) && isStringValue(right)) {
// For backwards compatibility per: https://jira.hl7.org/projects/FHIR/issues/FHIR-26605
FHIRPathFunction memberOfFunction = FHIRPathFunction.registry().getFunction("memberOf");
result = memberOfFunction.apply(evaluationContext, left, Collections.singletonList(right));
} else if (left.isEmpty()) {
if (left.isEmpty()) {
result = empty();
} else if (right.containsAll(left)) {
result = SINGLETON_TRUE;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* (C) Copyright IBM Corp. 2019, 2020
* (C) Copyright IBM Corp. 2019, 2021
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -118,7 +118,7 @@ public void testMemberOfFunction6() throws Exception {
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
@Test(enabled = false)
JohnTimm marked this conversation as resolved.
Show resolved Hide resolved
public void testMemberOfFunction7() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();

Expand Down Expand Up @@ -254,14 +254,14 @@ public void testMemberOfFunction17() throws Exception {

Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction18() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(Code.of(ENGLISH_US), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction19() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -279,7 +279,7 @@ public void testMemberOfFunction20() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction21() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -290,7 +290,7 @@ public void testMemberOfFunction21() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction22() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -314,7 +314,7 @@ public void testMemberOfFunction23() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction24() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -327,7 +327,7 @@ public void testMemberOfFunction24() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction25() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -351,7 +351,7 @@ public void testMemberOfFunction26() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction27() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -362,7 +362,7 @@ public void testMemberOfFunction27() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction28() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -373,28 +373,28 @@ public void testMemberOfFunction28() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction29() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of(ENGLISH_US), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction30() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of("invalidLanguageCode"), "$this.memberOf('" + MemberOfFunction.ALL_LANG_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction31() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(Code.of(UNITS_PER_LITER), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction32() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -412,7 +412,7 @@ public void testMemberOfFunction33() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction34() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -423,7 +423,7 @@ public void testMemberOfFunction34() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(coding, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction35() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -447,7 +447,7 @@ public void testMemberOfFunction36() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction37() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -460,7 +460,7 @@ public void testMemberOfFunction37() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(codeableConcept, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction38() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -484,7 +484,7 @@ public void testMemberOfFunction39() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction40() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -495,7 +495,7 @@ public void testMemberOfFunction40() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction41() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand All @@ -506,21 +506,21 @@ public void testMemberOfFunction41() throws Exception {
Collection<FHIRPathNode> result = evaluator.evaluate(quantity, "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction42() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of(UNITS_PER_LITER), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_TRUE);
}

@Test
public void testMemberOfFunction43() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Collection<FHIRPathNode> result = evaluator.evaluate(com.ibm.fhir.model.type.String.of("invalid ucum code"), "$this.memberOf('" + MemberOfFunction.UCUM_UNITS_VALUE_SET_URL + "')");
Assert.assertEquals(result, SINGLETON_FALSE);
}

@Test
public void testMemberOfFunction44() throws Exception {
FHIRPathEvaluator evaluator = FHIRPathEvaluator.evaluator();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,14 @@ private String generatePatternValueConstraint(Node node, boolean discriminator)
sb.append(cardinality(node, sb.toString()));
}
} else if (pattern.is(Uri.class)) {
sb.append(identifier).append(" = '").append(pattern.as(Uri.class).getValue()).append("'");
if (isSlice(elementDefinition) && hasDiscriminatorPath(elementDefinition, "$this")) {
sb.append(identifier).append(".where($this = '").append(pattern.as(Uri.class).getValue()).append("')");
if (!discriminator) {
sb.append(cardinality(node, sb.toString()));
}
} else {
sb.append(identifier).append(" = '").append(pattern.as(Uri.class).getValue()).append("'");
}
} else if (pattern.is(Code.class)) {
sb.append(identifier).append(" = '").append(pattern.as(Code.class).getValue()).append("'");
}
Expand Down Expand Up @@ -797,6 +804,18 @@ private boolean hasConstraint(Node node) {
return false;
}

private boolean hasDiscriminatorPath(ElementDefinition slice, String path) {
ElementDefinition sliceDefinition = getSliceDefinition(slice);
if (sliceDefinition != null) {
Slicing slicing = sliceDefinition.getSlicing();
List<String> paths = slicing.getDiscriminator().stream()
.map(discriminator -> discriminator.getPath().getValue())
.collect(Collectors.toList());
return paths.size() == 1 && path.equals(paths.get(0));
}
return false;
}

private boolean hasExtensionConstraint(ElementDefinition elementDefinition) {
List<Type> types = getTypes(elementDefinition);

Expand Down