use of org.hl7.fhir.utilities.graphql.Argument in project pathling by aehrc.
the class SubsumesFunctionTest method createNullCodingArg.
CodingPath createNullCodingArg() {
final Dataset<Row> dataset = new DatasetBuilder(spark).withIdColumn().withStructTypeColumns(codingStructType()).withIdValueRows(ALL_RES_IDS, id -> null).buildWithStructValue();
final ElementPath argument = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.CODING).dataset(dataset).idAndValueColumns().build();
return (CodingPath) argument;
}
use of org.hl7.fhir.utilities.graphql.Argument in project pathling by aehrc.
the class SubsumesFunctionTest method createCodingArg.
CodingPath createCodingArg() {
final Dataset<Row> dataset = new DatasetBuilder(spark).withIdColumn().withStructTypeColumns(codingStructType()).withIdValueRows(ALL_RES_IDS, id -> rowFromCoding(CODING_MEDIUM)).withIdValueRows(ALL_RES_IDS, id -> rowFromCoding(CODING_OTHER3)).buildWithStructValue();
final ElementPath argument = new ElementPathBuilder(spark).fhirType(FHIRDefinedType.CODING).dataset(dataset).idAndValueColumns().build();
return (CodingPath) argument;
}
use of org.hl7.fhir.utilities.graphql.Argument in project pathling by aehrc.
the class ValueSetMapping method toIntersection.
/**
* Constructs a {@link ValueSet} representing the intersection of a set of codings and a server
*
* @param valueSetUri the server defined value set.
* @param codings the set of codings to intersect.
* @return the intersection value set.
*/
@Nonnull
public static ValueSet toIntersection(@Nonnull final String valueSetUri, @Nonnull final Collection<SimpleCoding> codings) {
final Set<CodeSystemReference> validCodeSystems = codings.stream().filter(SimpleCoding::isDefined).map(coding -> new CodeSystemReference(Optional.ofNullable(coding.getSystem()), Optional.ofNullable(coding.getVersion()))).collect(Collectors.toUnmodifiableSet());
// Create a ValueSet to represent the intersection of the input codings and the ValueSet
// described by the URI in the argument.
final ValueSet intersection = new ValueSet();
final ValueSetComposeComponent compose = new ValueSetComposeComponent();
final List<ConceptSetComponent> includes = new ArrayList<>();
// Create an include section for each unique code system present within the input codings.
for (final CodeSystemReference codeSystem : validCodeSystems) {
final ConceptSetComponent include = new ConceptSetComponent();
include.setValueSet(Collections.singletonList(new CanonicalType(valueSetUri)));
// noinspection OptionalGetWithoutIsPresent
include.setSystem(codeSystem.getSystem().get());
codeSystem.getVersion().ifPresent(include::setVersion);
// Add the codings that match the current code system.
final List<ConceptReferenceComponent> concepts = codings.stream().filter(codeSystem::matchesCoding).map(SimpleCoding::getCode).filter(Objects::nonNull).distinct().map(code -> {
final ConceptReferenceComponent concept = new ConceptReferenceComponent();
concept.setCode(code);
return concept;
}).collect(Collectors.toList());
if (!concepts.isEmpty()) {
include.setConcept(concepts);
includes.add(include);
}
}
compose.setInclude(includes);
intersection.setCompose(compose);
return intersection;
}
use of org.hl7.fhir.utilities.graphql.Argument in project clinical_quality_language by cqframework.
the class Cql2ElmVisitor method visitRetrieve.
@Override
@SuppressWarnings("unchecked")
public Retrieve visitRetrieve(cqlParser.RetrieveContext ctx) {
libraryBuilder.checkLiteralContext();
List<String> qualifiers = parseQualifiers(ctx.namedTypeSpecifier());
String model = getModelIdentifier(qualifiers);
String label = getTypeIdentifier(qualifiers, parseString(ctx.namedTypeSpecifier().referentialOrTypeNameIdentifier()));
DataType dataType = libraryBuilder.resolveTypeName(model, label);
if (dataType == null) {
// ERROR:
throw new IllegalArgumentException(String.format("Could not resolve type name %s.", label));
}
if (!(dataType instanceof ClassType) || !((ClassType) dataType).isRetrievable()) {
// ERROR:
throw new IllegalArgumentException(String.format("Specified data type %s does not support retrieval.", label));
}
ClassType classType = (ClassType) dataType;
// BTR -> The original intent of this code was to have the retrieve return the base type, and use the "templateId"
// element of the retrieve to communicate the "positive" or "negative" profile to the data access layer.
// However, because this notion of carrying the "profile" through a type is not general, it causes inconsistencies
// when using retrieve results with functions defined in terms of the same type (see GitHub Issue #131).
// Based on the discussion there, the retrieve will now return the declared type, whether it is a profile or not.
// ProfileType profileType = dataType instanceof ProfileType ? (ProfileType)dataType : null;
// NamedType namedType = profileType == null ? classType : (NamedType)classType.getBaseType();
NamedType namedType = classType;
ModelInfo modelInfo = libraryBuilder.getModel(namedType.getNamespace()).getModelInfo();
boolean useStrictRetrieveTyping = modelInfo.isStrictRetrieveTyping() != null && modelInfo.isStrictRetrieveTyping();
Retrieve retrieve = of.createRetrieve().withDataType(libraryBuilder.dataTypeToQName((DataType) namedType)).withTemplateId(classType.getIdentifier());
if (ctx.contextIdentifier() != null) {
List<String> identifiers = (List<String>) visit(ctx.contextIdentifier());
Expression contextExpression = resolveQualifiedIdentifier(identifiers);
retrieve.setContext(contextExpression);
}
if (ctx.terminology() != null) {
if (ctx.codePath() != null) {
String identifiers = (String) visit(ctx.codePath());
retrieve.setCodeProperty(identifiers);
} else if (classType.getPrimaryCodePath() != null) {
retrieve.setCodeProperty(classType.getPrimaryCodePath());
}
Property property = null;
CqlCompilerException propertyException = null;
if (retrieve.getCodeProperty() == null) {
// ERROR:
// WARNING:
propertyException = new CqlSemanticException("Retrieve has a terminology target but does not specify a code path and the type of the retrieve does not have a primary code path defined.", useStrictRetrieveTyping ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx));
libraryBuilder.recordParsingException(propertyException);
} else {
try {
DataType codeType = libraryBuilder.resolvePath((DataType) namedType, retrieve.getCodeProperty());
property = of.createProperty().withPath(retrieve.getCodeProperty());
property.setResultType(codeType);
} catch (Exception e) {
// ERROR:
// WARNING:
propertyException = new CqlSemanticException(String.format("Could not resolve code path %s for the type of the retrieve %s.", retrieve.getCodeProperty(), namedType.getName()), useStrictRetrieveTyping ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx), e);
libraryBuilder.recordParsingException(propertyException);
}
}
Expression terminology = null;
if (ctx.terminology().qualifiedIdentifierExpression() != null) {
List<String> identifiers = (List<String>) visit(ctx.terminology());
terminology = resolveQualifiedIdentifier(identifiers);
track(terminology, ctx.terminology().qualifiedIdentifierExpression());
} else {
terminology = parseExpression(ctx.terminology().expression());
}
String codeComparator = ctx.codeComparator() != null ? (String) visit(ctx.codeComparator()) : null;
// Resolve the terminology target using an in or ~ operator
try {
if (codeComparator == null) {
codeComparator = (terminology.getResultType() instanceof ListType || (libraryBuilder.isCompatibleWith("1.5") && terminology.getResultType().isSubTypeOf(libraryBuilder.resolveTypeName("System", "Vocabulary")))) ? "in" : "~";
}
if (property == null) {
throw propertyException;
}
switch(codeComparator) {
case "in":
{
Expression in = libraryBuilder.resolveIn(property, terminology);
if (in instanceof In) {
retrieve.setCodes(((In) in).getOperand().get(1));
} else if (in instanceof InValueSet) {
retrieve.setCodes(((InValueSet) in).getValueset());
} else if (in instanceof InCodeSystem) {
retrieve.setCodes(((InCodeSystem) in).getCodesystem());
} else if (in instanceof AnyInValueSet) {
retrieve.setCodes(((AnyInValueSet) in).getValueset());
} else if (in instanceof AnyInCodeSystem) {
retrieve.setCodes(((AnyInCodeSystem) in).getCodesystem());
} else {
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Unexpected membership operator %s in retrieve", in.getClass().getSimpleName()), useStrictRetrieveTyping ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
}
break;
case "~":
{
// Resolve with equivalent to verify the type of the target
BinaryExpression equivalent = of.createEquivalent().withOperand(property, terminology);
libraryBuilder.resolveBinaryCall("System", "Equivalent", equivalent);
// Automatically promote to a list for use in the retrieve target
if (!(equivalent.getOperand().get(1).getResultType() instanceof ListType)) {
retrieve.setCodes(libraryBuilder.resolveToList(equivalent.getOperand().get(1)));
} else {
retrieve.setCodes(equivalent.getOperand().get(1));
}
}
break;
case "=":
{
// Resolve with equality to verify the type of the source and target
BinaryExpression equal = of.createEqual().withOperand(property, terminology);
libraryBuilder.resolveBinaryCall("System", "Equal", equal);
// Automatically promote to a list for use in the retrieve target
if (!(equal.getOperand().get(1).getResultType() instanceof ListType)) {
retrieve.setCodes(libraryBuilder.resolveToList(equal.getOperand().get(1)));
} else {
retrieve.setCodes(equal.getOperand().get(1));
}
}
break;
default:
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException(String.format("Unknown code comparator % in retrieve", codeComparator), useStrictRetrieveTyping ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx.codeComparator())));
}
retrieve.setCodeComparator(codeComparator);
// In that case, convert to a list of code (Union the Code elements of the Concepts in the list)
if (retrieve.getCodes() != null && retrieve.getCodes().getResultType() != null && retrieve.getCodes().getResultType() instanceof ListType && ((ListType) retrieve.getCodes().getResultType()).getElementType().equals(libraryBuilder.resolveTypeName("System", "Concept"))) {
if (retrieve.getCodes() instanceof ToList) {
// ToList will always have a single argument
ToList toList = (ToList) retrieve.getCodes();
// If that argument is a ToConcept, replace the ToList argument with the code (skip the implicit conversion, the data access layer is responsible for it)
if (toList.getOperand() instanceof ToConcept) {
toList.setOperand(((ToConcept) toList.getOperand()).getOperand());
} else {
// Otherwise, access the codes property of the resulting Concept
Expression codesAccessor = libraryBuilder.buildProperty(toList.getOperand(), "codes", false, toList.getOperand().getResultType());
retrieve.setCodes(codesAccessor);
}
} else {
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException("Terminology target is a list of concepts, but expects a list of codes", CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx)));
}
}
} catch (Exception e) {
// it shouldn't prevent translation unless the modelinfo indicates strict retrieve typing
if ((libraryBuilder.isCompatibleWith("1.5") && !(terminology.getResultType().isSubTypeOf(libraryBuilder.resolveTypeName("System", "Vocabulary")))) || (!libraryBuilder.isCompatibleWith("1.5") && !(terminology.getResultType() instanceof ListType))) {
retrieve.setCodes(libraryBuilder.resolveToList(terminology));
} else {
retrieve.setCodes(terminology);
}
retrieve.setCodeComparator(codeComparator);
// ERROR:
// WARNING:
libraryBuilder.recordParsingException(new CqlSemanticException("Could not resolve membership operator for terminology target of the retrieve.", useStrictRetrieveTyping ? CqlCompilerException.ErrorSeverity.Error : CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx), e));
}
}
retrieves.add(retrieve);
retrieve.setResultType(new ListType((DataType) namedType));
return retrieve;
}
use of org.hl7.fhir.utilities.graphql.Argument in project quality-measure-and-cohort-service by Alvearie.
the class AnyColumnVisitor method visitFunctionRef.
@Override
public Object visitFunctionRef(FunctionRef elm, AnyColumnContext context) {
if (AnyColumnFunctions.FUNCTION_NAMES.contains(elm.getName())) {
if (elm.getOperand().size() == 2) {
QName dataType = ((As) elm.getOperand().get(0)).getOperand().getResultTypeName();
// TODO - validate that the first operand is a model object. We really should be doing that at the
// method declaration level instead of Choice<Any>, but that will require the model
// to have a base class that everything extends from.
String columnMatchLogic = null;
if (elm.getOperand().get(1) instanceof Literal) {
columnMatchLogic = ((Literal) elm.getOperand().get(1)).getValue();
} else {
throw new IllegalArgumentException(String.format("Second argument to %s function at %s must be a literal", elm.getName(), elm.getLocator()));
}
StringMatcher matcher = null;
if (elm.getName().equals(AnyColumnFunctions.FUNC_ANY_COLUMN)) {
matcher = new PrefixStringMatcher(columnMatchLogic);
} else if (elm.getName().equals(AnyColumnFunctions.FUNC_ANY_COLUMN_REGEX)) {
matcher = new RegexStringMatcher(columnMatchLogic);
} else {
throw new IllegalArgumentException(String.format("Found declared, but unsupported AnyColumn function %s at %s", elm.getName(), elm.getLocator()));
}
context.reportAnyColumn(dataType, matcher);
} else {
throw new IllegalArgumentException(String.format("%s function at %s should have exactly two arguments", elm.getName(), elm.getLocator()));
}
}
return super.visitFunctionRef(elm, context);
}
Aggregations