diff --git a/Src/java/cql-to-elm-jackson/src/main/java/org/cqframework/cql/cq2elm/CqlTranslatorOptionsMapper.kt b/Src/java/cql-to-elm-jackson/src/main/java/org/cqframework/cql/cq2elm/CqlTranslatorOptionsMapper.kt index 9b37e069a..3952b6673 100644 --- a/Src/java/cql-to-elm-jackson/src/main/java/org/cqframework/cql/cq2elm/CqlTranslatorOptionsMapper.kt +++ b/Src/java/cql-to-elm-jackson/src/main/java/org/cqframework/cql/cq2elm/CqlTranslatorOptionsMapper.kt @@ -22,9 +22,7 @@ object CqlTranslatorOptionsMapper { return fromReader(fr) } catch (@Suppress("SwallowedException") e: IOException) { @Suppress("TooGenericExceptionThrown") - throw RuntimeException( - String.format(Locale.US, "Errors occurred reading options: %s", e.message) - ) + throw RuntimeException("Errors occurred reading options: ${e.message}", e) } } @@ -34,9 +32,7 @@ object CqlTranslatorOptionsMapper { return om.readValue(reader, CqlTranslatorOptions::class.java) } catch (@Suppress("SwallowedException") e: IOException) { @Suppress("TooGenericExceptionThrown") - throw RuntimeException( - String.format(Locale.US, "Errors occurred reading options: %s", e.message) - ) + throw RuntimeException("Errors occurred reading options: ${e.message}", e) } } @@ -48,9 +44,7 @@ object CqlTranslatorOptionsMapper { toWriter(fw, options) } catch (@Suppress("SwallowedException") e: IOException) { @Suppress("TooGenericExceptionThrown") - throw RuntimeException( - String.format(Locale.US, "Errors occurred writing options: %s", e.message) - ) + throw RuntimeException("Errors occurred writing options: ${e.message}", e) } } @@ -61,9 +55,7 @@ object CqlTranslatorOptionsMapper { om.writeValue(writer, options) } catch (@Suppress("SwallowedException") e: IOException) { @Suppress("TooGenericExceptionThrown") - throw RuntimeException( - String.format(Locale.US, "Errors occurred writing options: %s", e.message) - ) + throw RuntimeException("Errors occurred writing options: ${e.message}", e) } } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CompilerOptions.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CompilerOptions.kt index 3c3a98522..f2d807722 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CompilerOptions.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CompilerOptions.kt @@ -38,7 +38,7 @@ object CompilerOptions { /** * Parses a string representing CQL compiler Options into an EnumSet. The string is expected to - * be a comma delimited list of values from the CqlCompiler.Options enumeration. For example + * be a comma-delimited list of values from the CqlCompiler.Options enumeration. For example * "EnableListPromotion, EnableListDemotion". * * @param compilerOptions the string to parse diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/Cql2ElmVisitor.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/Cql2ElmVisitor.kt index e17ab01cd..14ddca105 100755 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/Cql2ElmVisitor.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/Cql2ElmVisitor.kt @@ -73,6 +73,10 @@ class Cql2ElmVisitor( return null } + private inline fun Any?.cast(): T { + return this as T + } + override fun visitLibrary(ctx: LibraryContext): Any? { var lastResult: Any? = null @@ -96,14 +100,13 @@ class Cql2ElmVisitor( } override fun visitLibraryDefinition(ctx: LibraryDefinitionContext): VersionedIdentifier { - val identifiers = visit(ctx.qualifiedIdentifier()) as MutableList + val identifiers: MutableList = visit(ctx.qualifiedIdentifier()).cast() val vid = of.createVersionedIdentifier() .withId(identifiers.removeAt(identifiers.size - 1)) .withVersion(parseString(ctx.versionSpecifier())) if (identifiers.isNotEmpty()) { - vid.system = - libraryBuilder.resolveNamespaceUri(java.lang.String.join(".", identifiers), true) + vid.system = libraryBuilder.resolveNamespaceUri(identifiers.joinToString("."), true) } else if (libraryBuilder.namespaceInfo != null) { vid.system = libraryBuilder.namespaceInfo.uri } @@ -112,13 +115,15 @@ class Cql2ElmVisitor( } override fun visitUsingDefinition(ctx: UsingDefinitionContext): UsingDef? { - val identifiers = visit(ctx.qualifiedIdentifier()) as MutableList + val identifiers: MutableList = visit(ctx.qualifiedIdentifier()).cast() val unqualifiedIdentifier: String = identifiers.removeAt(identifiers.size - 1) val namespaceName = - if (identifiers.isNotEmpty()) java.lang.String.join(".", identifiers) - else if (libraryBuilder.isWellKnownModelName(unqualifiedIdentifier)) null - else if (libraryBuilder.namespaceInfo != null) libraryBuilder.namespaceInfo.name - else null + when { + identifiers.isNotEmpty() -> java.lang.String.join(".", identifiers) + libraryBuilder.isWellKnownModelName(unqualifiedIdentifier) -> null + libraryBuilder.namespaceInfo != null -> libraryBuilder.namespaceInfo.name + else -> null + } var path: String? = null var modelNamespace: NamespaceInfo? = null if (namespaceName != null) { @@ -132,12 +137,7 @@ class Cql2ElmVisitor( if (ctx.localIdentifier() == null) unqualifiedIdentifier else parseString(ctx.localIdentifier())!! require(localIdentifier == unqualifiedIdentifier) { - String.format( - Locale.US, - "Local identifiers for models must be the same as the name of the model in this release of the translator (Model %s, Called %s)", - unqualifiedIdentifier, - localIdentifier - ) + "Local identifiers for models must be the same as the name of the model in this release of the translator (Model $unqualifiedIdentifier, Called $localIdentifier)" } // The model was already calculated by CqlPreprocessorVisitor @@ -157,7 +157,7 @@ class Cql2ElmVisitor( return libraryBuilder.getModel(modelIdentifier, localIdentifier) } - private fun getLibraryPath(namespaceName: String?, unqualifiedIdentifier: String): String? { + private fun getLibraryPath(namespaceName: String?, unqualifiedIdentifier: String): String { if (namespaceName != null) { val namespaceUri = libraryBuilder.resolveNamespaceUri(namespaceName, true) return NamespaceManager.getPath(namespaceUri, unqualifiedIdentifier) @@ -165,8 +165,8 @@ class Cql2ElmVisitor( return unqualifiedIdentifier } - override fun visitIncludeDefinition(ctx: IncludeDefinitionContext): Any? { - val identifiers = visit(ctx.qualifiedIdentifier()) as MutableList + override fun visitIncludeDefinition(ctx: IncludeDefinitionContext): IncludeDef { + val identifiers: MutableList = visit(ctx.qualifiedIdentifier()).cast() val unqualifiedIdentifier: String = identifiers.removeAt(identifiers.size - 1) var namespaceName = if (identifiers.isNotEmpty()) java.lang.String.join(".", identifiers) @@ -191,10 +191,12 @@ class Cql2ElmVisitor( // with the namespace if (!libraryBuilder.canResolveLibrary(library)) { namespaceName = - if (identifiers.size > 0) java.lang.String.join(".", identifiers) - else if (libraryBuilder.isWellKnownLibraryName(unqualifiedIdentifier)) null - else if (libraryBuilder.namespaceInfo != null) libraryBuilder.namespaceInfo.name - else null + when { + identifiers.isNotEmpty() -> java.lang.String.join(".", identifiers) + libraryBuilder.isWellKnownLibraryName(unqualifiedIdentifier) -> null + libraryBuilder.namespaceInfo != null -> libraryBuilder.namespaceInfo.name + else -> null + } path = getLibraryPath(namespaceName, unqualifiedIdentifier) library = of.createIncludeDef() @@ -210,7 +212,7 @@ class Cql2ElmVisitor( return library } - override fun visitParameterDefinition(ctx: ParameterDefinitionContext): ParameterDef? { + override fun visitParameterDefinition(ctx: ParameterDefinitionContext): ParameterDef { val param = of.createParameterDef() .withAccessLevel(parseAccessModifier(ctx.accessModifier())) @@ -229,11 +231,7 @@ class Cql2ElmVisitor( } } requireNotNull(paramType) { - String.format( - Locale.US, - "Could not determine parameter type for parameter %s.", - param.name - ) + "Could not determine parameter type for parameter ${param.name}." } param.resultType = paramType if (param.default != null) { @@ -260,11 +258,7 @@ class Cql2ElmVisitor( "private" -> AccessModifier.PRIVATE else -> throw IllegalArgumentException( - String.format( - Locale.US, - "Unknown access modifier %s.", - ctx.text.lowercase(Locale.getDefault()) - ) + "Unknown access modifier ${ctx.text.lowercase(Locale.getDefault())}." ) } } @@ -275,7 +269,7 @@ class Cql2ElmVisitor( .withAccessLevel(parseAccessModifier(ctx.accessModifier())) .withName(parseString(ctx.identifier())) .withId(parseString(ctx.codesystemId())) - .withVersion(parseString(ctx.versionSpecifier())) as CodeSystemDef + .withVersion(parseString(ctx.versionSpecifier())) if (libraryBuilder.isCompatibleWith("1.5")) { cs.resultType = libraryBuilder.resolveTypeName("System", "CodeSystem") } else { @@ -296,14 +290,11 @@ class Cql2ElmVisitor( } else { def = libraryBuilder.resolveCodeSystemRef(name) } - requireNotNull(def) { - // ERROR: - String.format(Locale.US, "Could not resolve reference to code system %s.", name) - } + requireNotNull(def) { "Could not resolve reference to code system $name." } return of.createCodeSystemRef() .withLibraryName(libraryName) .withName(name) - .withResultType(def.resultType) as CodeSystemRef + .withResultType(def.resultType) } override fun visitCodeIdentifier(ctx: CodeIdentifierContext): CodeRef { @@ -316,19 +307,17 @@ class Cql2ElmVisitor( } else { def = libraryBuilder.resolveCodeRef(name) } - if (def == null) { + requireNotNull(def) { // ERROR: - throw IllegalArgumentException( - String.format(Locale.US, "Could not resolve reference to code %s.", name) - ) + "Could not resolve reference to code $name." } return of.createCodeRef() .withLibraryName(libraryName) .withName(name) - .withResultType(def.resultType) as CodeRef + .withResultType(def.resultType) } - override fun visitValuesetDefinition(ctx: ValuesetDefinitionContext): ValueSetDef? { + override fun visitValuesetDefinition(ctx: ValuesetDefinitionContext): ValueSetDef { val vs = of.createValueSetDef() .withAccessLevel(parseAccessModifier(ctx.accessModifier())) @@ -340,11 +329,7 @@ class Cql2ElmVisitor( val cs = visit(codesystem) as CodeSystemRef? ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve reference to code system %s.", - codesystem.text - ) + "Could not resolve reference to code system ${codesystem.text}." ) vs.codeSystem.add(cs) } @@ -359,7 +344,7 @@ class Cql2ElmVisitor( return vs } - override fun visitCodeDefinition(ctx: CodeDefinitionContext): CodeDef? { + override fun visitCodeDefinition(ctx: CodeDefinitionContext): CodeDef { val cd = of.createCodeDef() .withAccessLevel(parseAccessModifier(ctx.accessModifier())) @@ -375,7 +360,7 @@ class Cql2ElmVisitor( return cd } - override fun visitConceptDefinition(ctx: ConceptDefinitionContext): ConceptDef? { + override fun visitConceptDefinition(ctx: ConceptDefinitionContext): ConceptDef { val cd = of.createConceptDef() .withAccessLevel(parseAccessModifier(ctx.accessModifier())) @@ -397,9 +382,7 @@ class Cql2ElmVisitor( val identifier = getTypeIdentifier(qualifiers, parseString(ctx.referentialOrTypeNameIdentifier())!!) val retrievedResult = - libraryBuilder.getNamedTypeSpecifierResult( - String.format(Locale.US, "%s:%s", modelIdentifier, identifier) - ) + libraryBuilder.getNamedTypeSpecifierResult("$modelIdentifier:$identifier") if (retrievedResult != null) { return if (retrievedResult.hasError()) { null @@ -408,12 +391,7 @@ class Cql2ElmVisitor( val resultType = libraryBuilder.resolveTypeName(modelIdentifier, identifier) ?: throw CqlCompilerException( - String.format( - Locale.US, - "Could not find type for model: %s and name: %s", - modelIdentifier, - identifier - ), + "Could not find type for model: $modelIdentifier and name: $identifier", getTrackBack(ctx) ) val result = @@ -521,16 +499,17 @@ class Cql2ElmVisitor( } } - fun internalVisitExpressionDefinition(ctx: ExpressionDefinitionContext): ExpressionDef? { + private fun internalVisitExpressionDefinition( + ctx: ExpressionDefinitionContext + ): ExpressionDef? { val identifier = parseString(ctx.identifier())!! var def = libraryBuilder.resolveExpressionRef(identifier) // First time visiting this expression definition, create a lightweight ExpressionDef to be - // used to output a - // hiding warning message - // If it's the second time around, we'll be able to resolve it and we can assume it's - // already on the - // hiding stack. + // used to output a hiding warning message + // + // If it's the second time around, we'll be able to resolve it, + // and we can assume it's already on the hiding stack. if (def == null) { val hollowExpressionDef = of.createExpressionDef().withName(identifier).withContext(currentContext) @@ -540,7 +519,6 @@ class Cql2ElmVisitor( if (def != null && isImplicitContextExpressionDef(def)) { libraryBuilder.removeExpression(def) removeImplicitContextExpressionDef(def) - def = null } libraryBuilder.pushExpressionContext(currentContext) try { @@ -571,15 +549,9 @@ class Cql2ElmVisitor( return try { val expressionDef = internalVisitExpressionDefinition(ctx) if (forwards.isEmpty() || forwards.peek().name != expressionDef!!.name) { - if (definedExpressionDefinitions.contains(expressionDef!!.name)) { + require(!definedExpressionDefinitions.contains(expressionDef!!.name)) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Identifier %s is already in use in this library.", - expressionDef.name - ) - ) + "Identifier ${expressionDef.name} is already in use in this library." } // Track defined expression definitions locally, otherwise duplicate expression @@ -619,7 +591,7 @@ class Cql2ElmVisitor( ) } - override fun visitTupleElementSelector(ctx: TupleElementSelectorContext): Any? { + override fun visitTupleElementSelector(ctx: TupleElementSelectorContext): TupleElement { val result = of.createTupleElement() .withName(parseString(ctx.referentialIdentifier())) @@ -627,7 +599,7 @@ class Cql2ElmVisitor( return result } - override fun visitTupleSelector(ctx: TupleSelectorContext): Any? { + override fun visitTupleSelector(ctx: TupleSelectorContext): Tuple { val tuple = of.createTuple() val elements = mutableListOf() for (elementContext in ctx.tupleElementSelector()) { @@ -639,14 +611,16 @@ class Cql2ElmVisitor( return tuple } - override fun visitInstanceElementSelector(ctx: InstanceElementSelectorContext): Any? { + override fun visitInstanceElementSelector( + ctx: InstanceElementSelectorContext + ): InstanceElement { val name = parseString(ctx.referentialIdentifier()) val exp = parseExpression(ctx.expression()) val result = of.createInstanceElement().withName(name).withValue(exp) return result } - override fun visitInstanceSelector(ctx: InstanceSelectorContext): Any { + override fun visitInstanceSelector(ctx: InstanceSelectorContext): Instance { val instance: Instance = of.createInstance() val classTypeSpecifier = visitNamedTypeSpecifier(ctx.namedTypeSpecifier())!! instance.classType = classTypeSpecifier.name @@ -665,7 +639,7 @@ class Cql2ElmVisitor( return instance } - override fun visitCodeSelector(ctx: CodeSelectorContext): Any? { + override fun visitCodeSelector(ctx: CodeSelectorContext): Code { val code = of.createCode() code.code = parseString(ctx.STRING()) code.system = visit(ctx.codesystemIdentifier()) as CodeSystemRef? @@ -676,7 +650,7 @@ class Cql2ElmVisitor( return code } - override fun visitConceptSelector(ctx: ConceptSelectorContext): Any? { + override fun visitConceptSelector(ctx: ConceptSelectorContext): Concept { val concept = of.createConcept() if (ctx.displayClause() != null) { concept.display = parseString(ctx.displayClause()!!.STRING()) @@ -688,7 +662,7 @@ class Cql2ElmVisitor( return concept } - override fun visitListSelector(ctx: ListSelectorContext): Any? { + override fun visitListSelector(ctx: ListSelectorContext): org.hl7.elm.r1.List { val elementTypeSpecifier = parseTypeSpecifier(ctx.typeSpecifier()) val list = of.createList() var listType: ListType? = null @@ -743,7 +717,12 @@ class Cql2ElmVisitor( for (element in elements) { if (!elementType!!.isSuperTypeOf(element.resultType!!)) { val conversion = - libraryBuilder.findConversion(element.resultType!!, elementType, true, false) + libraryBuilder.findConversion( + element.resultType!!, + elementType, + implicit = true, + allowPromotionAndDemotion = false + ) if (conversion != null) { list.element.add(libraryBuilder.convertExpression(element, conversion)) } else { @@ -760,7 +739,7 @@ class Cql2ElmVisitor( return list } - override fun visitTimeLiteral(ctx: TimeLiteralContext): Any? { + override fun visitTimeLiteral(ctx: TimeLiteralContext): Time { var input = ctx.text if (input.startsWith("@")) { input = input.substring(1) @@ -775,40 +754,26 @@ class Cql2ElmVisitor( var minute = -1 var second = -1 var millisecond = -1 - if (hour < 0 || hour > 24) { - throw IllegalArgumentException( - String.format(Locale.US, "Invalid hour in time literal (%s).", input) - ) - } + require(hour in 0..24) { "Invalid hour in time literal ($hour)." } result.hour = libraryBuilder.createLiteral(hour) if (matcher.group(3) != null) { minute = matcher.group(3).toInt() - if ((minute < 0) || (minute >= 60) || (hour == 24 && minute > 0)) { - throw IllegalArgumentException( - String.format(Locale.US, "Invalid minute in time literal (%s).", input) - ) + require(!((minute < 0) || (minute >= 60) || (hour == 24 && minute > 0))) { + "Invalid minute in time literal ($minute)." } result.minute = libraryBuilder.createLiteral(minute) } if (matcher.group(5) != null) { second = matcher.group(5).toInt() - if ((second < 0) || (second >= 60) || (hour == 24 && second > 0)) { - throw IllegalArgumentException( - String.format(Locale.US, "Invalid second in time literal (%s).", input) - ) + require(!((second < 0) || (second >= 60) || (hour == 24 && second > 0))) { + "Invalid second in time literal ($second)." } result.second = libraryBuilder.createLiteral(second) } if (matcher.group(7) != null) { millisecond = matcher.group(7).toInt() - if (millisecond < 0 || (hour == 24 && millisecond > 0)) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid millisecond in time literal (%s).", - input - ) - ) + require(hour == 24 && millisecond == 0 || millisecond >= 0) { + "Invalid millisecond in time literal ($millisecond)." } result.millisecond = libraryBuilder.createLiteral(millisecond) } @@ -816,21 +781,14 @@ class Cql2ElmVisitor( result } catch (e: RuntimeException) { throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid time input (%s). Use ISO 8601 time representation (hh:mm:ss.fff).", - input - ), + "Invalid time input ($input). Use ISO 8601 time representation (hh:mm:ss.fff).", e ) } } else { + @Suppress("UseRequire") throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid time input (%s). Use ISO 8601 time representation (hh:mm:ss.fff).", - input - ) + "Invalid time input ($input). Use ISO 8601 time representation (hh:mm:ss.fff)." ) } } @@ -905,15 +863,7 @@ class Cql2ElmVisitor( result.year = libraryBuilder.createLiteral(year) if (matcher.group(5) != null) { month = matcher.group(5).toInt() - if (month < 0 || month > 12) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid month in date/time literal (%s).", - input - ) - ) - } + require(month in 0..12) { "Invalid month in date/time literal ($input)." } result.month = libraryBuilder.createLiteral(month) } if (matcher.group(9) != null) { @@ -925,68 +875,33 @@ class Cql2ElmVisitor( 6, 9, 11 -> maxDay = 30 - else -> {} - } - if (day < 0 || day > maxDay) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid day in date/time literal (%s).", - input - ) - ) } + require(day in 0..maxDay) { "Invalid day in date/time literal ($input)." } result.day = libraryBuilder.createLiteral(day) } if (matcher.group(13) != null) { hour = matcher.group(13).toInt() - if (hour < 0 || hour > 24) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid hour in date/time literal (%s).", - input - ) - ) - } + require(hour in 0..24) { "Invalid hour in date/time literal ($input)." } result.hour = libraryBuilder.createLiteral(hour) } if (matcher.group(15) != null) { minute = matcher.group(15).toInt() - if ((minute < 0) || (minute >= 60) || (hour == 24 && minute > 0)) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid minute in date/time literal (%s).", - input - ) - ) + require(minute in 0..60 && !(hour == 24 && minute > 0)) { + "Invalid minute in date/time literal ($input)." } result.minute = libraryBuilder.createLiteral(minute) } if (matcher.group(17) != null) { second = matcher.group(17).toInt() - if ((second < 0) || (second >= 60) || (hour == 24 && second > 0)) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid second in date/time literal (%s).", - input - ) - ) + require(second in 0..60 && !(hour == 24 && second > 0)) { + "Invalid second in date/time literal ($input)." } result.second = libraryBuilder.createLiteral(second) } if (matcher.group(19) != null) { millisecond = matcher.group(19).toInt() - if (millisecond < 0 || (hour == 24 && millisecond > 0)) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid millisecond in date/time literal (%s).", - input - ) - ) + require(millisecond >= 0 && !(hour == 24 && millisecond > 0)) { + "Invalid millisecond in date/time literal ($input)." } result.millisecond = libraryBuilder.createLiteral(millisecond) } @@ -997,28 +912,12 @@ class Cql2ElmVisitor( val offsetPolarity = if ((matcher.group(25) == "+")) 1 else -1 if (matcher.group(28) != null) { val hourOffset = matcher.group(26).toInt() - if (hourOffset < 0 || hourOffset > 14) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Timezone hour offset is out of range in date/time literal (%s).", - input - ) - ) + require(hourOffset in 0..14) { + "Timezone hour offset is out of range in date/time literal ($input)." } val minuteOffset = matcher.group(28).toInt() - if ( - (minuteOffset < 0) || - (minuteOffset >= 60) || - (hourOffset == 14 && minuteOffset > 0) - ) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Timezone minute offset is out of range in date/time literal (%s).", - input - ) - ) + require(minuteOffset in 0..60 && !(hourOffset == 14 && minuteOffset > 0)) { + "Timezone minute offset is out of range in date/time literal ($input)." } result.timezoneOffset = libraryBuilder.createLiteral( @@ -1027,14 +926,8 @@ class Cql2ElmVisitor( } else { if (matcher.group(26) != null) { val hourOffset = matcher.group(26).toInt() - if (hourOffset < 0 || hourOffset > 14) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Timezone hour offset is out of range in date/time literal (%s).", - input - ) - ) + require(hourOffset in 0..14) { + "Timezone hour offset is out of range in date/time literal ($input)." } result.timezoneOffset = libraryBuilder.createLiteral( @@ -1060,23 +953,16 @@ class Cql2ElmVisitor( result } catch (e: RuntimeException) { throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid date-time input (%s). Use ISO 8601 date time representation (yyyy-MM-ddThh:mm:ss.fff(Z|(+/-hh:mm)).", - input - ), + "Invalid date-time input ($input)." + + " Use ISO 8601 date time representation (yyyy-MM-ddThh:mm:ss.fff(Z|(+/-hh:mm)).", e ) } - } else { + } else throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid date-time input (%s). Use ISO 8601 date time representation (yyyy-MM-ddThh:mm:ss.fff(Z|+/-hh:mm)).", - input - ) + "Invalid date-time input ($input)." + + " Use ISO 8601 date time representation (yyyy-MM-ddThh:mm:ss.fff(Z|+/-hh:mm))." ) - } } override fun visitDateLiteral(ctx: DateLiteralContext): Any { @@ -1095,7 +981,7 @@ class Cql2ElmVisitor( return parseDateTimeLiteral(input) } - override fun visitNullLiteral(ctx: NullLiteralContext): Null? { + override fun visitNullLiteral(ctx: NullLiteralContext): Null { val result = of.createNull() result.resultType = libraryBuilder.resolveTypeName("System", "Any") return result @@ -1121,9 +1007,7 @@ class Cql2ElmVisitor( return try { BigDecimal(value) } catch (@Suppress("SwallowedException") e: Exception) { - throw IllegalArgumentException( - String.format(Locale.US, "Could not parse number literal: %s", value) - ) + throw IllegalArgumentException("Could not parse number literal: $value") } } @@ -1147,19 +1031,19 @@ class Cql2ElmVisitor( throw IllegalArgumentException("Could not create quantity from source expression.") } - override fun visitRatio(ctx: RatioContext): Expression { + override fun visitRatio(ctx: RatioContext): Ratio { val numerator = getQuantity(visit(ctx.quantity(0)!!) as Expression?) val denominator = getQuantity(visit(ctx.quantity(1)!!) as Expression?) return libraryBuilder.createRatio(numerator, denominator) } - override fun visitNotExpression(ctx: NotExpressionContext): Not? { + override fun visitNotExpression(ctx: NotExpressionContext): Not { val result = of.createNot().withOperand(parseExpression(ctx.expression())) libraryBuilder.resolveUnaryCall("System", "Not", result) return result } - override fun visitExistenceExpression(ctx: ExistenceExpressionContext): Exists? { + override fun visitExistenceExpression(ctx: ExistenceExpressionContext): Exists { val result = of.createExists().withOperand(parseExpression(ctx.expression())) libraryBuilder.resolveUnaryCall("System", "Exists", result) return result @@ -1188,9 +1072,7 @@ class Cql2ElmVisitor( operatorName = "Modulo" } else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unsupported operator: %s.", ctx.getChild(1)!!.text) - ) + throw IllegalArgumentException("Unsupported operator: ${ctx.getChild(1)!!.text}.") } exp.withOperand( parseExpression(ctx.expressionTerm(0))!!, @@ -1200,7 +1082,7 @@ class Cql2ElmVisitor( return exp } - override fun visitPowerExpressionTerm(ctx: PowerExpressionTermContext): Power? { + override fun visitPowerExpressionTerm(ctx: PowerExpressionTermContext): Power { val power = of.createPower() .withOperand( @@ -1220,7 +1102,7 @@ class Cql2ElmVisitor( return result } - override fun visitAdditionExpressionTerm(ctx: AdditionExpressionTermContext): Expression? { + override fun visitAdditionExpressionTerm(ctx: AdditionExpressionTermContext): Expression { var exp: Expression? val operatorName: String? when (ctx.getChild(1)!!.text) { @@ -1237,9 +1119,7 @@ class Cql2ElmVisitor( operatorName = "Concatenate" } else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unsupported operator: %s.", ctx.getChild(1)!!.text) - ) + throw IllegalArgumentException("Unsupported operator: ${ctx.getChild(1)!!.text}.") } if (exp is BinaryExpression) { exp.withOperand( @@ -1254,7 +1134,7 @@ class Cql2ElmVisitor( exp = concatenate } } else { - val concatenate: Concatenate? = exp as Concatenate? + val concatenate = exp as Concatenate? concatenate!!.withOperand( parseExpression(ctx.expressionTerm(0))!!, parseExpression(ctx.expressionTerm(1))!! @@ -1283,13 +1163,15 @@ class Cql2ElmVisitor( override fun visitElementExtractorExpressionTerm( ctx: ElementExtractorExpressionTermContext - ): Any? { + ): SingletonFrom { val result = of.createSingletonFrom().withOperand(parseExpression(ctx.expressionTerm())) libraryBuilder.resolveUnaryCall("System", "SingletonFrom", result) return result } - override fun visitPointExtractorExpressionTerm(ctx: PointExtractorExpressionTermContext): Any? { + override fun visitPointExtractorExpressionTerm( + ctx: PointExtractorExpressionTermContext + ): PointFrom { val result = of.createPointFrom().withOperand(parseExpression(ctx.expressionTerm())) libraryBuilder.resolveUnaryCall("System", "PointFrom", result) return result @@ -1305,10 +1187,7 @@ class Cql2ElmVisitor( "maximum" -> { libraryBuilder.buildMaximum(targetType!!.resultType) } - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown extent: %s", extent) - ) + else -> throw IllegalArgumentException("Unknown extent: $extent") } } @@ -1327,7 +1206,11 @@ class Cql2ElmVisitor( } private fun parseComparableDateTimePrecision(dateTimePrecision: String): DateTimePrecision? { - return parseDateTimePrecision(dateTimePrecision, true, false) + return parseDateTimePrecision( + dateTimePrecision, + precisionRequired = true, + allowWeeks = false + ) } private fun parseComparableDateTimePrecision( @@ -1374,10 +1257,7 @@ class Cql2ElmVisitor( "ms", "millisecond", "milliseconds" -> DateTimePrecision.MILLISECOND - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown precision '%s'.", dateTimePrecision) - ) + else -> throw IllegalArgumentException("Unknown precision '$dateTimePrecision'.") } } @@ -1421,16 +1301,13 @@ class Cql2ElmVisitor( } "week" -> throw IllegalArgumentException("Date/time values do not have a week component.") - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown precision '%s'.", component) - ) + else -> throw IllegalArgumentException("Unknown precision '$component'.") } libraryBuilder.resolveUnaryCall("System", operatorName, result) return result } - override fun visitDurationExpressionTerm(ctx: DurationExpressionTermContext): Any? { + override fun visitDurationExpressionTerm(ctx: DurationExpressionTermContext): DurationBetween { // duration in days of X <=> days between start of X and end of X val operand = parseExpression(ctx.expressionTerm()) val start = of.createStart().withOperand(operand) @@ -1445,7 +1322,9 @@ class Cql2ElmVisitor( return result } - override fun visitDifferenceExpressionTerm(ctx: DifferenceExpressionTermContext): Any? { + override fun visitDifferenceExpressionTerm( + ctx: DifferenceExpressionTermContext + ): DifferenceBetween { // difference in days of X <=> difference in days between start of X and end of // X val operand = parseExpression(ctx.expressionTerm()) @@ -1461,7 +1340,7 @@ class Cql2ElmVisitor( return result } - override fun visitBetweenExpression(ctx: BetweenExpressionContext): Any? { + override fun visitBetweenExpression(ctx: BetweenExpressionContext): Expression { // X properly? between Y and Z val first = parseExpression(ctx.expression())!! val second = parseExpression(ctx.expressionTerm(0))!! @@ -1615,10 +1494,10 @@ class Cql2ElmVisitor( return contains } } - throw IllegalArgumentException(String.format(Locale.US, "Unknown operator: %s", operator)) + throw IllegalArgumentException("Unknown operator: $operator") } - override fun visitAndExpression(ctx: AndExpressionContext): And? { + override fun visitAndExpression(ctx: AndExpressionContext): And { val and = of.createAnd() .withOperand( @@ -1629,7 +1508,7 @@ class Cql2ElmVisitor( return and } - override fun visitOrExpression(ctx: OrExpressionContext): Expression? { + override fun visitOrExpression(ctx: OrExpressionContext): Expression { return if (ctx.getChild(1)!!.text == "xor") { val xor = of.createXor() @@ -1651,7 +1530,7 @@ class Cql2ElmVisitor( } } - override fun visitImpliesExpression(ctx: ImpliesExpressionContext): Expression? { + override fun visitImpliesExpression(ctx: ImpliesExpressionContext): Implies { val implies = of.createImplies() .withOperand( @@ -1662,7 +1541,7 @@ class Cql2ElmVisitor( return implies } - override fun visitInFixSetExpression(ctx: InFixSetExpressionContext): Any? { + override fun visitInFixSetExpression(ctx: InFixSetExpressionContext): Expression { val operator = ctx.getChild(1)!!.text val left = parseExpression(ctx.expression(0)) val right = parseExpression(ctx.expression(1)) @@ -1675,10 +1554,10 @@ class Cql2ElmVisitor( return of.createNull() } - override fun visitEqualityExpression(ctx: EqualityExpressionContext): Expression? { + override fun visitEqualityExpression(ctx: EqualityExpressionContext): Expression { val operator = parseString(ctx.getChild(1)) return if (operator == "~" || operator == "!~") { - val equivalent: BinaryExpression = + val equivalent = of.createEquivalent() .withOperand( parseExpression(ctx.expression(0))!!, @@ -1693,7 +1572,7 @@ class Cql2ElmVisitor( } equivalent } else { - val equal: BinaryExpression = + val equal = of.createEqual() .withOperand( parseExpression(ctx.expression(0))!!, @@ -1730,10 +1609,7 @@ class Cql2ElmVisitor( operatorName = "GreaterOrEqual" exp = of.createGreaterOrEqual() } - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown operator: %s", ctx.getChild(1)!!.text) - ) + else -> throw IllegalArgumentException("Unknown operator: ${ctx.getChild(1)!!.text}") } exp.withOperand(parseExpression(ctx.expression(0))!!, parseExpression(ctx.expression(1))!!) libraryBuilder.resolveBinaryCall("System", operatorName, exp) @@ -1786,15 +1662,8 @@ class Cql2ElmVisitor( override fun visitTermExpression(ctx: TermExpressionContext): Any? { val result = super.visitTermExpression(ctx) - if (result is LibraryRef) { - // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Identifier %s is a library and cannot be used as an expression.", - result.libraryName - ) - ) + require(result !is LibraryRef) { + "Identifier ${(result as LibraryRef).libraryName} is a library and cannot be used as an expression." } return result } @@ -1835,17 +1704,12 @@ class Cql2ElmVisitor( libraryBuilder.findConversion( operand.resultType!!, targetType.resultType!!, - false, - true + implicit = false, + allowPromotionAndDemotion = true ) ?: // ERROR: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve conversion from type %s to type %s.", - operand.resultType, - targetType.resultType - ) + "Could not resolve conversion from type ${operand.resultType} to type ${targetType.resultType}." ) return libraryBuilder.convertExpression((operand), conversion) } @@ -1863,7 +1727,7 @@ class Cql2ElmVisitor( } } - override fun visitTypeExpression(ctx: TypeExpressionContext): Any? { + override fun visitTypeExpression(ctx: TypeExpressionContext): Expression { // NOTE: These don't use the buildIs or buildAs because those start with a // DataType, rather than a TypeSpecifier if (ctx.getChild(1)!!.text == "is") { @@ -1885,7 +1749,7 @@ class Cql2ElmVisitor( return asExpression } - override fun visitCastExpression(ctx: CastExpressionContext): Any? { + override fun visitCastExpression(ctx: CastExpressionContext): As { // NOTE: This doesn't use buildAs because it starts with a DataType, rather than // a TypeSpecifier val asExpression = @@ -1899,7 +1763,7 @@ class Cql2ElmVisitor( return asExpression } - override fun visitBooleanExpression(ctx: BooleanExpressionContext): Expression? { + override fun visitBooleanExpression(ctx: BooleanExpressionContext): Expression { var exp: UnaryExpression? val left = visit(ctx.expression()) as Expression? val lastChild = ctx.getChild(ctx.childCount - 1)!!.text @@ -1917,16 +1781,14 @@ class Cql2ElmVisitor( exp = of.createIsFalse().withOperand(left) libraryBuilder.resolveUnaryCall("System", "IsFalse", exp) } - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown boolean test predicate %s.", lastChild) - ) + else -> throw IllegalArgumentException("Unknown boolean test predicate $lastChild.") } if ("not" == nextToLast) { track(exp, ctx) exp = of.createNot().withOperand(exp) libraryBuilder.resolveUnaryCall("System", "Not", exp) } + return exp } @@ -1946,7 +1808,7 @@ class Cql2ElmVisitor( override fun visitConcurrentWithIntervalOperatorPhrase( ctx: ConcurrentWithIntervalOperatorPhraseContext - ): Any? { + ): BinaryExpression { // ('starts' | 'ends' | 'occurs')? 'same' dateTimePrecision? (relativeQualifier // | 'as') ('start' | 'end')? val timingOperator: TimingOperatorContext = timingOperators.peek() @@ -2020,11 +1882,7 @@ class Cql2ElmVisitor( } else -> throw IllegalArgumentException( - String.format( - Locale.US, - "Unknown relative qualifier: '%s'.", - ctx.relativeQualifier()!!.text - ) + "Unknown relative qualifier: '${ctx.relativeQualifier()!!.text}'." ) } } @@ -2178,7 +2036,7 @@ class Cql2ElmVisitor( override fun visitBeforeOrAfterIntervalOperatorPhrase( ctx: BeforeOrAfterIntervalOperatorPhraseContext - ): Any? { + ): Expression { // ('starts' | 'ends' | 'occurs')? quantityOffset? ('before' | 'after') // dateTimePrecisionSpecifier? ('start' | // 'end')? @@ -2268,8 +2126,8 @@ class Cql2ElmVisitor( "System", "SameOrBefore", sameOrBefore, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) sameOrBefore } else { @@ -2283,8 +2141,8 @@ class Cql2ElmVisitor( "System", "SameOrAfter", sameOrAfter, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) sameOrAfter } @@ -2295,7 +2153,13 @@ class Cql2ElmVisitor( if (dateTimePrecision != null) { before.precision = parseComparableDateTimePrecision(dateTimePrecision) } - libraryBuilder.resolveBinaryCall("System", "Before", before, true, true) + libraryBuilder.resolveBinaryCall( + "System", + "Before", + before, + mustResolve = true, + allowPromotionAndDemotion = true + ) before } else { val after = @@ -2303,7 +2167,13 @@ class Cql2ElmVisitor( if (dateTimePrecision != null) { after.precision = parseComparableDateTimePrecision(dateTimePrecision) } - libraryBuilder.resolveBinaryCall("System", "After", after, true, true) + libraryBuilder.resolveBinaryCall( + "System", + "After", + after, + mustResolve = true, + allowPromotionAndDemotion = true + ) after } } @@ -2390,8 +2260,8 @@ class Cql2ElmVisitor( "System", "Before", before, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) before } else { @@ -2406,8 +2276,8 @@ class Cql2ElmVisitor( "System", "SameOrBefore", sameOrBefore, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) sameOrBefore } @@ -2428,8 +2298,8 @@ class Cql2ElmVisitor( "System", "After", after, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) after } else { @@ -2444,8 +2314,8 @@ class Cql2ElmVisitor( "System", "SameOrAfter", sameOrAfter, - true, - true + mustResolve = true, + allowPromotionAndDemotion = true ) sameOrAfter } @@ -2532,24 +2402,9 @@ class Cql2ElmVisitor( throw IllegalArgumentException("Unable to resolve interval operator phrase.") } - @Suppress("UnusedPrivateMember") - private fun resolveBetweenOperator( - unit: String?, - left: Expression, - right: Expression - ): BinaryExpression? { - if (unit != null) { - val between = - of.createDurationBetween() - .withPrecision(parseDateTimePrecision(unit)) - .withOperand(left, right) - libraryBuilder.resolveBinaryCall("System", "DurationBetween", between) - return between - } - return null - } - - override fun visitWithinIntervalOperatorPhrase(ctx: WithinIntervalOperatorPhraseContext): Any? { + override fun visitWithinIntervalOperatorPhrase( + ctx: WithinIntervalOperatorPhraseContext + ): Expression { // ('starts' | 'ends' | 'occurs')? 'properly'? 'within' quantityLiteral 'of' // ('start' | 'end')? // A starts within 3 days of start B @@ -2714,7 +2569,9 @@ class Cql2ElmVisitor( return operator } - override fun visitStartsIntervalOperatorPhrase(ctx: StartsIntervalOperatorPhraseContext): Any? { + override fun visitStartsIntervalOperatorPhrase( + ctx: StartsIntervalOperatorPhraseContext + ): Starts { val dateTimePrecision = if (ctx.dateTimePrecisionSpecifier() != null) ctx.dateTimePrecisionSpecifier()!!.dateTimePrecision().text @@ -2729,7 +2586,7 @@ class Cql2ElmVisitor( return starts } - override fun visitEndsIntervalOperatorPhrase(ctx: EndsIntervalOperatorPhraseContext): Any? { + override fun visitEndsIntervalOperatorPhrase(ctx: EndsIntervalOperatorPhraseContext): Ends { val dateTimePrecision = if (ctx.dateTimePrecisionSpecifier() != null) ctx.dateTimePrecisionSpecifier()!!.dateTimePrecision().text @@ -2831,13 +2688,13 @@ class Cql2ElmVisitor( return result } - override fun visitCaseExpressionItem(ctx: CaseExpressionItemContext): Any? { + override fun visitCaseExpressionItem(ctx: CaseExpressionItemContext): CaseItem { return of.createCaseItem() .withWhen(parseExpression(ctx.expression(0))) .withThen(parseExpression(ctx.expression(1))) } - override fun visitAggregateExpressionTerm(ctx: AggregateExpressionTermContext): Any? { + override fun visitAggregateExpressionTerm(ctx: AggregateExpressionTermContext): Expression { when (ctx.getChild(0)!!.text) { "distinct" -> { val distinct = of.createDistinct().withOperand(parseExpression(ctx.expression())) @@ -2850,9 +2707,7 @@ class Cql2ElmVisitor( return flatten } } - throw IllegalArgumentException( - String.format(Locale.US, "Unknown aggregate operator %s.", ctx.getChild(0)!!.text) - ) + throw IllegalArgumentException("Unknown aggregate operator ${ctx.getChild(0)!!.text}.") } override fun visitSetAggregateExpressionTerm(ctx: SetAggregateExpressionTermContext): Any { @@ -2906,9 +2761,7 @@ class Cql2ElmVisitor( return collapse } } - throw IllegalArgumentException( - String.format(Locale.US, "Unknown aggregate set operator %s.", ctx.getChild(0)!!.text) - ) + throw IllegalArgumentException("Unknown aggregate set operator ${ctx.getChild(0)!!.text}.") } override fun visitRetrieve(ctx: RetrieveContext): Expression? { @@ -2920,22 +2773,13 @@ class Cql2ElmVisitor( qualifiers, (parseString(ctx.namedTypeSpecifier().referentialOrTypeNameIdentifier()))!! ) - val dataType: DataType = - libraryBuilder.resolveTypeName(model, label) - ?: // ERROR: - throw IllegalArgumentException( - String.format(Locale.US, "Could not resolve type name %s.", label) - ) - if (dataType !is ClassType || !dataType.isRetrievable) { - // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Specified data type %s does not support retrieval.", - label - ) - ) + val dataType = libraryBuilder.resolveTypeName(model, label) + + requireNotNull(dataType) { "Could not resolve type name $label." } + require(dataType is ClassType && dataType.isRetrievable) { + "Specified data type $label does not support retrieval." } + val classType: ClassType = dataType // BTR -> The original intent of this code was to have the retrieve return the // base type, and use the @@ -2992,12 +2836,7 @@ class Cql2ElmVisitor( // WARNING: propertyException = CqlSemanticException( - String.format( - Locale.US, - "Could not resolve code path %s for the type of the retrieve %s.", - codePath, - namedType.name - ), + "Could not resolve code path $codePath for the type of the retrieve ${namedType.name}.", if (useStrictRetrieveTyping) CqlCompilerException.ErrorSeverity.Error else CqlCompilerException.ErrorSeverity.Warning, getTrackBack(ctx), @@ -3007,7 +2846,7 @@ class Cql2ElmVisitor( } } if (ctx.terminology()!!.qualifiedIdentifierExpression() != null) { - val identifiers = visit(ctx.terminology()!!) as List + val identifiers: List = visit(ctx.terminology()!!).cast() terminology = resolveQualifiedIdentifier(identifiers) track(terminology, ctx.terminology()!!.qualifiedIdentifierExpression()!!) } else { @@ -3027,10 +2866,10 @@ class Cql2ElmVisitor( (hasFHIRHelpers && propertyType is NamedType && ((propertyType as NamedType).simpleName == "Reference") && - ((namedType.simpleName == "MedicationRequest" || + (namedType.simpleName == "MedicationRequest" || namedType.simpleName == "MedicationAdministration" || namedType.simpleName == "MedicationDispense" || - namedType.simpleName == "MedicationStatement"))) + namedType.simpleName == "MedicationStatement")) ) { // TODO: This is a model-specific special case to support QICore // This functionality needs to be generalized to a retrieve mapping in the model @@ -3105,14 +2944,10 @@ class Cql2ElmVisitor( libraryBuilder.resolveBinaryCall("System", "Equal", e) // Apply target mapping if this is a profile-informed model info - if ( - DataTypes.equal(idType, libraryBuilder.resolveTypeName("System", "String")) - ) { + if (equal(idType, libraryBuilder.resolveTypeName("System", "String"))) { idProperty.path = "id.value" } - if ( - DataTypes.equal(refType, libraryBuilder.resolveTypeName("System", "String")) - ) { + if (equal(refType, libraryBuilder.resolveTypeName("System", "String"))) { refProperty.path = "medication.reference.value" } val mCodeType: DataType? = @@ -3237,7 +3072,7 @@ class Cql2ElmVisitor( .withTemplateId(classType.identifier) .withCodeProperty(codePath) if (ctx.contextIdentifier() != null) { - val identifiers = visit(ctx.contextIdentifier()!!) as List + val identifiers: List = visit(ctx.contextIdentifier()!!).cast() val contextExpression: Expression? = resolveQualifiedIdentifier(identifiers) retrieve.context = contextExpression } @@ -3303,11 +3138,7 @@ class Cql2ElmVisitor( // WARNING: libraryBuilder.recordParsingException( CqlSemanticException( - String.format( - Locale.US, - "Unexpected membership operator %s in retrieve", - inExpression.javaClass.simpleName - ), + "Unexpected membership operator ${inExpression.javaClass.simpleName} in retrieve", if (useStrictRetrieveTyping) CqlCompilerException.ErrorSeverity.Error else CqlCompilerException.ErrorSeverity.Warning, @@ -3347,13 +3178,13 @@ class Cql2ElmVisitor( // Automatically promote to a list for use in the retrieve target if ( - !((equivalent.operand[1].resultType is ListType || + !(equivalent.operand[1].resultType is ListType || (libraryBuilder.isCompatibleWith("1.5") && equivalent.operand[1] .resultType!! .isSubTypeOf( libraryBuilder.resolveTypeName("System", "Vocabulary")!! - )))) + ))) ) { retrieve.codes = libraryBuilder.resolveToList(equivalent.operand[1]) } else { @@ -3369,13 +3200,13 @@ class Cql2ElmVisitor( // Automatically promote to a list for use in the retrieve target if ( - !((equal.operand[1].resultType is ListType || + !(equal.operand[1].resultType is ListType || (libraryBuilder.isCompatibleWith("1.5") && equal.operand[1] .resultType!! .isSubTypeOf( libraryBuilder.resolveTypeName("System", "Vocabulary")!! - )))) + ))) ) { retrieve.codes = libraryBuilder.resolveToList(equal.operand[1]) } else { @@ -3386,11 +3217,7 @@ class Cql2ElmVisitor( // WARNING: libraryBuilder.recordParsingException( CqlSemanticException( - String.format( - Locale.US, - "Unknown code comparator %s in retrieve", - codeComparator - ), + "Unknown code comparator $codeComparator in retrieve", if (useStrictRetrieveTyping) CqlCompilerException.ErrorSeverity.Error else CqlCompilerException.ErrorSeverity.Warning, @@ -3485,7 +3312,7 @@ class Cql2ElmVisitor( } val sources: MutableList = ArrayList() for (source in ctx.aliasedQuerySource()) { - require(!(sources.size > 0 && !hasFrom)) { + require(!(sources.isNotEmpty() && !hasFrom)) { "The from keyword is required for multi-source queries." } sources.add(visit(source) as AliasedQuerySource?) @@ -3493,14 +3320,14 @@ class Cql2ElmVisitor( return sources } - override fun visitQuery(ctx: cqlParser.QueryContext): Any? { + override fun visitQuery(ctx: cqlParser.QueryContext): Query { val queryContext = QueryContext() libraryBuilder.pushQueryContext(queryContext) var sources: List? = null return try { queryContext.enterSourceClause() try { - sources = visit(ctx.sourceClause()) as List? + sources = visit(ctx.sourceClause()).cast() } finally { queryContext.exitSourceClause() } @@ -3526,9 +3353,7 @@ class Cql2ElmVisitor( */ var dfcx: List = emptyList() try { - dfcx = - if (ctx.letClause() != null) visit(ctx.letClause()!!) as List - else dfcx + dfcx = if (ctx.letClause() != null) visit(ctx.letClause()!!).cast() else dfcx for (letClause: LetClause in dfcx) { libraryBuilder.pushIdentifier(letClause.identifier!!, letClause) } @@ -3637,16 +3462,14 @@ class Cql2ElmVisitor( if (expressionContextPushed) { libraryBuilder.popExpressionContext() } - if (dfcx != null) { - for (letClause: LetClause? in dfcx) { - libraryBuilder.popIdentifier() - } + for (letClause in dfcx) { + libraryBuilder.popIdentifier() } } } finally { libraryBuilder.popQueryContext() if (sources != null) { - for (source: AliasedQuerySource? in sources) { + for (source in sources) { libraryBuilder.popIdentifier() } } @@ -3724,17 +3547,17 @@ class Cql2ElmVisitor( * @return The collapsed path operands (or sub-operands) were modified; `false` otherwise. */ private fun getPropertyPath(reference: Expression, alias: String): String? { - var reference = reference - reference = getConversionReference(reference) - reference = getChoiceSelection(reference) - if (reference is Property) { - val property = reference + var ref = reference + ref = getConversionReference(ref) + ref = getChoiceSelection(ref) + if (ref is Property) { + val property = ref if (alias == property.scope) { return property.path } else if (property.source != null) { val subPath = getPropertyPath(property.source!!, alias) if (subPath != null) { - return String.format(Locale.US, "%s.%s", subPath, property.path) + return "$subPath.${property.path}" } } } @@ -3837,14 +3660,11 @@ class Cql2ElmVisitor( var result: Expression = and val lhs = and.operand[0] val rhs = and.operand[1] - if (isBooleanLiteral(lhs, true)) { - result = rhs - } else if (isBooleanLiteral(rhs, true)) { - result = lhs - } else if (lhs is And) { - and.operand[0] = consolidateAnd(lhs) - } else if (rhs is And) { - and.operand[1] = consolidateAnd(rhs) + when { + isBooleanLiteral(lhs, true) -> result = rhs + isBooleanLiteral(rhs, true) -> result = lhs + lhs is And -> and.operand[0] = consolidateAnd(lhs) + rhs is And -> and.operand[1] = consolidateAnd(rhs) } return result } @@ -3912,11 +3732,6 @@ class Cql2ElmVisitor( // return isEligible; } - @Suppress("UnusedPrivateMember") - private fun isDateTimeTypeSpecifier(e: Element): Boolean { - return e.resultType == libraryBuilder.resolveTypeName("System", "DateTime") - } - override fun visitLetClause(ctx: LetClauseContext): Any { val letClauseItems: MutableList = ArrayList() for (letClauseItem in ctx.letClauseItem()) { @@ -3925,7 +3740,7 @@ class Cql2ElmVisitor( return letClauseItems } - override fun visitLetClauseItem(ctx: LetClauseItemContext): Any? { + override fun visitLetClauseItem(ctx: LetClauseItemContext): LetClause { val letClause = of.createLetClause() .withExpression(parseExpression(ctx.expression())) @@ -3935,7 +3750,7 @@ class Cql2ElmVisitor( return letClause } - override fun visitAliasedQuerySource(ctx: AliasedQuerySourceContext): Any? { + override fun visitAliasedQuerySource(ctx: AliasedQuerySourceContext): AliasedQuerySource { val source = of.createAliasedQuerySource() .withExpression(parseExpression(ctx.querySource())) @@ -3980,13 +3795,12 @@ class Cql2ElmVisitor( return result } - override fun visitReturnClause(ctx: ReturnClauseContext): Any? { + override fun visitReturnClause(ctx: ReturnClauseContext): ReturnClause { val returnClause = of.createReturnClause() if (ctx.getChild(1) is TerminalNode) { when (ctx.getChild(1)!!.text) { "all" -> returnClause.distinct = false "distinct" -> returnClause.distinct = true - else -> {} } } returnClause.expression = parseExpression(ctx.expression()) @@ -4008,14 +3822,13 @@ class Cql2ElmVisitor( } else null } - override fun visitAggregateClause(ctx: AggregateClauseContext): Any? { + override fun visitAggregateClause(ctx: AggregateClauseContext): AggregateClause { libraryBuilder.checkCompatibilityLevel("Aggregate query clause", "1.5") val aggregateClause = of.createAggregateClause() if (ctx.getChild(1) is TerminalNode) { when (ctx.getChild(1)!!.text) { "all" -> aggregateClause.distinct = false "distinct" -> aggregateClause.distinct = true - else -> {} } } if (ctx.startingClause() != null) { @@ -4047,11 +3860,11 @@ class Cql2ElmVisitor( return aggregateClause } - override fun visitSortDirection(ctx: SortDirectionContext): SortDirection? { + override fun visitSortDirection(ctx: SortDirectionContext): SortDirection { return SortDirection.fromValue(ctx.text) } - private fun parseSortDirection(ctx: SortDirectionContext?): SortDirection? { + private fun parseSortDirection(ctx: SortDirectionContext?): SortDirection { return if (ctx != null) { visitSortDirection(ctx) } else SortDirection.ASC @@ -4063,15 +3876,15 @@ class Cql2ElmVisitor( of.createByColumn() .withPath(sortExpression.name) .withDirection(parseSortDirection(ctx.sortDirection())) - .withResultType(sortExpression.resultType) as SortByItem + .withResultType(sortExpression.resultType) } else of.createByExpression() .withExpression(sortExpression) .withDirection(parseSortDirection(ctx.sortDirection())) - .withResultType(sortExpression.resultType) as SortByItem + .withResultType(sortExpression.resultType) } - override fun visitSortClause(ctx: SortClauseContext): Any? { + override fun visitSortClause(ctx: SortClauseContext): SortClause { if (ctx.sortDirection() != null) { return of.createSortClause() .withBy( @@ -4091,12 +3904,12 @@ class Cql2ElmVisitor( } else if (ctx.retrieve() != null) { visit(ctx.retrieve()!!) } else { - val identifiers = visit(ctx.qualifiedIdentifierExpression()!!) as List + val identifiers: List = visit(ctx.qualifiedIdentifierExpression()!!).cast() resolveQualifiedIdentifier(identifiers) } } - override fun visitIndexedExpressionTerm(ctx: IndexedExpressionTermContext): Any? { + override fun visitIndexedExpressionTerm(ctx: IndexedExpressionTermContext): Indexer { val indexer = of.createIndexer() .withOperand( @@ -4139,7 +3952,7 @@ class Cql2ElmVisitor( return resolveMemberIdentifier(identifier) } - fun resolveQualifiedIdentifier(identifiers: List): Expression? { + private fun resolveQualifiedIdentifier(identifiers: List): Expression? { var current: Expression? = null for (identifier in identifiers) { current = @@ -4152,7 +3965,7 @@ class Cql2ElmVisitor( return current } - fun resolveMemberIdentifier(identifier: String): Expression? { + private fun resolveMemberIdentifier(identifier: String): Expression? { if (libraryBuilder.hasExpressionTarget()) { val target = libraryBuilder.popExpressionTarget() return try { @@ -4178,15 +3991,9 @@ class Cql2ElmVisitor( chunks = Stack() forwards.push(expressionInfo) try { - if (expressionInfo.definition == null) { + requireNotNull(expressionInfo.definition) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to expression %s because its definition contains errors.", - expressionInfo.name - ) - ) + "Could not validate reference to expression ${expressionInfo.name} because its definition contains errors." } // Have to call the visit to get the outer processing to occur @@ -4209,19 +4016,19 @@ class Cql2ElmVisitor( } private fun ensureSystemFunctionName(libraryName: String?, functionName: String): String { - var functionName = functionName if (libraryName == null || libraryName == "System") { // Because these functions can be both a keyword and the name of a method, they // can be resolved by the // parser as a function, instead of as the keyword-based parser rule. In this // case, the function // name needs to be translated to the System function name in order to resolve. - when (functionName) { - "contains" -> functionName = "Contains" - "distinct" -> functionName = "Distinct" - "exists" -> functionName = "Exists" - "in" -> functionName = "In" - "not" -> functionName = "Not" + return when (functionName) { + "contains" -> "Contains" + "distinct" -> "Distinct" + "exists" -> "Exists" + "in" -> "In" + "not" -> "Not" + else -> functionName } } return functionName @@ -4238,7 +4045,14 @@ class Cql2ElmVisitor( expressions.add(visit(expressionContext) as Expression) } } - return resolveFunction(libraryName, functionName, expressions, true, false, false) + return resolveFunction( + libraryName, + functionName, + expressions, + mustResolve = true, + allowPromotionAndDemotion = false, + allowFluent = false + ) } @Suppress("LongParameterList") @@ -4250,11 +4064,11 @@ class Cql2ElmVisitor( allowPromotionAndDemotion: Boolean, allowFluent: Boolean ): Expression? { - var functionName = functionName + var name = functionName if (allowFluent) { libraryBuilder.checkCompatibilityLevel("Fluent functions", "1.5") } - functionName = ensureSystemFunctionName(libraryName, functionName) + name = ensureSystemFunctionName(libraryName, name) // 1. Ensure all overloads of the function are registered with the operator map // 2. Resolve the function, allowing for the case that operator map is a @@ -4266,7 +4080,7 @@ class Cql2ElmVisitor( // Find all functionDefinitionInfo instances with the given name // register each functionDefinitionInfo if (libraryName == null || libraryName == "" || libraryName == libraryInfo.libraryName) { - val fdis = libraryInfo.resolveFunctionReference(functionName) + val fdis = libraryInfo.resolveFunctionReference(name) if (fdis != null) { for ((_, context, definition) in fdis) { val saveContext = saveCurrentContext(context) @@ -4281,34 +4095,33 @@ class Cql2ElmVisitor( val result = libraryBuilder.resolveFunction( libraryName, - functionName, + name, expressions, mustResolve, allowPromotionAndDemotion, allowFluent ) - if (result is FunctionRefInvocation) { - if ( + if ( + result is FunctionRefInvocation && result.resolution != null && - (result.resolution!!.operator.libraryName == null || - (result.resolution!!.operator.libraryName == - libraryBuilder.compiledLibrary.identifier!!.id)) - ) { - val op = result.resolution!!.operator - val fh = getFunctionHeader(op) - if (!fh.isCompiled) { - val ctx = getFunctionDefinitionContext(fh) - val saveContext = saveCurrentContext(fh.functionDef.context!!) - val saveChunks = chunks - chunks = Stack() - try { - val fd = compileFunctionDefinition(ctx) - op.resultType = fd.resultType - result.resultType = op.resultType - } finally { - currentContext = saveContext - chunks = saveChunks - } + (result.resolution!!.operator.libraryName == null || + (result.resolution!!.operator.libraryName == + libraryBuilder.compiledLibrary.identifier!!.id)) + ) { + val op = result.resolution!!.operator + val fh = getFunctionHeader(op) + if (!fh.isCompiled) { + val ctx = getFunctionDefinitionContext(fh) + val saveContext = saveCurrentContext(fh.functionDef.context!!) + val saveChunks = chunks + chunks = Stack() + try { + val fd = compileFunctionDefinition(ctx) + op.resultType = fd.resultType + result.resultType = op.resultType + } finally { + currentContext = saveContext + chunks = saveChunks } } } @@ -4324,7 +4137,7 @@ class Cql2ElmVisitor( return result?.expression } - fun resolveFunctionOrQualifiedFunction( + private fun resolveFunctionOrQualifiedFunction( identifier: String, paramListCtx: ParamListContext? ): Expression? { @@ -4341,23 +4154,19 @@ class Cql2ElmVisitor( if (isMethodInvocationEnabled) { return systemMethodResolver.resolveMethod( target, - (identifier), + identifier, paramListCtx, true ) } if (!isMethodInvocationEnabled) { throw CqlCompilerException( - String.format( - Locale.US, - "The identifier %s could not be resolved as an invocation because method-style invocation is disabled.", - identifier - ), + "The identifier $identifier could not be resolved as an invocation because method-style invocation is disabled.", CqlCompilerException.ErrorSeverity.Error ) } throw IllegalArgumentException( - String.format(Locale.US, "Invalid invocation target: %s", target.javaClass.name) + "Invalid invocation target: ${target.javaClass.name}" ) } finally { libraryBuilder.pushExpressionTarget(target) @@ -4369,7 +4178,7 @@ class Cql2ElmVisitor( val thisRef: Expression? = libraryBuilder.resolveIdentifier("\$this", false) if (thisRef != null) { val result: Expression? = - systemMethodResolver.resolveMethod(thisRef, (identifier), paramListCtx, false) + systemMethodResolver.resolveMethod(thisRef, identifier, paramListCtx, false) if (result != null) { return result } @@ -4381,7 +4190,7 @@ class Cql2ElmVisitor( val parameterRef: ParameterRef? = libraryBuilder.resolveImplicitContext() if (parameterRef != null) { val result: Expression? = - systemMethodResolver.resolveMethod(parameterRef, (identifier), paramListCtx, false) + systemMethodResolver.resolveMethod(parameterRef, identifier, paramListCtx, false) if (result != null) { return result } @@ -4445,18 +4254,10 @@ class Cql2ElmVisitor( } } if (signaturesMatch) { - target = - if (target == null) { - fd - } else { - throw IllegalArgumentException( - String.format( - Locale.US, - "Internal error attempting to resolve function header for %s", - op.name - ) - ) - } + check(target == null) { + "Internal error attempting to resolve function header for ${op.name}" + } + target = fd } } } @@ -4480,52 +4281,36 @@ class Cql2ElmVisitor( val fd = getFunctionDef(op) ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve function header for operator %s", - op.name - ) + "Could not resolve function header for operator ${op.name}" ) return getFunctionHeaderByDef(fd) ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve function header for operator %s", - op.name - ) + "Could not resolve function header for operator ${op.name}" ) } private fun getFunctionDefinitionContext(fh: FunctionHeader): FunctionDefinitionContext { return functionDefinitions[fh] ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve function definition context for function header %s", - fh.functionDef.name - ) + "Could not resolve function definition context for function header ${fh.functionDef.name}" ) } - fun registerFunctionDefinition(ctx: FunctionDefinitionContext) { + private fun registerFunctionDefinition(ctx: FunctionDefinitionContext) { val fh = getFunctionHeader(ctx) if (!libraryBuilder.compiledLibrary.contains(fh.functionDef)) { libraryBuilder.addExpression(fh.functionDef) } } - fun compileFunctionDefinition(ctx: FunctionDefinitionContext): FunctionDef { + private fun compileFunctionDefinition(ctx: FunctionDefinitionContext): FunctionDef { val fh: FunctionHeader = getFunctionHeader(ctx) val functionDef: FunctionDef = fh.functionDef val resultType: TypeSpecifier? = fh.resultType val op: Operator = libraryBuilder.resolveFunctionDefinition(fh.functionDef) ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Internal error: Could not resolve operator map entry for function header %s", - fh.mangledName - ) + "Internal error: Could not resolve operator map entry for function header ${fh.mangledName}" ) libraryBuilder.pushIdentifier(functionDef.name!!, functionDef, IdentifierScope.GLOBAL) val operand = op.functionDef!!.operand as List @@ -4555,17 +4340,9 @@ class Cql2ElmVisitor( (functionDef.expression != null) && (functionDef.expression!!.resultType != null) ) { - if (!subTypeOf(functionDef.expression!!.resultType, resultType.resultType)) { + require(subTypeOf(functionDef.expression!!.resultType, resultType.resultType)) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Function %s has declared return type %s but the function body returns incompatible type %s.", - functionDef.name, - resultType.resultType, - functionDef.expression!!.resultType - ) - ) + "Function ${functionDef.name} has declared return type ${resultType.resultType} but the function body returns incompatible type ${functionDef.expression!!.resultType}." } } functionDef.resultType = functionDef.expression!!.resultType @@ -4574,11 +4351,7 @@ class Cql2ElmVisitor( functionDef.external = true requireNotNull(resultType) { // ERROR: - String.format( - Locale.US, - "Function %s is marked external but does not declare a return type.", - functionDef.name - ) + "Function ${functionDef.name} is marked external but does not declare a return type." } functionDef.resultType = resultType.resultType op.resultType = functionDef.resultType diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlCompiler.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlCompiler.kt index 8070a5597..f9d51fcdf 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlCompiler.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlCompiler.kt @@ -68,9 +68,6 @@ class CqlCompiler( return retrieves } - val compiledLibraries: Map - get() = libraryManager.compiledLibraries - val libraries: Map get() { val result = HashMap() @@ -129,11 +126,7 @@ class CqlCompiler( } else { if (offendingSymbol is CommonToken) { builder.recordParsingException( - CqlSyntaxException( - String.format(Locale.US, "Syntax error at %s", offendingSymbol.text), - trackback, - e - ) + CqlSyntaxException("Syntax error at ${offendingSymbol.text}", trackback, e) ) } else { builder.recordParsingException(CqlSyntaxException("Syntax error", trackback, e)) diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlInternalException.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlInternalException.kt index 8369a8bb0..4458fc36c 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlInternalException.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlInternalException.kt @@ -3,19 +3,5 @@ package org.cqframework.cql.cql2elm import org.cqframework.cql.cql2elm.tracking.TrackBack /** Created by Bryn on 5/20/2017. */ -class CqlInternalException : CqlCompilerException { - constructor(message: String?) : super(message, ErrorSeverity.Error) - - constructor(message: String?, cause: Throwable?) : super(message, ErrorSeverity.Error, cause) - - constructor( - message: String?, - locator: TrackBack? - ) : super(message, ErrorSeverity.Error, locator) - - constructor( - message: String?, - locator: TrackBack?, - cause: Throwable? - ) : super(message, ErrorSeverity.Error, locator, cause) -} +class CqlInternalException(message: String?, locator: TrackBack? = null, cause: Throwable? = null) : + CqlCompilerException(message, ErrorSeverity.Error, locator, cause) diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSemanticException.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSemanticException.kt index f48aa6ac9..5e8406c61 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSemanticException.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSemanticException.kt @@ -6,18 +6,6 @@ import org.cqframework.cql.cql2elm.tracking.TrackBack class CqlSemanticException : CqlCompilerException { constructor(message: String?) : super(message) - constructor(message: String?, severity: ErrorSeverity) : super(message, severity) - - constructor(message: String?, cause: Throwable?) : super(message, cause) - - constructor( - message: String?, - severity: ErrorSeverity, - cause: Throwable? - ) : super(message, severity, cause) - - constructor(message: String?, locator: TrackBack?) : super(message, locator) - constructor( message: String?, severity: ErrorSeverity, diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSyntaxException.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSyntaxException.kt index f0cfca952..0f23747db 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSyntaxException.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlSyntaxException.kt @@ -3,37 +3,5 @@ package org.cqframework.cql.cql2elm import org.cqframework.cql.cql2elm.tracking.TrackBack /** Created by Bryn on 3/27/2017. */ -class CqlSyntaxException : CqlCompilerException { - constructor(message: String?) : super(message) - - constructor(message: String?, severity: ErrorSeverity) : super(message, severity) - - constructor(message: String?, cause: Throwable?) : super(message, cause) - - constructor( - message: String?, - severity: ErrorSeverity, - cause: Throwable? - ) : super(message, severity, cause) - - constructor(message: String?, locator: TrackBack?) : super(message, locator) - - constructor( - message: String?, - severity: ErrorSeverity, - locator: TrackBack? - ) : super(message, severity, locator) - - constructor( - message: String?, - locator: TrackBack?, - cause: Throwable? - ) : super(message, locator, cause) - - constructor( - message: String?, - severity: ErrorSeverity, - locator: TrackBack?, - cause: Throwable? - ) : super(message, severity, locator, cause) -} +class CqlSyntaxException(message: String?, locator: TrackBack?, cause: Throwable?) : + CqlCompilerException(message, locator, cause) diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlTranslator.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlTranslator.kt index 7476b1cdf..ba91c64dd 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlTranslator.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/CqlTranslator.kt @@ -73,9 +73,6 @@ class CqlTranslator( val libraries: Map get() = compiler.libraries - val translatedLibraries: Map - get() = compiler.compiledLibraries - val exceptions: List? // public Map getLibrariesAsXML() { get() = compiler.exceptions @@ -97,35 +94,6 @@ class CqlTranslator( return CqlTranslator(null, null, CharStreams.fromString(cqlText), libraryManager) } - @JvmStatic - fun fromText( - namespaceInfo: NamespaceInfo?, - cqlText: String, - libraryManager: LibraryManager - ): CqlTranslator { - return CqlTranslator( - namespaceInfo, - null, - CharStreams.fromString(cqlText), - libraryManager - ) - } - - @JvmStatic - fun fromText( - namespaceInfo: NamespaceInfo?, - sourceInfo: VersionedIdentifier?, - cqlText: String, - libraryManager: LibraryManager - ): CqlTranslator { - return CqlTranslator( - namespaceInfo, - sourceInfo, - CharStreams.fromString(cqlText), - libraryManager - ) - } - @JvmStatic @Throws(IOException::class) fun fromStream( @@ -220,7 +188,7 @@ class CqlTranslator( fun fromFile( namespaceInfo: NamespaceInfo?, sourceInfo: VersionedIdentifier?, - cqlFile: File?, + cqlFile: File, libraryManager: LibraryManager ): CqlTranslator { return CqlTranslator( diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DataTypes.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DataTypes.kt index 7d533bd1c..dd0eebe57 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DataTypes.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DataTypes.kt @@ -1,23 +1,18 @@ package org.cqframework.cql.cql2elm -import java.util.* import org.hl7.cql.model.DataType +private const val UNKNOWN = "" + object DataTypes { - @JvmStatic fun verifyType(actualType: DataType?, expectedType: DataType?) { require(subTypeOf(actualType, expectedType)) { // ERROR: - String.format( - Locale.US, - "Expected an expression of type '%s', but found an expression of type '%s'.", - if (expectedType != null) expectedType.toLabel() else "", - if (actualType != null) actualType.toLabel() else "" - ) + "Expected an expression of type '${expectedType?.toLabel() ?: UNKNOWN}'," + + "but found an expression of type '${actualType?.toLabel() ?: UNKNOWN}'." } } - @JvmStatic fun verifyCast(targetType: DataType?, sourceType: DataType?) { // Casting can be used for compatible types as well as subtypes and supertypes require( @@ -26,30 +21,24 @@ object DataTypes { compatibleWith(sourceType, targetType) ) { // ERROR: - String.format( - Locale.US, - "Expression of type '%s' cannot be cast as a value of type '%s'.", - if (sourceType != null) sourceType.toLabel() else "", - if (targetType != null) targetType.toLabel() else "" - ) + "Expression of type '${sourceType?.toLabel() ?: UNKNOWN}'" + + " cannot be cast as a value of type '${targetType?.toLabel() ?: UNKNOWN}'." } } - @JvmStatic fun equal(a: DataType?, b: DataType?): Boolean { return a != null && b != null && a == b } - fun compatibleWith(a: DataType?, b: DataType?): Boolean { + private fun compatibleWith(a: DataType?, b: DataType?): Boolean { return a != null && b != null && a.isCompatibleWith(b) } - @JvmStatic fun subTypeOf(a: DataType?, b: DataType?): Boolean { return a != null && b != null && a.isSubTypeOf(b) } - fun superTypeOf(a: DataType?, b: DataType?): Boolean { + private fun superTypeOf(a: DataType?, b: DataType?): Boolean { return a != null && b != null && a.isSuperTypeOf(b) } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceLoader.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceLoader.kt index 2d50a776a..3353e4f24 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceLoader.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceLoader.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm import java.io.InputStream import java.nio.file.Path -import java.util.* import kotlin.collections.ArrayList import org.hl7.cql.model.NamespaceAware import org.hl7.cql.model.NamespaceManager @@ -10,12 +9,12 @@ import org.hl7.elm.r1.VersionedIdentifier /** * Used by LibraryManager to manage a set of library source providers that resolve library includes - * within CQL. Package private since its not intended to be used outside the context of the + * within CQL. Package private since it's not intended to be used outside the context of the * instantiating LibraryManager instance. */ internal class DefaultLibrarySourceLoader : LibrarySourceLoader, NamespaceAware, PathAware { private val providers: MutableList = ArrayList() - var initialized: Boolean = false + private var initialized: Boolean = false override fun registerProvider(provider: LibrarySourceProvider) { if (namespaceManager != null && provider is NamespaceAware) { @@ -30,9 +29,7 @@ internal class DefaultLibrarySourceLoader : LibrarySourceLoader, NamespaceAware, private var path: Path? = null override fun setPath(path: Path) { - require(path.toFile().isDirectory) { - String.format(Locale.US, "path '%s' is not a valid directory", path) - } + require(path.toFile().isDirectory) { "path '$path' is not a valid directory" } this.path = path for (provider in getProviders()) { @@ -65,25 +62,13 @@ internal class DefaultLibrarySourceLoader : LibrarySourceLoader, NamespaceAware, val localSource: InputStream? = provider.getLibrarySource(libraryIdentifier) if (localSource != null) { require(source == null) { - String.format( - Locale.US, - "Multiple sources found for library %s, version %s.", - libraryIdentifier.id, - libraryIdentifier.version - ) + "Multiple sources found for library ${libraryIdentifier.id}, version ${libraryIdentifier.version}." } source = localSource } } - if (source == null) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not load source for library %s, version %s.", - libraryIdentifier.id, - libraryIdentifier.version - ) - ) + requireNotNull(source) { + "Could not load source for library ${libraryIdentifier.id}, version ${libraryIdentifier.version}." } return source } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceProvider.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceProvider.kt index 2a61e3e81..506110290 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceProvider.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultLibrarySourceProvider.kt @@ -4,7 +4,6 @@ package org.cqframework.cql.cql2elm import java.io.* import java.nio.file.Path -import java.util.* import org.cqframework.cql.cql2elm.model.Version import org.hl7.elm.r1.VersionedIdentifier @@ -22,9 +21,7 @@ class DefaultLibrarySourceProvider(path: Path) : LibrarySourceProvider, PathAwar } override fun setPath(path: Path) { - require(path.toFile().isDirectory) { - String.format(Locale.US, "path '%s' is not a valid directory", path) - } + require(path.toFile().isDirectory) { "path '$path' is not a valid directory" } this.path = path } @@ -35,17 +32,14 @@ class DefaultLibrarySourceProvider(path: Path) : LibrarySourceProvider, PathAwar val libraryName: String = libraryIdentifier.id!! val libraryPath: Path = currentPath.resolve( - String.format( - Locale.US, - "%s%s.cql", - libraryName, + "$libraryName${ if (libraryIdentifier.version != null) ("-" + libraryIdentifier.version) else "" - ) + }.cql" ) var libraryFile: File? = libraryPath.toFile() if (libraryFile?.exists() != true) { - val filter = FilenameFilter { path, name -> + val filter = FilenameFilter { _, name -> name.startsWith(libraryName) && name.endsWith(".cql") } var mostRecentFile: File? = null @@ -53,7 +47,7 @@ class DefaultLibrarySourceProvider(path: Path) : LibrarySourceProvider, PathAwar val requestedVersion: Version? = if (libraryIdentifier.version == null) null else Version(libraryIdentifier.version!!) - for (file: File in currentPath.toFile().listFiles(filter)) { + for (file: File in currentPath.toFile().listFiles(filter)!!) { var fileName: String = file.name val indexOfExtension: Int = fileName.lastIndexOf(".") if (indexOfExtension >= 0) { @@ -72,9 +66,9 @@ class DefaultLibrarySourceProvider(path: Path) : LibrarySourceProvider, PathAwar @Suppress("ComplexCondition") if ( (mostRecent == null || - (((version.isComparable) && + ((version.isComparable) && (mostRecent.isComparable) && - (version.compareTo(mostRecent) > 0)))) + (version > mostRecent))) ) { mostRecent = version mostRecentFile = file @@ -106,11 +100,7 @@ class DefaultLibrarySourceProvider(path: Path) : LibrarySourceProvider, PathAwar } } catch (e: FileNotFoundException) { throw IllegalArgumentException( - String.format( - Locale.US, - "Could not load source for library %s.", - libraryIdentifier.id - ), + "Could not load source for library ${libraryIdentifier.id}.", e ) } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultModelInfoProvider.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultModelInfoProvider.kt index e998794b1..caa0541a8 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultModelInfoProvider.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/DefaultModelInfoProvider.kt @@ -4,7 +4,6 @@ package org.cqframework.cql.cql2elm import java.io.* import java.nio.file.Path -import java.util.* import org.cqframework.cql.cql2elm.model.Version import org.hl7.cql.model.ModelIdentifier import org.hl7.cql.model.ModelInfoProvider @@ -17,19 +16,15 @@ import org.hl7.elm_modelinfo.r1.serializing.ModelInfoReaderFactory // form // [.[.]] // Usage outside these boundaries will result in errors or incorrect behavior. -class DefaultModelInfoProvider : ModelInfoProvider, PathAware { - constructor() - - constructor(path: Path) { +class DefaultModelInfoProvider() : ModelInfoProvider, PathAware { + constructor(path: Path) : this() { this.setPath(path) } private var path: Path? = null override fun setPath(path: Path) { - require(path.toFile().isDirectory) { - String.format(Locale.US, "path '%s' is not a valid directory", path) - } + require(path.toFile().isDirectory) { "path '$path' is not a valid directory" } this.path = path } @@ -48,24 +43,18 @@ class DefaultModelInfoProvider : ModelInfoProvider, PathAware { val modelVersion = modelIdentifier.version val modelPath = currentPath.resolve( - String.format( - Locale.US, - "%s-modelinfo%s.xml", - modelName.lowercase(Locale.getDefault()), - if (modelVersion != null) "-$modelVersion" else "" - ) + "${modelName.lowercase()}-modelinfo${if (modelVersion != null) "-$modelVersion" else ""}.xml" ) - var modelFile: File? = modelPath.toFile() - if (modelFile?.exists() != true) { - val filter = FilenameFilter { path, name -> - name.startsWith(modelName.lowercase(Locale.getDefault()) + "-modelinfo") && - name.endsWith(".xml") + var modelFile = modelPath.toFile() + if (!modelFile.exists()) { + val filter = FilenameFilter { _, name -> + name.startsWith(modelName.lowercase() + "-modelinfo") && name.endsWith(".xml") } var mostRecentFile: File? = null var mostRecent: Version? = null try { val requestedVersion = if (modelVersion == null) null else Version(modelVersion) - for (file in currentPath.toFile().listFiles(filter)) { + for (file in currentPath.toFile().listFiles(filter)!!) { var fileName = file.name val indexOfExtension = fileName.lastIndexOf(".") if (indexOfExtension >= 0) { @@ -87,7 +76,7 @@ class DefaultModelInfoProvider : ModelInfoProvider, PathAware { mostRecent == null || version.isComparable && mostRecent.isComparable && - version.compareTo(mostRecent) > 0 + version > mostRecent ) { mostRecent = version mostRecentFile = file @@ -102,7 +91,7 @@ class DefaultModelInfoProvider : ModelInfoProvider, PathAware { } } } - modelFile = mostRecentFile + modelFile = mostRecentFile!! } catch (@Suppress("SwallowedException") e: IllegalArgumentException) { // do nothing, if the version can't be understood as a semantic version, don't // allow unspecified @@ -114,11 +103,7 @@ class DefaultModelInfoProvider : ModelInfoProvider, PathAware { return ModelInfoReaderFactory.getReader("application/xml")?.read(inputStream) } catch (e: IOException) { throw IllegalArgumentException( - String.format( - Locale.US, - "Could not load definition for model info %s.", - modelIdentifier.id - ), + "Could not load definition for model info ${modelIdentifier.id}.", e ) } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryBuilder.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryBuilder.kt index c316c036d..98214d638 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryBuilder.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryBuilder.kt @@ -17,6 +17,8 @@ import org.hl7.cql_annotations.r1.* import org.hl7.cql_annotations.r1.ObjectFactory import org.hl7.elm.r1.* +private const val FP_THIS = "\$this" + /** Created by Bryn on 12/29/2016. */ @Suppress("LargeClass", "TooManyFunctions", "ForbiddenComment", "ReturnCount", "MaxLineLength") class LibraryBuilder( @@ -32,7 +34,7 @@ class LibraryBuilder( None, /* - Indicates signatures will only be included in invocations if the declared signature of the resolve operator is different than the invocation signature + Indicates signatures will only be included in invocations if the declared signature of the resolve operator is different from the invocation signature */ Differing, @@ -69,8 +71,7 @@ class LibraryBuilder( MutableMap> = HashMap() private val libraries: MutableMap = LinkedHashMap() - private val systemFunctionResolver: SystemFunctionResolver = - SystemFunctionResolver(this, objectFactory) + private val systemFunctionResolver: SystemFunctionResolver = SystemFunctionResolver(this) private val expressionContext = Stack() private val expressionDefinitions = ExpressionDefinitionContextStack() private val functionDefs = Stack() @@ -170,13 +171,7 @@ class LibraryBuilder( "Internal Translator Error: feature name is required to perform a compatibility check" } require(isCompatibleWith(sinceCompatibilityLevel)) { - String.format( - Locale.US, - "Feature %s was introduced in version %s and so cannot be used at compatibility level %s", - featureName, - sinceCompatibilityLevel, - compatibilityLevel - ) + "Feature $featureName was introduced in version $sinceCompatibilityLevel and so cannot be used at compatibility level $compatibilityLevel" } } @@ -213,18 +208,10 @@ class LibraryBuilder( // Add the model using def to the output buildUsingDef(modelIdentifier, model, localIdentifier) } - if ( - (modelIdentifier.version != null && modelIdentifier.version != model.modelInfo.version) + require( + !(modelIdentifier.version != null && modelIdentifier.version != model.modelInfo.version) ) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not load model information for model %s, version %s because version %s is already loaded.", - modelIdentifier.id, - modelIdentifier.version, - model.modelInfo.version - ) - ) + "Could not load model information for model ${modelIdentifier.id}, version ${modelIdentifier.version} because version ${model.modelInfo.version} is already loaded." } return model } @@ -284,22 +271,14 @@ class LibraryBuilder( } @Suppress("NestedBlockDepth") - fun resolveLabel(modelName: String?, label: String): ClassType? { + private fun resolveLabel(modelName: String?, label: String): ClassType? { var result: ClassType? = null if (modelName == null || (modelName == "")) { for (model: Model? in models.values) { val modelResult: ClassType? = model!!.resolveLabel(label) if (modelResult != null) { - if (result != null) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Label %s is ambiguous between %s and %s.", - label, - result.label, - modelResult.label - ) - ) + require(result == null) { + "Label $label is ambiguous between ${(result as ClassType).label} and ${modelResult.label}." } result = modelResult } @@ -327,16 +306,8 @@ class LibraryBuilder( for (model: Model? in models.values) { val modelResult: ModelContext? = model!!.resolveContextName(contextName) if (modelResult != null) { - if (result != null) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Context name %s is ambiguous between %s and %s.", - contextName, - result.name, - modelResult.name - ) - ) + require(result == null) { + "Context name $contextName is ambiguous between ${(result as ModelContext).name} and ${modelResult.name}." } result = modelResult } @@ -369,16 +340,8 @@ class LibraryBuilder( for (model: Model? in models.values) { val modelResult: DataType? = model!!.resolveTypeName(typeName) if (modelResult != null) { - if (result != null) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Type name %s is ambiguous between %s and %s.", - typeName, - (result as NamedType).name, - (modelResult as NamedType).name - ) - ) + require(result == null) { + "Type name $typeName is ambiguous between ${(result as NamedType).name} and ${(modelResult as NamedType).name}." } result = modelResult } @@ -401,15 +364,8 @@ class LibraryBuilder( // This really should be // being done with preprocessor directives, // but that's a whole other project in and of itself. - if (!isCompatibleWith("1.5") && !isFHIRHelpers(compiledLibrary)) { - throw IllegalArgumentException( - String.format( - Locale.US, - "The type %s was introduced in CQL 1.5 and cannot be referenced at compatibility level %s", - (result as NamedType).name, - compatibilityLevel - ) - ) + require(!(!isCompatibleWith("1.5") && !isFHIRHelpers(compiledLibrary))) { + "The type ${(result as NamedType).name} was introduced in CQL 1.5 and cannot be referenced at compatibility level $compatibilityLevel" } } } @@ -430,7 +386,7 @@ class LibraryBuilder( // simpleTypeSpecifier: (identifier '.')? identifier // intervalTypeSpecifier: 'interval' '<' typeSpecifier '>' // listTypeSpecifier: 'list' '<' typeSpecifier '>' - when { + return when { typeSpecifier.lowercase(Locale.getDefault()).startsWith("interval<") -> { val pointType = resolveTypeSpecifier( @@ -439,10 +395,10 @@ class LibraryBuilder( typeSpecifier.lastIndexOf('>') ) ) - return IntervalType(pointType!!) + IntervalType(pointType!!) } else -> - return if (typeSpecifier.lowercase(Locale.getDefault()).startsWith("list<")) { + if (typeSpecifier.lowercase(Locale.getDefault()).startsWith("list<")) { val elementType = resolveTypeName( typeSpecifier.substring( @@ -475,13 +431,11 @@ class LibraryBuilder( // Special case for FHIR-derived models that include FHIR Helpers return modelManager.resolveModelByUri("http://hl7.org/fhir") } - requireNotNull(usingDef) { - String.format(Locale.US, "Could not resolve model name %s", modelName) - } + requireNotNull(usingDef) { "Could not resolve model name $modelName" } return getModel(usingDef) } - fun getModel(usingDef: UsingDef): Model { + private fun getModel(usingDef: UsingDef): Model { return getModel( ModelIdentifier( id = NamespaceManager.getNamePart(usingDef.uri)!!, @@ -504,7 +458,7 @@ class LibraryBuilder( } } - val systemLibrary: CompiledLibrary + private val systemLibrary: CompiledLibrary get() = resolveLibrary("System") fun resolveLibrary(identifier: String?): CompiledLibrary { @@ -512,15 +466,13 @@ class LibraryBuilder( checkLiteralContext() } return libraries[identifier] - ?: throw IllegalArgumentException( - String.format(Locale.US, "Could not resolve library name %s.", identifier) - ) + ?: throw IllegalArgumentException("Could not resolve library name $identifier.") } fun resolveNamespaceUri(namespaceName: String, mustResolve: Boolean): String? { val namespaceUri = libraryManager.namespaceManager.resolveNamespaceUri(namespaceName) require(!(namespaceUri == null && mustResolve)) { - String.format(Locale.US, "Could not resolve namespace name %s", namespaceName) + "Could not resolve namespace name $namespaceName" } return namespaceUri } @@ -566,10 +518,7 @@ class LibraryBuilder( errorSeverity == CqlCompilerException.ErrorSeverity.Error) CqlCompilerException.ErrorSeverity.Error -> errorSeverity == CqlCompilerException.ErrorSeverity.Error - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown error severity %s", errorSeverity.toString()) - ) + else -> throw IllegalArgumentException("Unknown error severity $errorSeverity") } } @@ -610,22 +559,8 @@ class LibraryBuilder( } } - private val libraryName: String - get() { - var libraryName = library.identifier!!.id - if (libraryName == null) { - libraryName = "Anonymous" - } - if (library.identifier!!.system != null) { - libraryName = library.identifier!!.system + "/" + libraryName - } - return libraryName - } - fun beginTranslation() { loadSystemLibrary() - - // libraryManager.beginCompilation(getLibraryName()); } var libraryIdentifier: VersionedIdentifier? @@ -637,7 +572,6 @@ class LibraryBuilder( fun endTranslation() { applyTargetModelMaps() - // libraryManager.endCompilation(getLibraryName()); } fun canResolveLibrary(includeDef: IncludeDef): Boolean { @@ -671,7 +605,7 @@ class LibraryBuilder( // Note that translation of a referenced library may result in implicit specification of the // namespace - // In this case, the referencedLibrary will have a namespaceUri different than the currently + // In this case, the referencedLibrary will have a namespaceUri different from the currently // resolved // namespaceUri // of the IncludeDef. @@ -758,7 +692,7 @@ class LibraryBuilder( return compiledLibrary.resolveIncludeRef(identifier) } - fun resolveIncludeAlias(libraryIdentifier: VersionedIdentifier): String? { + private fun resolveIncludeAlias(libraryIdentifier: VersionedIdentifier): String? { return compiledLibrary.resolveIncludeAlias(libraryIdentifier) } @@ -812,8 +746,8 @@ class LibraryBuilder( libraryName, operatorName, UnaryExpressionInvocation(expression), - false, - false + allowPromotionAndDemotion = false, + allowFluent = false ) } @@ -871,8 +805,8 @@ class LibraryBuilder( libraryName, operatorName, TernaryExpressionInvocation(expression), - false, - false + allowPromotionAndDemotion = false, + allowFluent = false ) } @@ -885,8 +819,8 @@ class LibraryBuilder( libraryName, operatorName, NaryExpressionInvocation(expression!!), - false, - false + allowPromotionAndDemotion = false, + allowFluent = false ) } @@ -899,8 +833,8 @@ class LibraryBuilder( libraryName, operatorName, AggregateExpressionInvocation(expression), - false, - false + allowPromotionAndDemotion = false, + allowFluent = false ) } @@ -1094,7 +1028,7 @@ class LibraryBuilder( return result?.expression } - fun resolveInInvocation( + private fun resolveInInvocation( left: Expression, right: Expression, dateTimePrecision: DateTimePrecision? @@ -1113,7 +1047,7 @@ class LibraryBuilder( return result?.expression } - fun resolveProperInInvocation( + private fun resolveProperInInvocation( left: Expression, right: Expression, dateTimePrecision: DateTimePrecision? @@ -1132,7 +1066,7 @@ class LibraryBuilder( return result?.expression } - fun resolveContainsInvocation( + private fun resolveContainsInvocation( left: Expression, right: Expression, dateTimePrecision: DateTimePrecision? @@ -1151,7 +1085,7 @@ class LibraryBuilder( return result?.expression } - fun resolveProperContainsInvocation( + private fun resolveProperContainsInvocation( left: Expression, right: Expression, dateTimePrecision: DateTimePrecision? @@ -1219,11 +1153,23 @@ class LibraryBuilder( val includes = objectFactory.createIncludes().withOperand(left, right).withPrecision(dateTimePrecision) val includesInvocation = - resolveBinaryInvocation("System", "Includes", includes, false, false) + resolveBinaryInvocation( + "System", + "Includes", + includes, + mustResolve = false, + allowPromotionAndDemotion = false + ) val contains = objectFactory.createContains().withOperand(left, right).withPrecision(dateTimePrecision) val containsInvocation = - resolveBinaryInvocation("System", "Contains", contains, false, false) + resolveBinaryInvocation( + "System", + "Contains", + contains, + mustResolve = false, + allowPromotionAndDemotion = false + ) return lowestScoringInvocation(includesInvocation, containsInvocation) ?: resolveBinaryCall("System", "Includes", includes) @@ -1241,14 +1187,26 @@ class LibraryBuilder( .withOperand(left, right) .withPrecision(dateTimePrecision) val properIncludesInvocation = - resolveBinaryInvocation("System", "ProperIncludes", properIncludes, false, false) + resolveBinaryInvocation( + "System", + "ProperIncludes", + properIncludes, + mustResolve = false, + allowPromotionAndDemotion = false + ) val properContains = objectFactory .createProperContains() .withOperand(left, right) .withPrecision(dateTimePrecision) val properContainsInvocation = - resolveBinaryInvocation("System", "ProperContains", properContains, false, false) + resolveBinaryInvocation( + "System", + "ProperContains", + properContains, + mustResolve = false, + allowPromotionAndDemotion = false + ) return lowestScoringInvocation(properIncludesInvocation, properContainsInvocation) ?: resolveBinaryCall("System", "ProperIncludes", properIncludes) @@ -1266,10 +1224,23 @@ class LibraryBuilder( .withOperand(left, right) .withPrecision(dateTimePrecision) val includedInInvocation = - resolveBinaryInvocation("System", "IncludedIn", includedIn, false, false) + resolveBinaryInvocation( + "System", + "IncludedIn", + includedIn, + mustResolve = false, + allowPromotionAndDemotion = false + ) val inExpression = objectFactory.createIn().withOperand(left, right).withPrecision(dateTimePrecision) - val inInvocation = resolveBinaryInvocation("System", "In", inExpression, false, false) + val inInvocation = + resolveBinaryInvocation( + "System", + "In", + inExpression, + mustResolve = false, + allowPromotionAndDemotion = false + ) return lowestScoringInvocation(includedInInvocation, inInvocation) ?: resolveBinaryCall("System", "IncludedIn", includedIn) @@ -1287,11 +1258,23 @@ class LibraryBuilder( .withOperand(left, right) .withPrecision(dateTimePrecision) val properIncludedInInvocation = - resolveBinaryInvocation("System", "ProperIncludedIn", properIncludedIn, false, false) + resolveBinaryInvocation( + "System", + "ProperIncludedIn", + properIncludedIn, + mustResolve = false, + allowPromotionAndDemotion = false + ) val properIn = objectFactory.createProperIn().withOperand(left, right).withPrecision(dateTimePrecision) val properInInvocation = - resolveBinaryInvocation("System", "ProperIn", properIn, false, false) + resolveBinaryInvocation( + "System", + "ProperIn", + properIn, + mustResolve = false, + allowPromotionAndDemotion = false + ) return lowestScoringInvocation(properIncludedInInvocation, properInInvocation) ?: resolveBinaryCall("System", "ProperIncludedIn", properIncludedIn) @@ -1303,10 +1286,17 @@ class LibraryBuilder( operatorName: String, invocation: Invocation ): Expression? { - return resolveCall(libraryName, operatorName, invocation, true, false, false) + return resolveCall( + libraryName, + operatorName, + invocation, + mustResolve = true, + allowPromotionAndDemotion = false, + allowFluent = false + ) } - fun resolveCall( + private fun resolveCall( libraryName: String?, operatorName: String, invocation: Invocation, @@ -1324,7 +1314,7 @@ class LibraryBuilder( } @Suppress("LongParameterList") - fun resolveCall( + private fun resolveCall( libraryName: String?, operatorName: String, invocation: Invocation, @@ -1362,7 +1352,7 @@ class LibraryBuilder( } @Suppress("LongParameterList") - fun buildCallContext( + private fun buildCallContext( libraryName: String?, operatorName: String, operands: Iterable, @@ -1373,12 +1363,7 @@ class LibraryBuilder( val dataTypes: MutableList = ArrayList() for (operand in operands) { require(!(operand == null || operand.resultType == null)) { - String.format( - Locale.US, - "Could not determine signature for invocation of operator %s%s.", - if (libraryName == null) "" else "$libraryName.", - operatorName - ) + "Could not determine signature for invocation of operator ${if (libraryName == null) "" else "$libraryName."}$operatorName." } dataTypes.add(operand.resultType!!) } @@ -1450,15 +1435,17 @@ class LibraryBuilder( // resolution with system functions // WARNING: reportWarning( - String.format( - "The function %s.%s has multiple overloads and due to the SignatureLevel setting (%s), " + - "the overload signature is not being included in the output. This may result in ambiguous function resolution " + - "at runtime, consider setting the SignatureLevel to Overloads or All to ensure that the output includes sufficient " + - "information to support correct overload selection at runtime.", - resolution.operator.libraryName, - resolution.operator.name, - options.signatureLevel.name - ), + """ + The function ${resolution.operator.libraryName}.${resolution.operator.name} has multiple overloads + and due to the SignatureLevel setting (${options.signatureLevel.name}), + the overload signature is not being included in the output. + This may result in ambiguous function resolution + at runtime, consider setting the SignatureLevel to Overloads or All + to ensure that the output includes sufficient + information to support correct overload selection at runtime. + """ + .trimIndent() + .replace("\n", " "), invocation.expression ) } @@ -1487,12 +1474,7 @@ class LibraryBuilder( val dataTypes: MutableList = ArrayList() for (operand in fd.operand) { requireNotNull(operand.resultType) { - String.format( - Locale.US, - "Could not determine signature for invocation of operator %s%s.", - if (libraryName == null) "" else "$libraryName.", - operatorName - ) + "Could not determine signature for invocation of operator ${if (libraryName == null) "" else "$libraryName."}$operatorName." } dataTypes.add(operand.resultType!!) } @@ -1510,7 +1492,7 @@ class LibraryBuilder( } @Suppress("NestedBlockDepth") - fun resolveCall(callContext: CallContext): OperatorResolution? { + private fun resolveCall(callContext: CallContext): OperatorResolution? { var result: OperatorResolution? if (callContext.libraryName.isNullOrEmpty()) { result = compiledLibrary.resolveCall(callContext, conversionMap) @@ -1564,35 +1546,18 @@ class LibraryBuilder( } else false } - fun checkOperator(callContext: CallContext, resolution: OperatorResolution?) { + private fun checkOperator(callContext: CallContext, resolution: OperatorResolution?) { requireNotNull(resolution) { // ERROR: - String.format( - Locale.US, - "Could not resolve call to operator %s with signature %s.", - callContext.operatorName, - callContext.signature - ) + "Could not resolve call to operator ${callContext.operatorName} with signature ${callContext.signature}." } - if (resolution.operator.fluent && !callContext.allowFluent) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Operator %s with signature %s is a fluent function and can only be invoked with fluent syntax.", - callContext.operatorName, - callContext.signature - ) - ) + require(!(resolution.operator.fluent && !callContext.allowFluent)) { + "Operator ${callContext.operatorName} with signature ${callContext.signature} is a fluent function and can only be invoked with fluent syntax." } - if (callContext.allowFluent && !resolution.operator.fluent && !resolution.allowFluent) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invocation of operator %s with signature %s uses fluent syntax, but the operator is not defined as a fluent function.", - callContext.operatorName, - callContext.signature - ) - ) + require( + !(callContext.allowFluent && !resolution.operator.fluent && !resolution.allowFluent) + ) { + "Invocation of operator ${callContext.operatorName} with signature ${callContext.signature} uses fluent syntax, but the operator is not defined as a fluent function." } } @@ -1607,12 +1572,7 @@ class LibraryBuilder( ) { // ERROR: throw CqlSemanticException( - String.format( - Locale.US, - "Identifier %s in library %s is marked private and cannot be referenced from another library.", - objectName, - libraryName - ) + "Identifier $objectName in library $libraryName is marked private and cannot be referenced from another library." ) } } @@ -1622,7 +1582,15 @@ class LibraryBuilder( functionName: String, paramList: List ): Expression? { - return resolveFunction(libraryName, functionName, paramList, true, false, false)?.expression + return resolveFunction( + libraryName, + functionName, + paramList, + mustResolve = true, + allowPromotionAndDemotion = false, + allowFluent = false + ) + ?.expression } private fun buildFunctionRef( @@ -1692,9 +1660,8 @@ class LibraryBuilder( functionRef = buildFunctionRef(libraryName, functionName, paramList) invocation = FunctionRefInvocation(functionRef) if (!allowFluent) { - // Only attempt to resolve as a system function if this is not a fluent call or it - // is a required - // resolution + // Only attempt to resolve as a system function if + // this is not a fluent call, or it is a required resolution val systemFunction = systemFunctionResolver.resolveSystemFunction(functionRef) if (systemFunction != null) { return systemFunction @@ -1749,7 +1716,7 @@ class LibraryBuilder( .createAliasedQuerySource() .withAlias("X") .withExpression(expression) - .withResultType(fromType) as AliasedQuerySource + .withResultType(fromType) ) .withReturn( objectFactory @@ -1760,13 +1727,13 @@ class LibraryBuilder( objectFactory .createAliasRef() .withName("X") - .withResultType(fromType.elementType) as AliasRef, + .withResultType(fromType.elementType), conversion.conversion!! ) ) - .withResultType(toType) as ReturnClause + .withResultType(toType) ) - .withResultType(toType) as Query + .withResultType(toType) } private fun reportWarning(message: String, expression: Element?) { @@ -1843,7 +1810,7 @@ class LibraryBuilder( // constructing an // interval // with null boundaries - fun resolveToInterval(expression: Expression?): Expression { + private fun resolveToInterval(expression: Expression?): Expression { val condition = objectFactory.createIf() condition.condition = buildIsNull(expression) condition.then = buildNull(IntervalType(expression!!.resultType!!)) @@ -1874,7 +1841,7 @@ class LibraryBuilder( .createProperty() .withSource(expression) .withPath("low") - .withResultType(fromType.pointType) as Property, + .withResultType(fromType.pointType), conversion.conversion!! ) ) @@ -1883,7 +1850,7 @@ class LibraryBuilder( .createProperty() .withSource(expression) .withPath("lowClosed") - .withResultType(resolveTypeName("System", "Boolean")) as Property + .withResultType(resolveTypeName("System", "Boolean")) ) .withHigh( convertExpression( @@ -1891,7 +1858,7 @@ class LibraryBuilder( .createProperty() .withSource(expression) .withPath("high") - .withResultType(fromType.pointType) as Property, + .withResultType(fromType.pointType), conversion.conversion ) ) @@ -1900,13 +1867,13 @@ class LibraryBuilder( .createProperty() .withSource(expression) .withPath("highClosed") - .withResultType(resolveTypeName("System", "Boolean")) as Property + .withResultType(resolveTypeName("System", "Boolean")) ) - .withResultType(toType) as Interval + .withResultType(toType) } fun buildAs(expression: Expression?, asType: DataType?): As { - val result = objectFactory.createAs().withOperand(expression).withResultType(asType) as As + val result = objectFactory.createAs().withOperand(expression).withResultType(asType) if (result.resultType is NamedType) { result.asType = dataTypeToQName(result.resultType) } else { @@ -1920,7 +1887,7 @@ class LibraryBuilder( objectFactory .createIs() .withOperand(expression) - .withResultType(resolveTypeName("System", "Boolean")) as Is + .withResultType(resolveTypeName("System", "Boolean")) if (isType is NamedType) { result.isType = dataTypeToQName(isType) } else { @@ -1930,7 +1897,7 @@ class LibraryBuilder( } fun buildNull(nullType: DataType?): Null { - val result = objectFactory.createNull().withResultType(nullType) as Null + val result = objectFactory.createNull().withResultType(nullType) if (nullType is NamedType) { result.resultTypeName = dataTypeToQName(nullType) } else { @@ -1939,13 +1906,13 @@ class LibraryBuilder( return result } - fun buildIsNull(expression: Expression?): IsNull { + private fun buildIsNull(expression: Expression?): IsNull { val isNull = objectFactory.createIsNull().withOperand(expression) isNull.resultType = resolveTypeName("System", "Boolean") return isNull } - fun buildIsNotNull(expression: Expression?): Not { + private fun buildIsNotNull(expression: Expression?): Not { val isNull = buildIsNull(expression) val not = objectFactory.createNot().withOperand(isNull) not.resultType = resolveTypeName("System", "Boolean") @@ -1985,170 +1952,179 @@ class LibraryBuilder( (conversion.fromType.isSuperTypeOf(conversion.toType) || conversion.fromType.isCompatibleWith(conversion.toType)) ) { - if (conversion.fromType is ChoiceType && conversion.toType is ChoiceType) { - if ( - (conversion.fromType as ChoiceType).isSubSetOf(conversion.toType as ChoiceType) - ) { - // conversion between compatible choice types requires no cast (i.e. - // choice can be - // safely passed to choice - return expression - } - // Otherwise, the choice is narrowing and a run-time As is required (to use only the - // expected target - // types) + // Otherwise, the choice is narrowing and a run-time As is required (to use only the + // expected target + // types) + if ( + conversion.fromType is ChoiceType && + conversion.toType is ChoiceType && + (conversion.fromType).isSubSetOf(conversion.toType) + ) { + // conversion between compatible choice types requires no cast (i.e. + // choice can be + // safely passed to choice + return expression } val castedOperand = buildAs(expression, conversion.toType) collapseTypeCase(castedOperand) } else @Suppress("ComplexCondition") - if ( + when { conversion.isCast && conversion.conversion != null && (conversion.fromType.isSuperTypeOf(conversion.conversion.fromType) || - conversion.fromType.isCompatibleWith(conversion.conversion.fromType)) - ) { - val castedOperand = buildAs(expression, conversion.conversion.fromType) - var result = convertExpression(castedOperand, conversion.conversion) - if (conversion.hasAlternativeConversions()) { - val caseResult = objectFactory.createCase() - caseResult.resultType = result.resultType - caseResult.caseItem.add( - objectFactory - .createCaseItem() - .withWhen(buildIs(expression, conversion.conversion.fromType)) - .withThen(result) - ) - for (alternative: Conversion in conversion.getAlternativeConversions()) { + conversion.fromType.isCompatibleWith(conversion.conversion.fromType)) -> { + val castedOperand = buildAs(expression, conversion.conversion.fromType) + var result = convertExpression(castedOperand, conversion.conversion) + if (conversion.hasAlternativeConversions()) { + val caseResult = objectFactory.createCase() + caseResult.resultType = result.resultType caseResult.caseItem.add( objectFactory .createCaseItem() - .withWhen(buildIs(expression, alternative.fromType)) - .withThen( - convertExpression( - buildAs(expression, alternative.fromType), - alternative - ) - ) + .withWhen(buildIs(expression, conversion.conversion.fromType)) + .withThen(result) ) + for (alternative: Conversion in conversion.getAlternativeConversions()) { + caseResult.caseItem.add( + objectFactory + .createCaseItem() + .withWhen(buildIs(expression, alternative.fromType)) + .withThen( + convertExpression( + buildAs(expression, alternative.fromType), + alternative + ) + ) + ) + } + caseResult.withElse(buildNull(result.resultType)) + result = caseResult } - caseResult.withElse(buildNull(result.resultType)) - result = caseResult + result } - result - } else if (conversion.isListConversion) { - convertListExpression(expression, conversion) - } else if (conversion.isListDemotion) { - demoteListExpression(expression, conversion) - } else if (conversion.isListPromotion) { - promoteListExpression(expression, conversion) - } else if (conversion.isIntervalConversion) { - convertIntervalExpression(expression, conversion) - } else if (conversion.isIntervalDemotion) { - demoteIntervalExpression(expression, conversion) - } else if (conversion.isIntervalPromotion) { - promoteIntervalExpression(expression, conversion) - } else if (conversion.operator != null) { - val functionRef = - objectFactory - .createFunctionRef() - .withLibraryName(conversion.operator.libraryName) - .withName(conversion.operator.name) - .withOperand(expression) as FunctionRef - val systemFunctionInvocation = - systemFunctionResolver.resolveSystemFunction(functionRef) - if (systemFunctionInvocation != null) { - return systemFunctionInvocation.expression + conversion.isListConversion -> { + convertListExpression(expression, conversion) } - resolveCall( - functionRef.libraryName, - functionRef.name!!, - FunctionRefInvocation(functionRef), - false, - false - ) - functionRef - } else { - when (conversion.toType) { - resolveTypeName("System", "Boolean") -> { - objectFactory - .createToBoolean() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Integer") -> { - objectFactory - .createToInteger() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Long") -> { - objectFactory - .createToLong() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Decimal") -> { - objectFactory - .createToDecimal() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "String") -> { - objectFactory - .createToString() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Date") -> { - objectFactory - .createToDate() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "DateTime") -> { - objectFactory - .createToDateTime() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Time") -> { - objectFactory - .createToTime() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Quantity") -> { - objectFactory - .createToQuantity() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Ratio") -> { - objectFactory - .createToRatio() - .withOperand(expression) - .withResultType(conversion.toType) as Expression - } - resolveTypeName("System", "Concept") -> { + conversion.isListDemotion -> { + demoteListExpression(expression, conversion) + } + conversion.isListPromotion -> { + promoteListExpression(expression, conversion) + } + conversion.isIntervalConversion -> { + convertIntervalExpression(expression, conversion) + } + conversion.isIntervalDemotion -> { + demoteIntervalExpression(expression, conversion) + } + conversion.isIntervalPromotion -> { + promoteIntervalExpression(expression, conversion) + } + conversion.operator != null -> { + val functionRef = objectFactory - .createToConcept() + .createFunctionRef() + .withLibraryName(conversion.operator.libraryName) + .withName(conversion.operator.name) .withOperand(expression) - .withResultType(conversion.toType) as Expression + val systemFunctionInvocation = + systemFunctionResolver.resolveSystemFunction(functionRef) + if (systemFunctionInvocation != null) { + return systemFunctionInvocation.expression } - else -> { - val convertedOperand = + resolveCall( + functionRef.libraryName, + functionRef.name!!, + FunctionRefInvocation(functionRef), + allowPromotionAndDemotion = false, + allowFluent = false + ) + functionRef + } + else -> { + when (conversion.toType) { + resolveTypeName("System", "Boolean") -> { objectFactory - .createConvert() + .createToBoolean() .withOperand(expression) - .withResultType(conversion.toType) as Convert - if (convertedOperand.resultType is NamedType) { - convertedOperand.toType = dataTypeToQName(convertedOperand.resultType) - } else { - convertedOperand.toTypeSpecifier = - dataTypeToTypeSpecifier(convertedOperand.resultType) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Integer") -> { + objectFactory + .createToInteger() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Long") -> { + objectFactory + .createToLong() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Decimal") -> { + objectFactory + .createToDecimal() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "String") -> { + objectFactory + .createToString() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Date") -> { + objectFactory + .createToDate() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "DateTime") -> { + objectFactory + .createToDateTime() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Time") -> { + objectFactory + .createToTime() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Quantity") -> { + objectFactory + .createToQuantity() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Ratio") -> { + objectFactory + .createToRatio() + .withOperand(expression) + .withResultType(conversion.toType) + } + resolveTypeName("System", "Concept") -> { + objectFactory + .createToConcept() + .withOperand(expression) + .withResultType(conversion.toType) + } + else -> { + val convertedOperand = + objectFactory + .createConvert() + .withOperand(expression) + .withResultType(conversion.toType) + if (convertedOperand.resultType is NamedType) { + convertedOperand.toType = + dataTypeToQName(convertedOperand.resultType) + } else { + convertedOperand.toTypeSpecifier = + dataTypeToTypeSpecifier(convertedOperand.resultType) + } + convertedOperand } - convertedOperand } } } @@ -2200,7 +2176,13 @@ class LibraryBuilder( if (expectedType.isSuperTypeOf(actualType) || actualType.isCompatibleWith(expectedType)) { return } - val conversion = findConversion(actualType, expectedType, true, false) + val conversion = + findConversion( + actualType, + expectedType, + implicit = true, + allowPromotionAndDemotion = false + ) if (conversion != null) { return } @@ -2228,11 +2210,13 @@ class LibraryBuilder( // eliminate choices // based on convertibility if (!(first is ChoiceType || second is ChoiceType)) { - var conversion = findConversion(second, first, true, false) + var conversion = + findConversion(second, first, implicit = true, allowPromotionAndDemotion = false) if (conversion != null) { return first } - conversion = findConversion(first, second, true, false) + conversion = + findConversion(first, second, implicit = true, allowPromotionAndDemotion = false) if (conversion != null) { return second } @@ -2254,7 +2238,7 @@ class LibraryBuilder( return first } - fun ensureCompatible(expression: Expression?, targetType: DataType?): Expression? { + fun ensureCompatible(expression: Expression?, targetType: DataType?): Expression { if (targetType == null) { return objectFactory.createNull() } @@ -2263,7 +2247,7 @@ class LibraryBuilder( } else expression } - fun enforceCompatible(expression: Expression?, targetType: DataType?): Expression? { + fun enforceCompatible(expression: Expression?, targetType: DataType?): Expression { if (targetType == null) { return objectFactory.createNull() } @@ -2272,7 +2256,7 @@ class LibraryBuilder( } else expression } - fun createLiteral(value: String?, type: String): Literal { + private fun createLiteral(value: String?, type: String): Literal { val resultType = resolveTypeName("System", type) val result = objectFactory @@ -2322,7 +2306,7 @@ class LibraryBuilder( return result } - fun validateUnit(unit: String) { + private fun validateUnit(unit: String) { when (unit) { "year", "years", @@ -2413,7 +2397,7 @@ class LibraryBuilder( return typeBuilder.dataTypeToQName(type) } - fun dataTypesToTypeSpecifiers(types: List): List { + private fun dataTypesToTypeSpecifiers(types: List): List { return typeBuilder.dataTypesToTypeSpecifiers(types) } @@ -2451,133 +2435,110 @@ class LibraryBuilder( ): PropertyResolution? { var currentType: DataType? = sourceType while (currentType != null) { - if (currentType is ClassType) { - val classType: ClassType = currentType - if (identifier.startsWith("?") && isCompatibleWith("1.5")) { - val searchPath: String = identifier.substring(1) - for (s: SearchType in classType.getSearches()) { - if ((s.name == searchPath)) { - return PropertyResolution(s) + when { + currentType is ClassType -> { + val classType: ClassType = currentType + if (identifier.startsWith("?") && isCompatibleWith("1.5")) { + val searchPath: String = identifier.substring(1) + for (s: SearchType in classType.getSearches()) { + if ((s.name == searchPath)) { + return PropertyResolution(s) + } } - } - } else { - for (e: ClassTypeElement in classType.elements) { - if ((e.name == identifier)) { - if (e.prohibited) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Element %s cannot be referenced because it is marked prohibited in type %s.", - e.name, - currentType.name - ) - ) + } else { + for (e: ClassTypeElement in classType.elements) { + if ((e.name == identifier)) { + require(!e.prohibited) { + "Element ${e.name} cannot be referenced because it is marked prohibited in type ${(currentType as ClassType).name}." + } + return PropertyResolution(e) } - return PropertyResolution(e) } } } - } else if (currentType is TupleType) { - for (e: TupleTypeElement in currentType.elements) { - if ((e.name == identifier)) { - return PropertyResolution(e) + currentType is TupleType -> { + for (e: TupleTypeElement in currentType.elements) { + if ((e.name == identifier)) { + return PropertyResolution(e) + } } } - } else if (currentType is IntervalType) { - return when (identifier) { - "low", - "high" -> PropertyResolution(currentType.pointType, identifier) - "lowClosed", - "highClosed" -> - PropertyResolution((resolveTypeName("System", "Boolean"))!!, identifier) - else -> // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid interval property name %s.", - identifier + currentType is IntervalType -> { + return when (identifier) { + "low", + "high" -> PropertyResolution(currentType.pointType, identifier) + "lowClosed", + "highClosed" -> + PropertyResolution((resolveTypeName("System", "Boolean"))!!, identifier) + else -> // ERROR: + throw IllegalArgumentException( + "Invalid interval property name $identifier." ) - ) + } } - } else if (currentType is ChoiceType) { - // TODO: Issue a warning if the property does not resolve against every type in the - // choice - - // Resolve the property against each type in the choice - val resultTypes: MutableSet = HashSet() - val resultTargetMaps: MutableMap = HashMap() - var name: String? = null - for (choice: DataType in currentType.types) { - val resolution: PropertyResolution? = resolveProperty(choice, identifier, false) - if (resolution != null) { - resultTypes.add(resolution.type) - if (resolution.targetMap != null) { - if (resultTargetMaps.containsKey(resolution.type)) { - if (resultTargetMaps[resolution.type] != resolution.targetMap) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Inconsistent target maps %s and %s for choice type %s", - resultTargetMaps[resolution.type], - resolution.targetMap, - resolution.type - ) - ) + currentType is ChoiceType -> { + // TODO: Issue a warning if the property does not resolve against every type in + // the + // choice + + // Resolve the property against each type in the choice + val resultTypes: MutableSet = HashSet() + val resultTargetMaps: MutableMap = HashMap() + var name: String? = null + for (choice: DataType in currentType.types) { + val resolution: PropertyResolution? = + resolveProperty(choice, identifier, false) + if (resolution != null) { + resultTypes.add(resolution.type) + if (resolution.targetMap != null) { + if (resultTargetMaps.containsKey(resolution.type)) { + require( + resultTargetMaps[resolution.type] == resolution.targetMap + ) { + "Inconsistent target maps ${resultTargetMaps[resolution.type]} and ${resolution.targetMap} for choice type ${resolution.type}" + } + } else { + resultTargetMaps[resolution.type] = resolution.targetMap } - } else { - resultTargetMaps[resolution.type] = resolution.targetMap } - } - if (name == null) { - name = resolution.name - } else if (name != resolution.name) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Inconsistent property resolution for choice type %s (was %s, is %s)", - choice.toString(), - name, - resolution.name - ) - ) + if (name == null) { + name = resolution.name + } else + require(name == resolution.name) { + "Inconsistent property resolution for choice type $choice (was $name, is ${resolution.name})" + } } } - } - // The result type is a choice of all the resolved types - if (resultTypes.size > 1) { - return PropertyResolution(ChoiceType(resultTypes), name!!, resultTargetMaps) + // The result type is a choice of all the resolved types + if (resultTypes.size > 1) { + return PropertyResolution(ChoiceType(resultTypes), name!!, resultTargetMaps) + } + if (resultTypes.size == 1) { + return PropertyResolution( + resultTypes.iterator().next(), + name!!, + resultTargetMaps + ) + } } - if (resultTypes.size == 1) { - return PropertyResolution( - resultTypes.iterator().next(), - name!!, - resultTargetMaps - ) + currentType is ListType && listTraversal -> { + // NOTE: FHIRPath path traversal support + // Resolve property as a list of items of property of the element type + val resolution: PropertyResolution? = + resolveProperty(currentType.elementType, identifier) + return PropertyResolution(ListType(resolution!!.type), (resolution.targetMap)!!) } - } else if (currentType is ListType && listTraversal) { - // NOTE: FHIRPath path traversal support - // Resolve property as a list of items of property of the element type - val resolution: PropertyResolution? = - resolveProperty(currentType.elementType, identifier) - return PropertyResolution(ListType(resolution!!.type), (resolution.targetMap)!!) } - if (currentType.baseType != null) { + if (currentType.baseType != DataType.ANY) { currentType = currentType.baseType } else { break } } - if (mustResolve) { + require(!mustResolve) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Member %s not found for type %s.", - identifier, - sourceType?.toLabel() - ) - ) + "Member $identifier not found for type ${sourceType?.toLabel()}." } return null } @@ -2659,15 +2620,9 @@ class LibraryBuilder( val expressionRef: ExpressionRef = objectFactory.createExpressionRef().withName(element.name) expressionRef.resultType = getExpressionDefResultType(element) - if (expressionRef.resultType == null) { + requireNotNull(expressionRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to expression %s because its definition contains errors.", - expressionRef.name - ) - ) + "Could not validate reference to expression ${expressionRef.name} because its definition contains errors." } return expressionRef } @@ -2676,15 +2631,9 @@ class LibraryBuilder( val parameterRef: ParameterRef = objectFactory.createParameterRef().withName(element.name) parameterRef.resultType = element.resultType - if (parameterRef.resultType == null) { + requireNotNull(parameterRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to parameter %s because its definition contains errors.", - parameterRef.name - ) - ) + "Could not validate reference to parameter ${parameterRef.name} because its definition contains errors." } return parameterRef } @@ -2693,15 +2642,9 @@ class LibraryBuilder( val valuesetRef: ValueSetRef = objectFactory.createValueSetRef().withName(element.name) valuesetRef.resultType = element.resultType - if (valuesetRef.resultType == null) { + requireNotNull(valuesetRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to valueset %s because its definition contains errors.", - valuesetRef.name - ) - ) + "Could not validate reference to valueset ${valuesetRef.name} because its definition contains errors." } if (isCompatibleWith("1.5")) { valuesetRef.preserve = true @@ -2713,15 +2656,9 @@ class LibraryBuilder( val codesystemRef: CodeSystemRef = objectFactory.createCodeSystemRef().withName(element.name) codesystemRef.resultType = element.resultType - if (codesystemRef.resultType == null) { + requireNotNull(codesystemRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to codesystem %s because its definition contains errors.", - codesystemRef.name - ) - ) + "Could not validate reference to codesystem ${codesystemRef.name} because its definition contains errors." } return codesystemRef } @@ -2729,15 +2666,9 @@ class LibraryBuilder( checkLiteralContext() val codeRef: CodeRef = objectFactory.createCodeRef().withName(element.name) codeRef.resultType = element.resultType - if (codeRef.resultType == null) { + requireNotNull(codeRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to code %s because its definition contains errors.", - codeRef.name - ) - ) + "Could not validate reference to code ${codeRef.name} because its definition contains errors." } return codeRef } @@ -2745,15 +2676,9 @@ class LibraryBuilder( checkLiteralContext() val conceptRef: ConceptRef = objectFactory.createConceptRef().withName(element.name) conceptRef.resultType = element.resultType - if (conceptRef.resultType == null) { + requireNotNull(conceptRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to concept %s because its definition contains error.", - conceptRef.name - ) - ) + "Could not validate reference to concept ${conceptRef.name} because its definition contains error." } return conceptRef } @@ -2787,12 +2712,7 @@ class LibraryBuilder( // ERROR: var message = resolvedIdentifierContext.warnCaseInsensitiveIfApplicable() if (message == null) { - message = - String.format( - Locale.US, - "Could not resolve identifier %s in the current library.", - identifier - ) + message = "Could not resolve identifier $identifier in the current library." } throw IllegalArgumentException(message) @@ -2822,15 +2742,9 @@ class LibraryBuilder( val parameterRef: ParameterRef = objectFactory.createParameterRef().withName(contextParameter.name) parameterRef.resultType = contextParameter.resultType - if (parameterRef.resultType == null) { + requireNotNull(parameterRef.resultType) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not validate reference to parameter %s because its definition contains errors.", - parameterRef.name - ) - ) + "Could not validate reference to parameter ${parameterRef.name} because its definition contains errors." } return parameterRef } @@ -2881,15 +2795,11 @@ class LibraryBuilder( if (model.modelInfo.targetUrl != null) { if (result != null) { reportWarning( - String.format( - Locale.US, - "Duplicate mapped model %s:%s%s", - model.modelInfo.name, - model.modelInfo.targetUrl, + "Duplicate mapped model ${model.modelInfo.name}:${model.modelInfo.targetUrl}${ if (model.modelInfo.targetVersion != null) "|" + model.modelInfo.targetVersion else "" - ), + }", sourceContext ) } @@ -2968,86 +2878,82 @@ class LibraryBuilder( // If there is a trailing qualified path, the query is wrapped in a singletonFrom and a // property access // Any other target map results in an exception - if (targetMap.contains(";")) { - val typeCases: Array = - targetMap.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - val c: Case = objectFactory.createCase() - for (typeCase: String in typeCases) { - if (typeCase.isNotEmpty()) { - val splitIndex: Int = typeCase.indexOf(':') - if (splitIndex <= 0) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Malformed type case in targetMap %s", - targetMap - ) - ) + when { + targetMap.contains(";") -> { + val typeCases: Array = + targetMap.split(";".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + val c: Case = objectFactory.createCase() + for (typeCase: String in typeCases) { + if (typeCase.isNotEmpty()) { + val splitIndex: Int = typeCase.indexOf(':') + require(splitIndex > 0) { "Malformed type case in targetMap $targetMap" } + val typeCaseElement: String = typeCase.substring(0, splitIndex) + val typeCaseType: DataType? = resolveTypeName(typeCaseElement) + val typeCaseMap: String = typeCase.substring(splitIndex + 1) + val ci: CaseItem = + objectFactory + .createCaseItem() + .withWhen( + objectFactory + .createIs() + .withOperand(applyTargetMap(source, typeCaseMap)) + .withIsType(dataTypeToQName(typeCaseType)) + ) + .withThen(applyTargetMap(source, typeCaseMap)) + ci.then!!.resultType = typeCaseType + c.caseItem.add(ci) } - val typeCaseElement: String = typeCase.substring(0, splitIndex) - val typeCaseType: DataType? = resolveTypeName(typeCaseElement) - val typeCaseMap: String = typeCase.substring(splitIndex + 1) - val ci: CaseItem = - objectFactory - .createCaseItem() - .withWhen( - objectFactory - .createIs() - .withOperand(applyTargetMap(source, typeCaseMap)) - .withIsType(dataTypeToQName(typeCaseType)) - ) - .withThen(applyTargetMap(source, typeCaseMap)) - ci.then!!.resultType = typeCaseType - c.caseItem.add(ci) - } - } - return when (c.caseItem.size) { - 0 -> { - buildNull(source!!.resultType) } - 1 -> { - c.caseItem[0].then - } - else -> { - c.`else` = (buildNull(source!!.resultType)) - c.resultType = source.resultType - c + return when (c.caseItem.size) { + 0 -> { + buildNull(source!!.resultType) + } + 1 -> { + c.caseItem[0].then + } + else -> { + c.`else` = (buildNull(source!!.resultType)) + c.resultType = source.resultType + c + } } } - } else if (targetMap.contains("(")) { - val invocationStart: Int = targetMap.indexOf("(") - val qualifiedFunctionName: String = targetMap.substring(0, invocationStart) - val nameParts: Array = - qualifiedFunctionName - .split("\\.".toRegex()) - .dropLastWhile { it.isEmpty() } - .toTypedArray() - var libraryName: String? = null - var functionName: String? = qualifiedFunctionName - if (nameParts.size == 2) { - libraryName = nameParts[0] - functionName = nameParts[1] - ensureLibraryIncluded(libraryName, source) - } - val functionArgument: String = - targetMap.substring(invocationStart + 1, targetMap.lastIndexOf(')')) - val argumentSource: Expression? = - if ((functionArgument == "%value")) source - else applyTargetMap(source, functionArgument) - - // NOTE: This is needed to work around the mapping for ToInterval - // FHIRHelpers defines multiple overloads of ToInterval, but the type mapping - // does not have the type of the source data type. - // All the mappings for ToInterval use FHIR.Period, so this is safe to assume - // In addition, no other FHIRHelpers functions use overloads (except ToString and - // ToDateTime, - // but those mappings expand the value element directly, rather than invoking the - // FHIRHelpers function) - var argumentSignature: TypeSpecifier? = null - if (options.signatureLevel != SignatureLevel.None) { - if (qualifiedFunctionName.equals("FHIRHelpers.ToInterval")) { + targetMap.contains("(") -> { + val invocationStart: Int = targetMap.indexOf("(") + val qualifiedFunctionName: String = targetMap.substring(0, invocationStart) + val nameParts: Array = + qualifiedFunctionName + .split("\\.".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray() + var libraryName: String? = null + var functionName: String? = qualifiedFunctionName + if (nameParts.size == 2) { + libraryName = nameParts[0] + functionName = nameParts[1] + ensureLibraryIncluded(libraryName, source) + } + val functionArgument: String = + targetMap.substring(invocationStart + 1, targetMap.lastIndexOf(')')) + val argumentSource: Expression? = + if ((functionArgument == "%value")) source + else applyTargetMap(source, functionArgument) + + // NOTE: This is needed to work around the mapping for ToInterval + // FHIRHelpers defines multiple overloads of ToInterval, but the type mapping + // does not have the type of the source data type. + // All the mappings for ToInterval use FHIR.Period, so this is safe to assume + // In addition, no other FHIRHelpers functions use overloads (except ToString and + // ToDateTime, + // but those mappings expand the value element directly, rather than invoking the + // FHIRHelpers function) + var argumentSignature: TypeSpecifier? = null + if ( + options.signatureLevel != SignatureLevel.None && + qualifiedFunctionName == "FHIRHelpers.ToInterval" + ) { // Force loading of the FHIR model, as it's an implicit - // dependency of the the target mapping here. + // dependency of the target mapping here. var fhirVersion = "4.0.1" val qiCoreModel = this.getModel("QICore") val version = qiCoreModel.modelInfo.version @@ -3065,150 +2971,184 @@ class LibraryBuilder( .withName(dataTypeToQName(resolveTypeName("FHIR", "Period"))) argumentSignature = namedTypeSpecifier } - } - when (argumentSource!!.resultType) { - is ListType -> { - val query: Query = - objectFactory - .createQuery() - .withSource( - objectFactory - .createAliasedQuerySource() - .withExpression(argumentSource) - .withAlias("\$this") - ) - val fr: FunctionRef = - objectFactory - .createFunctionRef() - .withLibraryName(libraryName) - .withName(functionName) - .withOperand(objectFactory.createAliasRef().withName("\$this")) + when (argumentSource!!.resultType) { + is ListType -> { + val query: Query = + objectFactory + .createQuery() + .withSource( + objectFactory + .createAliasedQuerySource() + .withExpression(argumentSource) + .withAlias(FP_THIS) + ) + val fr: FunctionRef = + objectFactory + .createFunctionRef() + .withLibraryName(libraryName) + .withName(functionName) + .withOperand(objectFactory.createAliasRef().withName(FP_THIS)) - if (argumentSignature != null) { - fr.signature.add(argumentSignature) + if (argumentSignature != null) { + fr.signature.add(argumentSignature) + } + + // This doesn't quite work because the US.Core types aren't subtypes of FHIR + // types. + // resolveCall(libraryName, functionName, new FunctionRefInvocation(fr), + // false, + // false); + query.`return` = + (objectFactory + .createReturnClause() + .withDistinct(false) + .withExpression(fr)) + query.resultType = source!!.resultType + return query } + else -> { + val fr: FunctionRef = + objectFactory + .createFunctionRef() + .withLibraryName(libraryName) + .withName(functionName) + .withOperand(argumentSource) + fr.resultType = source!!.resultType - // This doesn't quite work because the US.Core types aren't subtypes of FHIR - // types. - // resolveCall(libraryName, functionName, new FunctionRefInvocation(fr), false, - // false); - query.`return` = - (objectFactory.createReturnClause().withDistinct(false).withExpression(fr)) - query.resultType = source!!.resultType - return query - } - else -> { - val fr: FunctionRef = - objectFactory - .createFunctionRef() - .withLibraryName(libraryName) - .withName(functionName) - .withOperand(argumentSource) - fr.resultType = source!!.resultType + if (argumentSignature != null) { + fr.signature.add(argumentSignature) + } - if (argumentSignature != null) { - fr.signature.add(argumentSignature) + return fr + // This doesn't quite work because the US.Core types aren't subtypes of FHIR + // types, + // or they are defined as System types and not FHIR types + // return resolveCall(libraryName, functionName, new + // FunctionRefInvocation(fr), + // false, false); } - - return fr - // This doesn't quite work because the US.Core types aren't subtypes of FHIR - // types, - // or they are defined as System types and not FHIR types - // return resolveCall(libraryName, functionName, new FunctionRefInvocation(fr), - // false, false); } } - } else if (targetMap.contains("[")) { - val indexerStart: Int = targetMap.indexOf("[") - val indexerEnd: Int = targetMap.indexOf("]") - val indexer: String = targetMap.substring(indexerStart + 1, indexerEnd) - val indexerPath: String = targetMap.substring(0, indexerStart) - var result: Expression? = null - - // Apply sourcePaths to get to the indexer - val indexerPaths: Array = - indexerPath.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - for (path: String in indexerPaths) { - if ((path == "%parent")) { - if (source !is Property) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Cannot expand target map %s for non-property-accessor type %s", - targetMap, - source!!.javaClass.simpleName - ) - ) - } - val sourceProperty: Property = source - result = - if (sourceProperty.source != null) { + targetMap.contains("[") -> { + val indexerStart: Int = targetMap.indexOf("[") + val indexerEnd: Int = targetMap.indexOf("]") + val indexer: String = targetMap.substring(indexerStart + 1, indexerEnd) + val indexerPath: String = targetMap.substring(0, indexerStart) + var result: Expression? = null + + // Apply sourcePaths to get to the indexer + val indexerPaths: Array = + indexerPath.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() + for (path: String in indexerPaths) { + if ((path == "%parent")) { + require(source is Property) { + "Cannot expand target map $targetMap for non-property-accessor type ${source!!.javaClass.simpleName}" + } + val sourceProperty: Property = source + result = sourceProperty.source - } else if (sourceProperty.scope != null) { - resolveIdentifier(sourceProperty.scope!!, true) - } else { - throw IllegalArgumentException( - String.format( - Locale.US, - "Cannot resolve %%parent reference in targetMap %s", - targetMap - ) - ) + ?: sourceProperty.scope?.let { + resolveIdentifier(sourceProperty.scope!!, true) + } + requireNotNull(result) { + "Cannot resolve %%parent reference in targetMap $targetMap" } - } else { - val p: Property = - objectFactory.createProperty().withSource(result).withPath(path) - result = p + } else { + val p: Property = + objectFactory.createProperty().withSource(result).withPath(path) + result = p + } } - } - // Build a query with the current result as source and the indexer content as criteria - // in the where clause - val querySource: AliasedQuerySource = - objectFactory.createAliasedQuerySource().withExpression(result).withAlias("\$this") - var criteria: Expression? = null - for (indexerItem: String in - indexer.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { - val indexerItems: Array = - indexerItem.split("=".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray() - if (indexerItems.size != 2) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid indexer item %s in targetMap %s", - indexerItem, - targetMap - ) - ) - } - var left: Expression? = null - for (path: String in - indexerItems[0] - .split("\\.".toRegex()) - .dropLastWhile { it.isEmpty() } - .toTypedArray()) { - left = - if (left == null) { - objectFactory.createProperty().withScope("\$this").withPath(path) - } else { - objectFactory.createProperty().withSource(left).withPath(path) + // Build a query with the current result as source and the indexer content as + // criteria + // in the where clause + val querySource: AliasedQuerySource = + objectFactory + .createAliasedQuerySource() + .withExpression(result) + .withAlias(FP_THIS) + var criteria: Expression? = null + for (indexerItem: String in + indexer.split(",".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()) { + val indexerItems: Array = + indexerItem + .split("=".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray() + require(indexerItems.size == 2) { + "Invalid indexer item $indexerItem in targetMap $targetMap" + } + var left: Expression? = null + for (path: String in + indexerItems[0] + .split("\\.".toRegex()) + .dropLastWhile { it.isEmpty() } + .toTypedArray()) { + left = + if (left == null) { + objectFactory.createProperty().withScope(FP_THIS).withPath(path) + } else { + objectFactory.createProperty().withSource(left).withPath(path) + } + + // HACK: Workaround the fact that we don't have type information for the + // mapping + // expansions... + if ((path == "coding")) { + left = + objectFactory + .createFirst() + .withSource(left) + .withResultType( + this.getModel("FHIR").resolveTypeName("FHIR.coding") + ) } + if ((path == "url")) { + // HACK: This special cases FHIR model resolution + left.resultType = this.getModel("FHIR").resolveTypeName("FHIR.uri") + val ref: FunctionRef = + objectFactory + .createFunctionRef() + .withLibraryName("FHIRHelpers") + .withName("ToString") + .withOperand(left) + left = + resolveCall( + ref.libraryName, + ref.name!!, + FunctionRefInvocation(ref), + allowPromotionAndDemotion = false, + allowFluent = false + ) + } + } // HACK: Workaround the fact that we don't have type information for the mapping // expansions... - if ((path == "coding")) { - left = + // These hacks will be removed when addressed by the model info + if ((indexerItems[0] == "code.coding.system")) { + // HACK: This special cases FHIR model resolution + left!!.resultType = this.getModel("FHIR").resolveTypeName("FHIR.uri") + val ref: FunctionRef = objectFactory - .createFirst() - .withSource(left) - .withResultType( - this.getModel("FHIR").resolveTypeName("FHIR.coding") - ) as Expression + .createFunctionRef() + .withLibraryName("FHIRHelpers") + .withName("ToString") + .withOperand(left) + left = + resolveCall( + ref.libraryName, + ref.name!!, + FunctionRefInvocation(ref), + allowPromotionAndDemotion = false, + allowFluent = false + ) } - if ((path == "url")) { + if ((indexerItems[0] == "code.coding.code")) { // HACK: This special cases FHIR model resolution - left.resultType = this.getModel("FHIR").resolveTypeName("FHIR.uri") + left!!.resultType = this.getModel("FHIR").resolveTypeName("FHIR.code") val ref: FunctionRef = objectFactory .createFunctionRef() @@ -3220,129 +3160,92 @@ class LibraryBuilder( ref.libraryName, ref.name!!, FunctionRefInvocation(ref), - false, - false + allowPromotionAndDemotion = false, + allowFluent = false ) } + val rightValue: String = + indexerItems[1].substring(1, indexerItems[1].length - 1) + val right: Expression = + this.createLiteral(StringEscapeUtils.unescapeCql(rightValue)) + val criteriaItem: Expression = + objectFactory.createEqual().withOperand(left!!, right) + criteria = + if (criteria == null) { + criteriaItem + } else { + objectFactory.createAnd().withOperand(criteria, criteriaItem) + } } + val query: Query = + objectFactory.createQuery().withSource(querySource).withWhere(criteria) + result = query + if (indexerEnd + 1 < targetMap.length) { + // There are additional paths following the indexer, apply them + var targetPath: String = targetMap.substring(indexerEnd + 1) + if (targetPath.startsWith(".")) { + targetPath = targetPath.substring(1) + } + if (targetPath.isNotEmpty()) { + query.`return` = + (objectFactory + .createReturnClause() + .withDistinct(false) + .withExpression( + objectFactory + .createProperty() + .withSource( + objectFactory.createAliasRef().withName(FP_THIS) + ) + .withPath(targetPath) + )) + } - // HACK: Workaround the fact that we don't have type information for the mapping - // expansions... - // These hacks will be removed when addressed by the model info - if ((indexerItems[0] == "code.coding.system")) { - // HACK: This special cases FHIR model resolution - left!!.resultType = this.getModel("FHIR").resolveTypeName("FHIR.uri") - val ref: FunctionRef = - objectFactory - .createFunctionRef() - .withLibraryName("FHIRHelpers") - .withName("ToString") - .withOperand(left) as FunctionRef - left = - resolveCall( - ref.libraryName, - ref.name!!, - FunctionRefInvocation(ref), - false, - false - ) + // The value reference should go inside the query, rather than being applied as + // a + // property outside of it + // for (String path : targetPath.split("\\.")) { + // result = of.createProperty().withSource(result).withPath(path); + // } } - if ((indexerItems[0] == "code.coding.code")) { - // HACK: This special cases FHIR model resolution - left!!.resultType = this.getModel("FHIR").resolveTypeName("FHIR.code") - val ref: FunctionRef = - objectFactory - .createFunctionRef() - .withLibraryName("FHIRHelpers") - .withName("ToString") - .withOperand(left) - left = - resolveCall( - ref.libraryName, - ref.name!!, - FunctionRefInvocation(ref), - false, - false - ) + if (source!!.resultType !is ListType) { + // Use a singleton from since the source of the query is a list + result = objectFactory.createSingletonFrom().withOperand(result) } - val rightValue: String = indexerItems[1].substring(1, indexerItems[1].length - 1) - val right: Expression = - this.createLiteral(StringEscapeUtils.unescapeCql(rightValue)) - val criteriaItem: Expression = - objectFactory.createEqual().withOperand(left!!, right) - criteria = - if (criteria == null) { - criteriaItem - } else { - objectFactory.createAnd().withOperand(criteria, criteriaItem) - } + result.resultType = source.resultType + return result } - val query: Query = - objectFactory.createQuery().withSource(querySource).withWhere(criteria) - result = query - if (indexerEnd + 1 < targetMap.length) { - // There are additional paths following the indexer, apply them - var targetPath: String = targetMap.substring(indexerEnd + 1) - if (targetPath.startsWith(".")) { - targetPath = targetPath.substring(1) - } - if (targetPath.isNotEmpty()) { - query.`return` = - (objectFactory - .createReturnClause() - .withDistinct(false) - .withExpression( - objectFactory - .createProperty() - .withSource(objectFactory.createAliasRef().withName("\$this")) - .withPath(targetPath) - )) + targetMap.startsWith("%value.") -> { + val propertyName: String = targetMap.substring(@Suppress("MagicNumber") 7) + // If the source is a list, the mapping is expected to apply to every element in the + // list + // ((source $this return all $this.value) + if (source!!.resultType is ListType) { + val s: AliasedQuerySource = + objectFactory + .createAliasedQuerySource() + .withExpression(source) + .withAlias(FP_THIS) + val p: Property = + objectFactory.createProperty().withScope(FP_THIS).withPath(propertyName) + p.resultType = (source.resultType as ListType).elementType + val r: ReturnClause = + objectFactory.createReturnClause().withDistinct(false).withExpression(p) + val q: Query = objectFactory.createQuery().withSource(s).withReturn(r) + q.resultType = source.resultType + return q + } else { + val p: Property = + objectFactory.createProperty().withSource(source).withPath(propertyName) + p.resultType = source.resultType + return p } - - // The value reference should go inside the query, rather than being applied as a - // property outside of it - // for (String path : targetPath.split("\\.")) { - // result = of.createProperty().withSource(result).withPath(path); - // } - } - if (source!!.resultType !is ListType) { - // Use a singleton from since the source of the query is a list - result = objectFactory.createSingletonFrom().withOperand(result) - } - result.resultType = source.resultType - return result - } else if (targetMap.startsWith("%value.")) { - val propertyName: String = targetMap.substring(@Suppress("MagicNumber") 7) - // If the source is a list, the mapping is expected to apply to every element in the - // list - // ((source $this return all $this.value) - if (source!!.resultType is ListType) { - val s: AliasedQuerySource = - objectFactory - .createAliasedQuerySource() - .withExpression(source) - .withAlias("\$this") - val p: Property = - objectFactory.createProperty().withScope("\$this").withPath(propertyName) - p.resultType = (source.resultType as ListType).elementType - val r: ReturnClause = - objectFactory.createReturnClause().withDistinct(false).withExpression(p) - val q: Query = objectFactory.createQuery().withSource(s).withReturn(r) - q.resultType = source.resultType - return q - } else { - val p: Property = - objectFactory.createProperty().withSource(source).withPath(propertyName) - p.resultType = source.resultType - return p } } - throw IllegalArgumentException( - String.format(Locale.US, "TargetMapping not implemented: %s", targetMap) - ) + throw IllegalArgumentException("TargetMapping not implemented: $targetMap") } - @Suppress("LongMethod", "NestedBlockDepth") + @Suppress("LongMethod", "NestedBlockDepth", "CyclomaticComplexMethod") fun resolveAccessor(left: Expression, memberIdentifier: String): Expression? { // if left is a LibraryRef // if right is an identifier @@ -3361,145 +3264,153 @@ class LibraryBuilder( // return a new Identifier with left as a qualifier // else // throws an error as an unresolved identifier - if (left is LibraryRef) { - val libraryName: String? = left.libraryName - val referencedLibrary: CompiledLibrary = resolveLibrary(libraryName) - val resolvedIdentifierContext: ResolvedIdentifierContext = - referencedLibrary.resolve(memberIdentifier) - val element = resolvedIdentifierContext.exactMatchElement - if (element != null) { - if (element is ExpressionDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: Expression = - objectFactory - .createExpressionRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = getExpressionDefResultType(element) - return result - } - if (element is ParameterDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: Expression = - objectFactory - .createParameterRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = element.resultType - return result - } - if (element is ValueSetDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: ValueSetRef = - objectFactory - .createValueSetRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = element.resultType - if (isCompatibleWith("1.5")) { - result.preserve = true + when { + left is LibraryRef -> { + val libraryName: String? = left.libraryName + val referencedLibrary: CompiledLibrary = resolveLibrary(libraryName) + val resolvedIdentifierContext: ResolvedIdentifierContext = + referencedLibrary.resolve(memberIdentifier) + val element = resolvedIdentifierContext.exactMatchElement + if (element != null) { + if (element is ExpressionDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: Expression = + objectFactory + .createExpressionRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = getExpressionDefResultType(element) + return result + } + if (element is ParameterDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: Expression = + objectFactory + .createParameterRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = element.resultType + return result + } + if (element is ValueSetDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: ValueSetRef = + objectFactory + .createValueSetRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = element.resultType + if (isCompatibleWith("1.5")) { + result.preserve = true + } + return result + } + if (element is CodeSystemDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: CodeSystemRef = + objectFactory + .createCodeSystemRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = element.resultType + return result + } + if (element is CodeDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: CodeRef = + objectFactory + .createCodeRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = element.resultType + return result + } + if (element is ConceptDef) { + checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) + val result: ConceptRef = + objectFactory + .createConceptRef() + .withLibraryName(libraryName) + .withName(memberIdentifier) + result.resultType = element.resultType + return result } - return result - } - if (element is CodeSystemDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: CodeSystemRef = - objectFactory - .createCodeSystemRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = element.resultType - return result - } - if (element is CodeDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: CodeRef = - objectFactory - .createCodeRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = element.resultType - return result - } - if (element is ConceptDef) { - checkAccessLevel(libraryName, memberIdentifier, element.accessLevel!!) - val result: ConceptRef = - objectFactory - .createConceptRef() - .withLibraryName(libraryName) - .withName(memberIdentifier) - result.resultType = element.resultType - return result } - } - // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve identifier %s in library %s.", - memberIdentifier, - referencedLibrary.identifier!!.id - ) - ) - } else if (left is AliasRef) { - val resolution: PropertyResolution? = resolveProperty(left.resultType, memberIdentifier) - val result: Expression = - buildProperty(left.name, resolution!!.name, resolution.isSearch, resolution.type) - return applyTargetMap(result, resolution.targetMap) - } else if (left.resultType is ListType && listTraversal) { - // NOTE: FHIRPath path traversal support - // Resolve property access of a list of items as a query: - // listValue.property ::= listValue X where X.property is not null return all X.property - val listType: ListType = left.resultType as ListType - val resolution: PropertyResolution? = - resolveProperty(listType.elementType, memberIdentifier) - var accessor: Expression? = - buildProperty( - objectFactory.createAliasRef().withName("\$this"), - resolution!!.name, - resolution.isSearch, - resolution.type - ) - accessor = applyTargetMap(accessor, resolution.targetMap) - val not: Expression = buildIsNotNull(accessor) - - // Recreate property, it needs to be accessed twice - accessor = - buildProperty( - objectFactory.createAliasRef().withName("\$this"), - resolution.name, - resolution.isSearch, - resolution.type + // ERROR: + throw IllegalArgumentException( + "Could not resolve identifier $memberIdentifier in library ${referencedLibrary.identifier!!.id}." ) - accessor = applyTargetMap(accessor, resolution.targetMap) - val source: AliasedQuerySource = - objectFactory.createAliasedQuerySource().withExpression(left).withAlias("\$this") - source.resultType = left.resultType - val query: Query = - objectFactory - .createQuery() - .withSource(source) - .withWhere(not) - .withReturn( - objectFactory - .createReturnClause() - .withDistinct(false) - .withExpression(accessor) + } + left is AliasRef -> { + val resolution: PropertyResolution? = + resolveProperty(left.resultType, memberIdentifier) + val result: Expression = + buildProperty( + left.name, + resolution!!.name, + resolution.isSearch, + resolution.type + ) + return applyTargetMap(result, resolution.targetMap) + } + left.resultType is ListType && listTraversal -> { + // NOTE: FHIRPath path traversal support + // Resolve property access of a list of items as a query: + // listValue.property ::= listValue X where X.property is not null return all + // X.property + val listType: ListType = left.resultType as ListType + val resolution: PropertyResolution? = + resolveProperty(listType.elementType, memberIdentifier) + var accessor: Expression? = + buildProperty( + objectFactory.createAliasRef().withName(FP_THIS), + resolution!!.name, + resolution.isSearch, + resolution.type + ) + accessor = applyTargetMap(accessor, resolution.targetMap) + val not: Expression = buildIsNotNull(accessor) + + // Recreate property, it needs to be accessed twice + accessor = + buildProperty( + objectFactory.createAliasRef().withName(FP_THIS), + resolution.name, + resolution.isSearch, + resolution.type ) - query.resultType = ListType(accessor!!.resultType!!) - if (accessor.resultType is ListType) { - val result: Flatten = objectFactory.createFlatten().withOperand(query) - result.resultType = accessor.resultType + accessor = applyTargetMap(accessor, resolution.targetMap) + val source: AliasedQuerySource = + objectFactory.createAliasedQuerySource().withExpression(left).withAlias(FP_THIS) + source.resultType = left.resultType + val query: Query = + objectFactory + .createQuery() + .withSource(source) + .withWhere(not) + .withReturn( + objectFactory + .createReturnClause() + .withDistinct(false) + .withExpression(accessor) + ) + query.resultType = ListType(accessor!!.resultType!!) + if (accessor.resultType is ListType) { + val result: Flatten = objectFactory.createFlatten().withOperand(query) + result.resultType = accessor.resultType + return result + } + return query + } + else -> { + val resolution: PropertyResolution? = + resolveProperty(left.resultType, memberIdentifier) + var result: Expression? = + buildProperty(left, resolution!!.name, resolution.isSearch, resolution.type) + result = applyTargetMap(result, resolution.targetMap) return result } - return query - } else { - val resolution: PropertyResolution? = resolveProperty(left.resultType, memberIdentifier) - var result: Expression? = - buildProperty(left, resolution!!.name, resolution.isSearch, resolution.type) - result = applyTargetMap(result, resolution.targetMap) - return result } } @@ -3507,7 +3418,7 @@ class LibraryBuilder( if (inQueryContext()) { val query = peekQueryContext() if (query.inSortClause() && !query.isSingular) { - if (identifier == "\$this") { + if (identifier == FP_THIS) { val result = objectFactory.createIdentifierRef().withName(identifier) result.resultType = query.resultElementType return result @@ -3541,9 +3452,9 @@ class LibraryBuilder( if (inQueryContext()) { val query = peekQueryContext() if (query.isImplicit) { - val source = resolveAlias("\$this") + val source = resolveAlias(FP_THIS) if (source != null) { - val aliasRef = objectFactory.createAliasRef().withName("\$this") + val aliasRef = objectFactory.createAliasRef().withName(FP_THIS) if (source.resultType is ListType) { aliasRef.resultType = (source.resultType as ListType).elementType } else { @@ -3579,7 +3490,7 @@ class LibraryBuilder( return objectFactory .createOperandRef() .withName(identifier) - .withResultType(operand.resultType) as OperandRef + .withResultType(operand.resultType) } } } @@ -3620,12 +3531,7 @@ class LibraryBuilder( } } throw IllegalArgumentException( - String.format( - Locale.US, - "Invalid context reference from %s context to %s context.", - currentExpressionContext(), - expressionDef.context - ) + "Invalid context reference from ${currentExpressionContext()} context to ${expressionDef.context} context." ) } @@ -3633,26 +3539,7 @@ class LibraryBuilder( GLOBAL, LOCAL } - /** - * Add an identifier to the deque to indicate that we are considering it for consideration for - * identifier hiding and adding a compiler warning if this is the case. - * - * For example, if an alias within an expression body has the same name as a parameter, - * execution would have added the parameter identifier and the next execution would consider an - * alias with the same name, thus resulting in a warning. - * - * Exact case matching as well as case-insensitive matching are considered. If known, the type - * of the structure in question will be considered in crafting the warning message, as per the - * [Element] parameter. - * - * Also, special case function overloads so that only a single overloaded function name is taken - * into account. - * - * @param identifier The identifier belonging to the parameter, expression, function, alias, - * etc, to be evaluated. - * @param trackable The construct trackable, for example [ExpressionRef]. - * @param scope the scope of the current identifier - */ + /** * Add an identifier to the deque to indicate that we are considering it for consideration for * identifier hiding and adding a compiler warning if this is the case. @@ -3671,7 +3558,7 @@ class LibraryBuilder( * Default scope is [IdentifierScope.LOCAL] * * @param identifier The identifier belonging to the parameter, expression, function, alias, - * etc, to be evaluated. + * etc., to be evaluated. * @param element The construct trackable, for example [ExpressionRef]. */ @JvmOverloads @@ -3681,7 +3568,7 @@ class LibraryBuilder( scope: IdentifierScope = IdentifierScope.LOCAL ) { val localMatch = - if (!localIdentifierStack.isEmpty()) + if (localIdentifierStack.isNotEmpty()) findMatchingIdentifierContext(localIdentifierStack.peek(), identifier) else Optional.empty() val globalMatch = findMatchingIdentifierContext(globalIdentifiers, identifier) @@ -3740,8 +3627,6 @@ class LibraryBuilder( localIdentifierStack.pop() } - // TODO: consider other structures that should only trigger a readonly check of identifier - // hiding private fun shouldAddIdentifierContext(element: Element?): Boolean { return element !is Literal } @@ -3753,19 +3638,9 @@ class LibraryBuilder( ): String { val elementString = lookupElementWarning(element) return if (element is Literal) { - String.format( - Locale.US, - "You used a string literal: [%s] here that matches an identifier in scope: [%s]. Did you mean to use the identifier instead?", - identifierParam, - matchedIdentifier - ) + "You used a string literal: [$identifierParam] here that matches an identifier in scope: [$matchedIdentifier]. Did you mean to use the identifier instead?" } else - String.format( - Locale.US, - "%s identifier [%s] is hiding another identifier of the same name.", - elementString, - identifierParam - ) + "$elementString identifier [$identifierParam] is hiding another identifier of the same name." } private inner class Scope { @@ -3790,7 +3665,7 @@ class LibraryBuilder( } fun determineRootCause(): Exception? { - if (!expressionDefinitions.isEmpty()) { + if (expressionDefinitions.isNotEmpty()) { val currentContext = expressionDefinitions.peek() if (currentContext != null) { return currentContext.rootCause @@ -3800,22 +3675,16 @@ class LibraryBuilder( } fun setRootCause(rootCause: Exception?) { - if (!expressionDefinitions.isEmpty()) { + if (expressionDefinitions.isNotEmpty()) { val currentContext = expressionDefinitions.peek() currentContext?.rootCause = rootCause } } fun pushExpressionDefinition(identifier: String) { - if (expressionDefinitions.contains(identifier)) { + require(!expressionDefinitions.contains(identifier)) { // ERROR: - throw IllegalArgumentException( - String.format( - Locale.US, - "Cannot resolve reference to expression or function %s because it results in a circular reference.", - identifier - ) - ) + "Cannot resolve reference to expression or function $identifier because it results in a circular reference." } expressionDefinitions.push(ExpressionDefinitionContext(identifier)) } @@ -3841,22 +3710,22 @@ class LibraryBuilder( expressionContext.pop() } - fun currentExpressionContext(): String { + private fun currentExpressionContext(): String { check(!expressionContext.empty()) { "Expression context stack is empty." } return expressionContext.peek() } - fun inSpecificContext(): Boolean { + private fun inSpecificContext(): Boolean { return !inUnfilteredContext() } - fun inUnfilteredContext(): Boolean { + private fun inUnfilteredContext(): Boolean { return currentExpressionContext() == "Unfiltered" || isCompatibilityLevel3 && currentExpressionContext() == "Population" } - fun inQueryContext(): Boolean { - return hasScope() && scope.queries.size > 0 + private fun inQueryContext(): Boolean { + return hasScope() && scope.queries.isNotEmpty() } fun pushQueryContext(context: QueryContext) { @@ -3880,7 +3749,7 @@ class LibraryBuilder( } fun hasExpressionTarget(): Boolean { - return hasScope() && !scope.targets.isEmpty() + return hasScope() && scope.targets.isNotEmpty() } fun beginFunctionDef(functionDef: FunctionDef) { @@ -3900,7 +3769,7 @@ class LibraryBuilder( literalContext-- } - fun inLiteralContext(): Boolean { + private fun inLiteralContext(): Boolean { return literalContext > 0 } @@ -3919,52 +3788,27 @@ class LibraryBuilder( typeSpecifierContext-- } - fun inTypeSpecifierContext(): Boolean { + private fun inTypeSpecifierContext(): Boolean { return typeSpecifierContext > 0 } companion object { private fun lookupElementWarning(element: Any?): String { - // TODO: this list is not exhaustive and may need to be updated - when (element) { - is ExpressionDef -> { - return "An expression" - } - is ParameterDef -> { - return "A parameter" - } - is ValueSetDef -> { - return "A valueset" - } - is CodeSystemDef -> { - return "A codesystem" - } - is CodeDef -> { - return "A code" - } - is ConceptDef -> { - return "A concept" - } - is IncludeDef -> { - return "An include" - } - is AliasedQuerySource -> { - return "An alias" - } - is LetClause -> { - return "A let" - } - is OperandDef -> { - return "An operand" - } - is UsingDef -> { - return "A using" - } - is Literal -> { - return "A literal" - } + return when (element) { + is ExpressionDef -> "An expression" + is ParameterDef -> "A parameter" + is ValueSetDef -> "A valueset" + is CodeSystemDef -> "A codesystem" + is CodeDef -> "A code" + is ConceptDef -> "A concept" + is IncludeDef -> "An include" + is AliasedQuerySource -> "An alias" + is LetClause -> "A let" + is OperandDef -> "An operand" + is UsingDef -> "A using" + is Literal -> "A literal" // default message if no match is made: - else -> return "An [unknown structure]" + else -> "An [unknown structure]" } } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryManager.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryManager.kt index 90153e9f4..9a08003d8 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryManager.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryManager.kt @@ -3,7 +3,6 @@ package org.cqframework.cql.cql2elm import java.io.* -import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap import kotlin.collections.HashSet @@ -44,9 +43,6 @@ constructor( * namespace in a namespace-aware context */ fun isWellKnownLibraryName(unqualifiedIdentifier: String?): Boolean { - if (unqualifiedIdentifier == null) { - return false - } return when (unqualifiedIdentifier) { "FHIRHelpers" -> true else -> false @@ -54,24 +50,24 @@ constructor( } fun resolveLibrary( - libraryIdentifier: VersionedIdentifier?, + libraryIdentifier: VersionedIdentifier, cacheMode: CacheMode ): CompiledLibrary { return this.resolveLibrary(libraryIdentifier, ArrayList(), cacheMode) } - fun canResolveLibrary(libraryIdentifier: VersionedIdentifier?): Boolean { - val lib = this.resolveLibrary(libraryIdentifier) - return lib != null + fun canResolveLibrary(libraryIdentifier: VersionedIdentifier): Boolean { + // This throws an exception if the library cannot be resolved + this.resolveLibrary(libraryIdentifier) + return true } @JvmOverloads fun resolveLibrary( - libraryIdentifier: VersionedIdentifier?, + libraryIdentifier: VersionedIdentifier, errors: MutableList = ArrayList(), cacheMode: CacheMode = CacheMode.READ_WRITE ): CompiledLibrary { - require(libraryIdentifier != null) { "libraryIdentifier is null." } require(!libraryIdentifier.id.isNullOrEmpty()) { "libraryIdentifier Id is null." } var library: CompiledLibrary? if (cacheMode != CacheMode.NONE) { @@ -106,12 +102,8 @@ constructor( val cqlSource: InputStream = librarySourceLoader.getLibrarySource(libraryIdentifier) ?: throw CqlIncludeException( - String.format( - Locale.US, - "Could not load source for library %s, version %s.", - libraryIdentifier.id, - libraryIdentifier.version - ), + """Could not load source for library ${libraryIdentifier.id}, + version ${libraryIdentifier.version}.""", libraryIdentifier.system, libraryIdentifier.id!!, libraryIdentifier.version @@ -130,13 +122,8 @@ constructor( libraryIdentifier.version != result!!.identifier!!.version) ) { throw CqlIncludeException( - String.format( - Locale.US, - "Library %s was included as version %s, but version %s of the library was found.", - libraryPath, - libraryIdentifier.version, - result.identifier!!.version - ), + """Library $libraryPath was included as version ${libraryIdentifier.version}, + but version ${result.identifier!!.version} of the library was found.""", libraryIdentifier.system, libraryIdentifier.id!!, libraryIdentifier.version @@ -144,12 +131,7 @@ constructor( } } catch (e: IOException) { throw CqlIncludeException( - String.format( - Locale.US, - "Errors occurred translating library %s, version %s.", - libraryPath, - libraryIdentifier.version - ), + "Errors occurred translating library $libraryPath, version ${libraryIdentifier.version}.", libraryIdentifier.system!!, libraryIdentifier.id!!, libraryIdentifier.version, @@ -158,15 +140,10 @@ constructor( } if (result == null) { throw CqlIncludeException( - String.format( - Locale.US, - "Could not load source for library %s, version %s.", - libraryPath, - libraryIdentifier.version - ), + "Could not load source for library $libraryPath.", libraryIdentifier.system, libraryIdentifier.id!!, - libraryIdentifier.version + null ) } else { sortStatements(result) @@ -328,8 +305,8 @@ constructor( } @Suppress("NestedBlockDepth") - fun hasSignature(library: Library?): Boolean { - if (library?.statements != null) { + private fun hasSignature(library: Library): Boolean { + if (library.statements != null) { // Just a quick top-level scan for signatures. To fully verify we'd have to // recurse all // the way down. At that point, let's just translate. diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryReaderUtil.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryReaderUtil.kt deleted file mode 100644 index 46ebd90be..000000000 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibraryReaderUtil.kt +++ /dev/null @@ -1,53 +0,0 @@ -@file:Suppress("WildcardImport") - -package org.cqframework.cql.cql2elm - -import java.io.* -import java.net.URI -import java.net.URISyntaxException -import java.net.URL -import java.util.* -import javax.xml.transform.Source -import javax.xml.transform.stream.StreamSource - -object LibraryReaderUtil { - /** Creates [Source] from various JSON representation. */ - @Suppress("ReturnCount") - @Throws(IOException::class) - fun toSource(json: Any?): Source { - var json: Any? = json ?: throw CqlCompilerException("no JSON is given") - if (json is String) { - json = - try { - URI(json) - } catch (@Suppress("SwallowedException") e: URISyntaxException) { - File(json) - } - } - if (json is File) { - return StreamSource(json as File?) - } - if (json is URI) { - json = json.toURL() - } - if (json is URL) { - return StreamSource(json.toExternalForm()) - } - if (json is InputStream) { - return StreamSource(json as InputStream?) - } - if (json is Reader) { - return StreamSource(json as Reader?) - } - if (json is Source) { - return json - } - throw CqlCompilerException( - String.format( - Locale.US, - "Could not determine access path for input of type %s.", - json!!.javaClass - ) - ) - } -} diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibrarySourceLoader.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibrarySourceLoader.kt index 213b2a92a..19abe867e 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibrarySourceLoader.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/LibrarySourceLoader.kt @@ -20,14 +20,4 @@ interface LibrarySourceLoader { } return null } - - fun isLibraryContentAvailable( - libraryIdentifier: VersionedIdentifier, - type: LibraryContentType - ): Boolean { - if (LibraryContentType.CQL == type) { - return getLibrarySource(libraryIdentifier) != null - } - return false - } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelInfoLoader.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelInfoLoader.kt index 63f37a096..0488ee54e 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelInfoLoader.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelInfoLoader.kt @@ -1,7 +1,6 @@ package org.cqframework.cql.cql2elm import java.nio.file.Path -import java.util.* import kotlin.collections.ArrayList import org.hl7.cql.model.ModelIdentifier import org.hl7.cql.model.ModelInfoProvider @@ -36,13 +35,10 @@ class ModelInfoLoader : NamespaceAware, PathAware { } } requireNotNull(modelInfo) { - String.format( - Locale.US, - "Could not resolve model info provider for model %s, version %s.", + "Could not resolve model info provider for model ${ if (modelIdentifier.system == null) modelIdentifier.id - else NamespaceManager.getPath(modelIdentifier.system, modelIdentifier.id), - modelIdentifier.version - ) + else NamespaceManager.getPath(modelIdentifier.system, modelIdentifier.id) + }, version ${modelIdentifier.version}." } return modelInfo } @@ -82,9 +78,7 @@ class ModelInfoLoader : NamespaceAware, PathAware { } override fun setPath(path: Path) { - require(path.toFile().isDirectory) { - String.format(Locale.US, "path '%s' is not a valid directory", path) - } + require(path.toFile().isDirectory) { "path '$path' is not a valid directory" } this.path = path for (provider in getProviders()) { if (provider is PathAware) { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelManager.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelManager.kt index 710c346a2..608baaa16 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelManager.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/ModelManager.kt @@ -16,12 +16,18 @@ class ModelManager { var modelInfoLoader: ModelInfoLoader? = null private set - private val models: MutableMap = HashMap() + private val models: MutableMap = HashMap() private val loadingModels: MutableSet = HashSet() - private val modelsByUri: MutableMap = HashMap() - private val globalCache: MutableMap - var isDefaultModelInfoLoadingEnabled = true - private set + private val modelsByUri: MutableMap = HashMap() + + /** + * The global cache is by @{org.hl7.cql.model.ModelIdentifier}, while the local cache is by + * name. This is because the translator expects the ModelManager to only permit loading of a + * single version of a given Model in a single translation context, while the global cache is + * for all versions of Models + */ + private val globalCache: MutableMap + private var isDefaultModelInfoLoadingEnabled = true constructor() { namespaceManager = NamespaceManager() @@ -30,7 +36,7 @@ class ModelManager { } /** @param globalCache cache for Models by ModelIdentifier. Expected to be thread-safe. */ - constructor(globalCache: MutableMap) { + constructor(globalCache: MutableMap) { namespaceManager = NamespaceManager() this.globalCache = globalCache initialize() @@ -43,7 +49,7 @@ class ModelManager { initialize() } - constructor(path: Path?, globalCache: MutableMap) { + constructor(path: Path?, globalCache: MutableMap) { namespaceManager = NamespaceManager() this.globalCache = globalCache this.path = path @@ -59,7 +65,7 @@ class ModelManager { constructor( enableDefaultModelInfoLoading: Boolean, - globalCache: MutableMap + globalCache: MutableMap ) { namespaceManager = NamespaceManager() this.globalCache = globalCache @@ -78,7 +84,7 @@ class ModelManager { constructor( enableDefaultModelInfoLoading: Boolean, path: Path?, - globalCache: MutableMap + globalCache: MutableMap ) { namespaceManager = NamespaceManager() this.globalCache = globalCache @@ -95,7 +101,7 @@ class ModelManager { constructor( namespaceManager: NamespaceManager, - globalCache: MutableMap + globalCache: MutableMap ) { this.namespaceManager = namespaceManager this.globalCache = globalCache @@ -112,7 +118,7 @@ class ModelManager { constructor( namespaceManager: NamespaceManager, path: Path?, - globalCache: MutableMap + globalCache: MutableMap ) { this.namespaceManager = namespaceManager this.globalCache = globalCache @@ -130,7 +136,7 @@ class ModelManager { constructor( namespaceManager: NamespaceManager, enableDefaultModelInfoLoading: Boolean, - globalCache: MutableMap + globalCache: MutableMap ) { this.namespaceManager = namespaceManager this.globalCache = globalCache @@ -154,7 +160,7 @@ class ModelManager { namespaceManager: NamespaceManager, enableDefaultModelInfoLoading: Boolean, path: Path?, - globalCache: MutableMap + globalCache: MutableMap ) { this.namespaceManager = namespaceManager this.globalCache = globalCache @@ -171,16 +177,6 @@ class ModelManager { } } - /** - * The global cache is by @{org.hl7.cql.model.ModelIdentifier}, while the local cache is by - * name. This is because the translator expects the ModelManager to only permit loading of a - * single version of a given Model in a single translation context, while the global cache is - * for all versions of Models - */ - fun getGlobalCache(): Map { - return globalCache - } - /* A "well-known" model name is one that is allowed to resolve without a namespace in a namespace-aware context */ @@ -218,9 +214,7 @@ class ModelManager { } private fun pushLoading(modelId: String) { - require(!loadingModels.contains(modelId)) { - String.format(Locale.US, "Circular model reference %s", modelId) - } + require(!loadingModels.contains(modelId)) { "Circular model reference $modelId" } loadingModels.add(modelId) } @@ -245,16 +239,16 @@ class ModelManager { model?.let { checkModelVersion(modelIdentifier, it) } if (model == null && globalCache.containsKey(modelIdentifier)) { model = globalCache[modelIdentifier] - models[modelPath] = model - modelsByUri[model!!.modelInfo.url!!] = model + models[modelPath] = model!! + modelsByUri[model.modelInfo.url!!] = model } if (model == null) { model = buildModel(modelIdentifier) - globalCache[modelIdentifier] = model + globalCache[modelIdentifier] = model!! checkModelVersion(modelIdentifier, model) models[modelPath] = model - modelsByUri[model!!.modelInfo.url!!] = model + modelsByUri[model.modelInfo.url!!] = model } return model } @@ -264,20 +258,15 @@ class ModelManager { !(modelIdentifier.version != null && modelIdentifier.version != model!!.modelInfo.version) ) { - String.format( - Locale.US, - "Could not load model information for model %s, version %s because version %s is already loaded.", - modelIdentifier.id, - modelIdentifier.version, - model!!.modelInfo.version - ) + "Could not load model information for model ${modelIdentifier.id}, version ${modelIdentifier.version}" + + " because version ${model!!.modelInfo.version} is already loaded." } } fun resolveModelByUri(namespaceUri: String): Model { return modelsByUri[namespaceUri] ?: throw IllegalArgumentException( - String.format(Locale.US, "Could not resolve model with namespace %s", namespaceUri) + "Could not resolve model with namespace $namespaceUri" ) } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/PriorityLibrarySourceLoader.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/PriorityLibrarySourceLoader.kt index 38ae54e6f..b233536f4 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/PriorityLibrarySourceLoader.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/PriorityLibrarySourceLoader.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm import java.io.InputStream import java.nio.file.Path -import java.util.* import kotlin.collections.ArrayList import org.hl7.cql.model.NamespaceAware import org.hl7.cql.model.NamespaceManager @@ -31,9 +30,7 @@ class PriorityLibrarySourceLoader : LibrarySourceLoader, NamespaceAware, PathAwa private var path: Path? = null override fun setPath(path: Path) { - require(path.toFile().isDirectory) { - String.format(Locale.US, "path '%s' is not a valid directory", path) - } + require(path.toFile().isDirectory) { "path '$path' is not a valid directory" } this.path = path for (provider in getProviders()) { if (provider is PathAware) { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringEscapeUtils.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringEscapeUtils.kt index 116a60495..94759fd0b 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringEscapeUtils.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringEscapeUtils.kt @@ -50,7 +50,8 @@ object StringEscapeUtils { // '\u0020'..'\u007E' are printable ASCII characters ESCAPE_MAP[char] ?: if (char !in '\u0020'..'\u007E') { - "\\u%04x".format(char.code) + @Suppress("MagicNumber") + "\\u${char.code.toString(HEX_RADIX).padStart(4, '0')}" } else { char } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringLibrarySourceProvider.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringLibrarySourceProvider.kt index 87a88f259..b59850529 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringLibrarySourceProvider.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/StringLibrarySourceProvider.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm import java.io.ByteArrayInputStream import java.io.InputStream -import java.util.* import kotlin.collections.ArrayList import org.hl7.elm.r1.VersionedIdentifier @@ -28,14 +27,10 @@ class StringLibrarySourceProvider(private val libraries: List) : Library matches.add(library) } } - if (matches.size > 1) { - throw IllegalArgumentException( - String.format( - Locale.US, - "Multiple libraries for id : %s resolved.%nEnsure that there are no duplicates in the input set.", - libraryIdentifier.toString() - ) - ) + require(matches.size <= 1) { + """"Multiple libraries for id : $libraryIdentifier resolved. + Ensure that there are no duplicates in the input set.""" + .trimMargin() } return if (matches.size == 1) ByteArrayInputStream(matches[0].toByteArray()) else null } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemFunctionResolver.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemFunctionResolver.kt index a3b2ef408..294894ebe 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemFunctionResolver.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemFunctionResolver.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm -import java.util.* import kotlin.collections.ArrayList import org.cqframework.cql.cql2elm.model.Invocation import org.cqframework.cql.cql2elm.model.invocation.* @@ -11,11 +10,10 @@ import org.cqframework.cql.cql2elm.model.invocation.DateTimeInvocation.Companion import org.cqframework.cql.cql2elm.model.invocation.TimeInvocation.Companion.setTimeFieldsFromOperands import org.cqframework.cql.cql2elm.tracking.Trackable.resultType import org.cqframework.cql.cql2elm.tracking.Trackable.trackbacks -import org.cqframework.cql.elm.IdObjectFactory import org.hl7.elm.r1.* @Suppress("LargeClass", "TooManyFunctions") -class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFactory?) { +class SystemFunctionResolver(private val builder: LibraryBuilder) { private val of = builder.objectFactory @Suppress("LongMethod", "CyclomaticComplexMethod", "NestedBlockDepth", "ReturnCount") @@ -111,27 +109,25 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa builder.findConversion( op.resultType!!, builder.resolveTypeName("System", "Date")!!, - true, - false + implicit = true, + allowPromotionAndDemotion = false ) val dateTimeConversion = builder.findConversion( op.resultType!!, builder.resolveTypeName("System", "DateTime")!!, - true, - false + implicit = true, + allowPromotionAndDemotion = false ) op = when { dateConversion != null && dateTimeConversion != null -> { require(dateConversion.score != dateTimeConversion.score) { - "Ambiguous implicit conversion from %s to %s or %s." - .format( - Locale.US, - op.resultType.toString(), - dateConversion.toType.toString(), - dateTimeConversion.toType.toString() - ) + """Ambiguous implicit conversion from + |${op.resultType} to ${dateConversion.toType} + |or ${dateTimeConversion}.""" + .trimMargin() + .replace("\n", "") } if (dateConversion.score < dateTimeConversion.score) { @@ -147,17 +143,14 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa else -> { // ERROR throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve call to operator %s with argument of type %s.", - functionRef.name, - op.resultType.toString() - ) + """Could not resolve call to operator ${functionRef.name} + with argument of type ${op.resultType.toString()}.""" + .trimIndent() ) } } } - ops.add(builder.enforceCompatible(patientBirthDateProperty, op.resultType)!!) + ops.add(builder.enforceCompatible(patientBirthDateProperty, op.resultType)) ops.add(op) return resolveCalculateAgeAt( ops, @@ -649,11 +642,7 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa "ToConcept" -> convert.toType = builder.dataTypeToQName(sm.concept) else -> throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve call to system operator %s. Unknown conversion type.", - functionRef.name - ) + "Could not resolve call to system operator ${functionRef.name}. Unknown conversion type." ) } val invocation = ConvertInvocation(convert) @@ -667,11 +656,7 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa T::class.java.cast(of.javaClass.getMethod("create" + functionRef.name).invoke(of)) } catch (@Suppress("TooGenericExceptionCaught") e: Exception) { throw CqlInternalException( - String.format( - Locale.US, - "Could not create instance of Element \"%s\"", - functionRef.name - ), + "Could not create instance of Element \"${functionRef.name}\"", if (functionRef.trackbacks.isNotEmpty()) functionRef.trackbacks[0] else null, e ) @@ -724,12 +709,7 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa private fun checkNumberOfOperands(functionRef: FunctionRef, expectedOperands: Int) { require(functionRef.operand.size == expectedOperands) { - String.format( - Locale.US, - "Could not resolve call to system operator %s. Expected %d arguments.", - functionRef.name, - expectedOperands - ) + "Could not resolve call to system operator ${functionRef.name}. Expected $expectedOperands arguments." } } @@ -747,10 +727,7 @@ class SystemFunctionResolver(private val builder: LibraryBuilder, of: IdObjectFa name.contains("Minutes") -> DateTimePrecision.MINUTE name.contains("Second") -> DateTimePrecision.SECOND name.contains("Milliseconds") -> DateTimePrecision.MILLISECOND - else -> - throw IllegalArgumentException( - String.format(Locale.US, "Unknown precision '%s'.", name) - ) + else -> throw IllegalArgumentException("Unknown precision '$name'.") } } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemMethodResolver.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemMethodResolver.kt index 3c5faa1ad..54a179c2e 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemMethodResolver.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/SystemMethodResolver.kt @@ -41,12 +41,7 @@ class SystemMethodResolver( actualCount = ctx.expression().size } require(actualCount == expectedCount) { - String.format( - Locale.US, - "Expected %s argument for method %s.", - Integer.valueOf(expectedCount).toString(), - functionName - ) + "Expected ${Integer.valueOf(expectedCount)} argument for method $functionName." } } @@ -233,34 +228,39 @@ class SystemMethodResolver( recurse: Boolean, dataTypes: MutableSet ) { - if (dataType is ClassType) { - for (element in dataType.elements) { - val elementType = - if (element.type is ListType) (element.type as ListType).elementType - else element.type - dataTypes.add(elementType) - if (recurse) { - gatherChildTypes(elementType, recurse, dataTypes) + when (dataType) { + is ClassType -> { + for (element in dataType.elements) { + val elementType = + if (element.type is ListType) (element.type as ListType).elementType + else element.type + dataTypes.add(elementType) + if (recurse) { + gatherChildTypes(elementType, true, dataTypes) + } } } - } else if (dataType is TupleType) { - for (element in dataType.elements) { - val elementType = - if (element.type is ListType) (element.type as ListType).elementType - else element.type + is TupleType -> { + for (element: TupleTypeElement in dataType.elements) { + val elementType = + if (element.type is ListType) (element.type as ListType).elementType + else element.type + dataTypes.add(elementType) + if (recurse) { + gatherChildTypes(elementType, true, dataTypes) + } + } + } + is ListType -> { + val elementType = dataType.elementType dataTypes.add(elementType) if (recurse) { - gatherChildTypes(elementType, recurse, dataTypes) + gatherChildTypes(elementType, true, dataTypes) } } - } else if (dataType is ListType) { - val elementType = dataType.elementType - dataTypes.add(elementType) - if (recurse) { - gatherChildTypes(elementType, recurse, dataTypes) + else -> { + dataTypes.add(builder.resolveTypeName("System.Any")!!) } - } else { - dataTypes.add(builder.resolveTypeName("System.Any")!!) } } @@ -319,8 +319,8 @@ class SystemMethodResolver( builder.ensureCompatibleTypes(target.resultType, argument.resultType!!)!! val list = of.createList() list.resultType = ListType(elementType) - list.element.add(builder.ensureCompatible(target, elementType)!!) - list.element.add(builder.ensureCompatible(argument, elementType)!!) + list.element.add(builder.ensureCompatible(target, elementType)) + list.element.add(builder.ensureCompatible(argument, elementType)) val params = ArrayList() params.add(list) builder.resolveFunction(null, "Flatten", params) @@ -525,8 +525,8 @@ class SystemMethodResolver( functionName, getParams(target, ctx), mustResolve, - false, - true + allowPromotionAndDemotion = false, + allowFluent = true ) } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/TypeBuilder.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/TypeBuilder.kt index 4c17ebeac..3e97726b9 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/TypeBuilder.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/TypeBuilder.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm -import java.util.* import javax.xml.namespace.QName import kotlin.collections.ArrayList import org.cqframework.cql.cql2elm.model.Model @@ -55,7 +54,7 @@ class TypeBuilder(private val of: IdObjectFactory, private val mr: ModelResolver is NamedType -> { return of.createNamedTypeSpecifier() .withName(dataTypeToQName(type)) - .withResultType(type) as TypeSpecifier + .withResultType(type) } is ListType -> { return listTypeToTypeSpecifier(type) @@ -73,9 +72,7 @@ class TypeBuilder(private val of: IdObjectFactory, private val mr: ModelResolver return typeParameterToTypeSpecifier(type) } else -> { - throw IllegalArgumentException( - String.format(Locale.US, "Could not convert type %s to a type specifier.", type) - ) + throw IllegalArgumentException("Could not convert type $type to a type specifier.") } } } @@ -83,25 +80,24 @@ class TypeBuilder(private val of: IdObjectFactory, private val mr: ModelResolver private fun listTypeToTypeSpecifier(type: ListType): TypeSpecifier { return of.createListTypeSpecifier() .withElementType(dataTypeToTypeSpecifier(type.elementType)) - .withResultType(type) as TypeSpecifier + .withResultType(type) } private fun intervalTypeToTypeSpecifier(type: IntervalType): TypeSpecifier { return of.createIntervalTypeSpecifier() .withPointType(dataTypeToTypeSpecifier(type.pointType)) - .withResultType(type) as TypeSpecifier + .withResultType(type) } private fun tupleTypeToTypeSpecifier(type: TupleType): TypeSpecifier { - @Suppress("SpreadOperator") return of.createTupleTypeSpecifier() - .withElement(*tupleTypeElementsToTupleElementDefinitions(type.elements)) - .withResultType(type) as TypeSpecifier + .withElement(tupleTypeElementsToTupleElementDefinitions(type.elements)) + .withResultType(type) } private fun tupleTypeElementsToTupleElementDefinitions( elements: Iterable - ): Array { + ): List { val definitions: MutableList = ArrayList() for (element: TupleTypeElement in elements) { definitions.add( @@ -110,22 +106,21 @@ class TypeBuilder(private val of: IdObjectFactory, private val mr: ModelResolver .withElementType(dataTypeToTypeSpecifier(element.type)) ) } - return definitions.toTypedArray() + return definitions } private fun choiceTypeToTypeSpecifier(type: ChoiceType): TypeSpecifier { - @Suppress("SpreadOperator") return of.createChoiceTypeSpecifier() - .withChoice(*choiceTypeTypesToTypeSpecifiers(type)) - .withResultType(type) as TypeSpecifier + .withChoice(choiceTypeTypesToTypeSpecifiers(type)) + .withResultType(type) } - private fun choiceTypeTypesToTypeSpecifiers(choiceType: ChoiceType): Array { + private fun choiceTypeTypesToTypeSpecifiers(choiceType: ChoiceType): List { val specifiers: MutableList = ArrayList() for (type: DataType in choiceType.types) { specifiers.add(dataTypeToTypeSpecifier(type)) } - return specifiers.toTypedArray() + return specifiers } private fun typeParameterToTypeSpecifier(type: TypeParameter): TypeSpecifier { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/elm/ElmEdit.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/elm/ElmEdit.kt index 0036c9d4f..35702ab2e 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/elm/ElmEdit.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/elm/ElmEdit.kt @@ -21,7 +21,7 @@ enum class ElmEdit : IElmEdit { val x = annotations[i] if (x is Annotation) { x.s = null - // Remove narrative but _not_ tags + // Remove narrative but _not_ tags. // Tags are necessary for `allowFluent` compiler resolution // to work correctly if (x.t.isEmpty()) { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/CompiledLibrary.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/CompiledLibrary.kt index fbbaa147e..f94bc790b 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/CompiledLibrary.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/CompiledLibrary.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.model -import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap import org.hl7.cql.model.DataType @@ -32,11 +31,7 @@ class CompiledLibrary { val existingResolvedIdentifierContext = resolve(identifier) existingResolvedIdentifierContext.exactMatchElement?.let { throw IllegalArgumentException( - String.format( - Locale.US, - "Identifier %s is already in use in this library.", - identifier - ) + "Identifier $identifier is already in use in this library." ) } } @@ -97,25 +92,16 @@ class CompiledLibrary { // If this library has no identifier, the operator must not have an identifier operator.libraryName = operator.libraryName ?: identifier?.id require(operator.libraryName == identifier?.id) { - String.format( - Locale.US, - "Operator %s cannot be registered in library %s because it is defined in library %s.", - operator.name, - identifier?.id ?: "", - operator.libraryName - ) + "Operator ${operator.name} cannot be registered in library ${identifier?.id ?: ""}" + + "because it is defined in library ${operator.libraryName}." } } @Suppress("UnusedPrivateMember") private fun ensureResultType(operator: Operator) { requireNotNull(operator.resultType) { - String.format( - Locale.US, - "Operator %s cannot be registered in library %s because it does not have a result type defined.", - operator.name, - identifier?.id ?: "" - ) + """Operator ${operator.name} cannot be registered in library ${identifier?.id ?: ""} + because it does not have a result type defined.""" } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ConversionMap.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ConversionMap.kt index 3c88bdb29..3f4c99a34 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ConversionMap.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ConversionMap.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.model -import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap import org.hl7.cql.model.ChoiceType @@ -64,24 +63,14 @@ class ConversionMap { if (conversion.isGeneric) { val conversions = genericConversions check(!hasConversion(conversion, conversions)) { - String.format( - Locale.US, - "Conversion from %s to %s is already defined.", - conversion.fromType.toString(), - conversion.toType.toString() - ) + "Conversion from ${conversion.fromType} to ${conversion.toType} is already defined." } conversions.add(conversion) } else { val conversions = getConversions(conversion.fromType) check(!hasConversion(conversion, conversions)) { - String.format( - Locale.US, - "Conversion from %s to %s is already defined.", - conversion.fromType.toString(), - conversion.toType.toString() - ) + "Conversion from ${conversion.fromType} to ${conversion.toType} is already defined." } conversions.add(conversion) @@ -321,13 +310,7 @@ class ConversionMap { } else require(newScore != score) { // ERROR - String.format( - Locale.US, - "Ambiguous implicit conversion from %s to %s or %s.", - fromType.toString(), - result!!.toType.toString(), - conversion.toType.toString() - ) + "Ambiguous implicit conversion from $fromType to ${result!!.toType} or ${conversion.toType}." } } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/InstantiationContextImpl.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/InstantiationContextImpl.kt index eb59e055b..538b7ff52 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/InstantiationContextImpl.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/InstantiationContextImpl.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.model -import java.util.* import kotlin.collections.ArrayList import org.hl7.cql.model.DataType import org.hl7.cql.model.InstantiationContext @@ -144,11 +143,7 @@ class InstantiationContextImpl( val result = typeMap[parameter] ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve type parameter %s.", - parameter.identifier - ) + "Could not resolve type parameter ${parameter.identifier}." ) return result diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/Model.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/Model.kt index 33703477c..fcb5e5e07 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/Model.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/Model.kt @@ -83,12 +83,7 @@ open class Model(val modelInfo: ModelInfo, modelManager: ModelManager?) { // then throw an error require(!mustResolve) { // ERROR: - String.format( - Locale.US, - "Could not resolve context name %s in model %s.", - contextName, - modelInfo.name - ) + "Could not resolve context name $contextName in model ${modelInfo.name}." } return null diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ModelImporter.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ModelImporter.kt index a28c8d71e..e8f689b9b 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ModelImporter.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ModelImporter.kt @@ -114,7 +114,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { val contextType = resolveTypeSpecifier(c.contextType!!) require(contextType is ClassType) { // ERROR: - String.format(Locale.US, "Model context %s must be a class type.", c.name) + "Model context ${c.name} must be a class type." } val modelContext = ModelContext( @@ -202,7 +202,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { qualifier = modelInfo.name } - val qualifiedTypeName = String.format(Locale.US, "%s.%s", qualifier, typeSpecifier.name) + val qualifiedTypeName = "$qualifier.${typeSpecifier.name}" return resolveTypeName(qualifiedTypeName) } @@ -277,11 +277,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { val typeInfo = lookupTypeInfo(ensureUnqualified(typeName)) ?: throw IllegalArgumentException( - String.format( - Locale.US, - "Could not resolve type info for type name %s.", - typeName - ) + "Could not resolve type info for type name $typeName." ) result = resolveTypeInfo(typeInfo) @@ -338,9 +334,9 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { // qualified with the // model name private fun ensureQualified(name: String): String { - val qualifier = String.format(Locale.US, "%s.", modelInfo.name) + val qualifier = "${modelInfo.name}." if (!name.startsWith(qualifier)) { - return String.format(Locale.US, "%s%s", qualifier, name) + return "$qualifier$name" } return name @@ -350,7 +346,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { // qualified with the // model name private fun ensureUnqualified(name: String): String { - if (name.startsWith(String.format(Locale.US, "%s.", modelInfo.name))) { + if (name.startsWith("${modelInfo.name}.")) { return name.substring(name.indexOf('.') + 1) } @@ -361,11 +357,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { val qualifiedTypeName = ensureQualified(t.name!!) val lookupType = lookupType(qualifiedTypeName) require(lookupType !is ClassType) { - String.format( - Locale.US, - "Expected instance of SimpleType but found instance of %s instead.", - lookupType - ) + "Expected instance of SimpleType but found instance of $lookupType instead." } var result = lookupType(qualifiedTypeName) as SimpleType? @@ -670,9 +662,7 @@ class ModelImporter(val modelInfo: ModelInfo, val modelManager: ModelManager?) { } } - throw IllegalArgumentException( - String.format(Locale.US, "Could not resolve context name %s.", contextName) - ) + throw IllegalArgumentException("Could not resolve context name $contextName.") } private fun resolveRelationship(relationshipInfo: RelationshipInfo): Relationship { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/OperatorEntry.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/OperatorEntry.kt index 51b13078b..a381fd782 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/OperatorEntry.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/OperatorEntry.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.model -import java.util.* import kotlin.collections.ArrayList import kotlin.collections.HashMap import org.hl7.cql.model.ChoiceType @@ -224,12 +223,7 @@ class OperatorEntry(val name: String) { requireNotNull(node) { "node is null." } require(!signatures.containsKey(node.signature)) { - String.format( - Locale.US, - "Operator %s already has a registration for signature: %s.", - node.operator.name, - node.signature.toString() - ) + "Operator ${node.operator.name} already has a registration for signature: ${node.signature}." } var added = false @@ -307,12 +301,7 @@ class OperatorEntry(val name: String) { private fun addGenericOperator(operator: GenericOperator) { require(!genericOperators.containsKey(operator.signature)) { - String.format( - Locale.US, - "Operator %s already has a generic registration for signature: %s.", - name, - operator.signature.toString() - ) + "Operator $name already has a generic registration for signature: ${operator.signature}." } genericOperators[operator.signature] = operator diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/QueryContext.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/QueryContext.kt index 5334cefc0..2869710ac 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/QueryContext.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/QueryContext.kt @@ -48,7 +48,7 @@ class QueryContext { lets[let.identifier!!] = let } - fun removeLetClause(let: LetClause) { + private fun removeLetClause(let: LetClause) { lets.remove(let.identifier) } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.kt index 322c97773..b46652d21 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/ResolvedIdentifierContext.kt @@ -40,12 +40,7 @@ private constructor( fun warnCaseInsensitiveIfApplicable(): String? { if (element != null && !isExactMatch) { return getName(element)?.let { - String.format( - Locale.US, - "Could not find identifier: [%s]. Did you mean [%s]?", - identifier, - it - ) + "Could not find identifier: [$identifier]. Did you mean [$it]?" } } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/SystemLibraryHelper.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/SystemLibraryHelper.kt index 93c264eb2..e3d245e72 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/SystemLibraryHelper.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/model/SystemLibraryHelper.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.model -import java.util.* import org.cqframework.cql.cql2elm.TypeBuilder import org.cqframework.cql.cql2elm.tracking.Trackable.resultType import org.hl7.cql.model.IntervalType @@ -2947,7 +2946,7 @@ object SystemLibraryHelper { var n = 0 for (dataType in operator.signature.operandTypes) { n++ - val od = OperandDef().withName(String.format(Locale.US, "param%d", n)) + val od = OperandDef().withName("param${n}") if (dataType is NamedType) { od.operandType = tb.dataTypeToQName(dataType) } else { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessor.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessor.kt index 6ca89b2b9..7f51863b6 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessor.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessor.kt @@ -2,7 +2,6 @@ package org.cqframework.cql.cql2elm.preprocessor -import java.util.* import kotlin.collections.ArrayList import org.antlr.v4.kotlinruntime.Recognizer import org.antlr.v4.kotlinruntime.TokenStream @@ -135,13 +134,8 @@ class CqlPreprocessor(libraryBuilder: LibraryBuilder, tokenStream: TokenStream) if (ctx.localIdentifier() == null) unqualifiedIdentifier else parseString(ctx.localIdentifier())!! require(localIdentifier == unqualifiedIdentifier) { - String.format( - Locale.US, - @Suppress("MaxLineLength") - "Local identifiers for models must be the same as the name of the model in this release of the translator (Model %s, Called %s)", - unqualifiedIdentifier, - localIdentifier - ) + """Local identifiers for models must be the same as the name of the model + in this release of the translator (Model $unqualifiedIdentifier, Called $localIdentifier)""" } // This has the side effect of initializing @@ -238,7 +232,7 @@ class CqlPreprocessor(libraryBuilder: LibraryBuilder, tokenStream: TokenStream) val modelIdentifier = getModelIdentifier(qualifiers) val identifier = getTypeIdentifier(qualifiers, parseString(ctx.referentialOrTypeNameIdentifier())!!) - val typeSpecifierKey = String.format(Locale.US, "%s:%s", modelIdentifier, identifier) + val typeSpecifierKey = "$modelIdentifier:$identifier" val resultType = libraryBuilder.resolveTypeName(modelIdentifier, identifier) if (null == resultType) { libraryBuilder.addNamedTypeSpecifierResult( @@ -246,12 +240,7 @@ class CqlPreprocessor(libraryBuilder: LibraryBuilder, tokenStream: TokenStream) ResultWithPossibleError.withError() ) throw CqlCompilerException( - String.format( - Locale.US, - "Could not find type for model: %s and name: %s", - modelIdentifier, - identifier - ) + "Could not find type for model: $modelIdentifier and name: $identifier" ) } val result = diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessorElmCommonVisitor.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessorElmCommonVisitor.kt index c4f93d3db..b0672cb01 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessorElmCommonVisitor.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/CqlPreprocessorElmCommonVisitor.kt @@ -42,10 +42,8 @@ abstract class CqlPreprocessorElmCommonVisitor( @JvmField protected val libraryBuilder: LibraryBuilder, protected val tokenStream: TokenStream ) : cqlBaseVisitor() { - @JvmField - protected val of: IdObjectFactory = - requireNotNull(libraryBuilder.objectFactory) { "libraryBuilder.objectFactory required" } - protected val af = ObjectFactory() + @JvmField protected val of: IdObjectFactory = libraryBuilder.objectFactory + private val af = ObjectFactory() protected var implicitContextCreated = false protected var currentContext = "Unfiltered" @JvmField protected var chunks = Stack() @@ -87,17 +85,11 @@ abstract class CqlPreprocessorElmCommonVisitor( // ERROR: try { o = super.visit(tree) - if (o is Element) { - if (o.localId == null) { - throw CqlInternalException( - String.format( - Locale.US, - "Internal translator error. 'localId' was not assigned for Element \"%s\"", - o.javaClass.name - ), - getTrackBack(tree) - ) - } + if (o is Element && o.localId == null) { + throw CqlInternalException( + "Internal translator error. 'localId' was not assigned for Element \"${o.javaClass.name}\"", + getTrackBack(tree) + ) } } catch (e: CqlIncludeException) { val translatorException = CqlCompilerException(e.message, getTrackBack(tree), e) @@ -285,7 +277,7 @@ abstract class CqlPreprocessorElmCommonVisitor( o is ExpressionDef ) { val a = getAnnotation(o) - if (a == null || a.s == null) { + if (a?.s == null) { // Add header information (comments prior to the definition) val definitionInfo = libraryInfo.resolveDefinition(tree) if (definitionInfo?.headerInterval != null) { diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/LibraryInfo.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/LibraryInfo.kt index 1af450d0d..25d695c8d 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/LibraryInfo.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/preprocessor/LibraryInfo.kt @@ -153,7 +153,7 @@ class LibraryInfo( addDefinition(functionDefinition) } - fun resolveFunctionReference(identifier: String): Iterable? { + fun resolveFunctionReference(identifier: String): List? { return functionDefinitions[identifier] } diff --git a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/tracking/TrackBack.kt b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/tracking/TrackBack.kt index 43ecf0576..d4ae90cfd 100644 --- a/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/tracking/TrackBack.kt +++ b/Src/java/cql-to-elm/src/main/kotlin/org/cqframework/cql/cql2elm/tracking/TrackBack.kt @@ -1,6 +1,5 @@ package org.cqframework.cql.cql2elm.tracking -import java.util.* import org.hl7.elm.r1.VersionedIdentifier data class TrackBack( @@ -28,8 +27,7 @@ data class TrackBack( } fun toLocator(): String { - return if (startLine == endLine && startChar == endChar) - String.format(Locale.US, "%s:%s", startLine, startChar) - else String.format(Locale.US, "%s:%s-%s:%s", startLine, startChar, endLine, endChar) + return if (startLine == endLine && startChar == endChar) "$startLine:$startChar" + else "$startLine:$startChar-$endLine:$endChar" } } diff --git a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/evaluating/SimpleElmEngine.kt b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/evaluating/SimpleElmEngine.kt index 68062f205..a0519f67d 100644 --- a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/evaluating/SimpleElmEngine.kt +++ b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/evaluating/SimpleElmEngine.kt @@ -91,8 +91,7 @@ etc.) class SimpleElmEngine { private fun literalsEqual(left: Literal?, right: Literal?): Boolean { return (left == null && right == null) || - (left != null && - left.valueType != null && + (left?.valueType != null && left.valueType == right!!.valueType && stringsEqual(left.value, right.value)) } @@ -109,7 +108,7 @@ class SimpleElmEngine { return expressionsEqual(left, right) } - fun decimalsEqual(left: BigDecimal?, right: BigDecimal?): Boolean { + private fun decimalsEqual(left: BigDecimal?, right: BigDecimal?): Boolean { if (left == null && right == null) { return true } @@ -121,7 +120,7 @@ class SimpleElmEngine { return left == right } - fun quantitiesEqual(left: Quantity?, right: Quantity?): Boolean { + private fun quantitiesEqual(left: Quantity?, right: Quantity?): Boolean { if (left == null && right == null) { return true } @@ -149,7 +148,7 @@ class SimpleElmEngine { return (left == null && right == null) || (left != null && left == right) } - fun systemsEqual(left: CodeSystemRef?, right: CodeSystemRef?): Boolean { + private fun systemsEqual(left: CodeSystemRef?, right: CodeSystemRef?): Boolean { // TODO: Needs to do the comparison on the URI, but I don't want to have to resolve here return (left == null && right == null) || (left != null && @@ -157,7 +156,7 @@ class SimpleElmEngine { stringsEqual(left.name, right.name)) } - fun valueSetsEqual(left: ValueSetRef?, right: ValueSetRef?): Boolean { + private fun valueSetsEqual(left: ValueSetRef?, right: ValueSetRef?): Boolean { // TODO: Needs to do the comparison on the URI, but I don't want to have to resolve here return (left == null && right == null) || (left != null && @@ -220,26 +219,15 @@ class SimpleElmEngine { // TupleTypeSpecifier if (left is TupleTypeSpecifier) { if (right is TupleTypeSpecifier) { - val leftArg = left - val rightArg = right - if ( - leftArg.element != null && - rightArg.element != null && - leftArg.element!!.size == rightArg.element!!.size - ) { - for (i in leftArg.element!!.indices) { - val leftElement = leftArg.element!![i] - val rightElement = rightArg.element!![i] + if (left.element.size == right.element.size) { + for (i in left.element.indices) { + val leftElement = left.element[i] + val rightElement = right.element[i] if ( !typeSpecifiersEqual( - leftElement!!.elementType, - rightElement!!.elementType - ) || - !typeSpecifiersEqual( - leftElement.elementType, - rightElement.elementType - ) || - !stringsEqual(leftElement.name, rightElement.name) + leftElement.elementType, + rightElement.elementType + ) || !stringsEqual(leftElement.name, rightElement.name) ) { return false } @@ -257,30 +245,20 @@ class SimpleElmEngine { // ChoiceTypeSpecifier if (left is ChoiceTypeSpecifier) { if (right is ChoiceTypeSpecifier) { - val leftArg = left - val rightArg = right - if ( - leftArg.choice != null && - rightArg.choice != null && - leftArg.choice!!.size == rightArg.choice!!.size - ) { - for (i in leftArg.choice!!.indices) { - val leftType = leftArg.choice!![i] - val rightType = rightArg.choice!![i] + if (left.choice.size == right.choice.size) { + for (i in left.choice.indices) { + val leftType = left.choice[i] + val rightType = right.choice[i] if (!typeSpecifiersEqual(leftType, rightType)) { return false } } } - if ( - leftArg.choice != null && - rightArg.choice != null && - leftArg.choice!!.size == rightArg.choice!!.size - ) { - for (i in leftArg.choice!!.indices) { - val leftType = leftArg.choice!![i] - val rightType = rightArg.choice!![i] + if (left.choice.size == right.choice.size) { + for (i in left.choice.indices) { + val leftType = left.choice[i] + val rightType = right.choice[i] if (!typeSpecifiersEqual(leftType, rightType)) { return false } @@ -299,7 +277,7 @@ class SimpleElmEngine { return false } - fun expressionsEqual(left: Expression?, right: Expression?): Boolean { + private fun expressionsEqual(left: Expression?, right: Expression?): Boolean { if (left == null && right == null) { return true } @@ -318,12 +296,10 @@ class SimpleElmEngine { if (left is Date) { if (right is Date) { - val leftDate = left - val rightDate = right - return integersEqual(leftDate.year, rightDate.year) && - integersEqual(leftDate.month, rightDate.month) && - integersEqual(leftDate.day, rightDate.day) + return integersEqual(left.year, right.year) && + integersEqual(left.month, right.month) && + integersEqual(left.day, right.day) } return false @@ -331,13 +307,11 @@ class SimpleElmEngine { if (left is Time) { if (right is Time) { - val leftTime = left - val rightTime = right - return integersEqual(leftTime.hour, rightTime.hour) && - integersEqual(leftTime.minute, rightTime.minute) && - integersEqual(leftTime.second, rightTime.second) && - integersEqual(leftTime.millisecond, rightTime.millisecond) + return integersEqual(left.hour, right.hour) && + integersEqual(left.minute, right.minute) && + integersEqual(left.second, right.second) && + integersEqual(left.millisecond, right.millisecond) } return false @@ -345,17 +319,15 @@ class SimpleElmEngine { if (left is DateTime) { if (right is DateTime) { - val leftDateTime = left - val rightDateTime = right - return integersEqual(leftDateTime.year, rightDateTime.year) && - integersEqual(leftDateTime.month, rightDateTime.month) && - integersEqual(leftDateTime.day, rightDateTime.day) && - integersEqual(leftDateTime.hour, rightDateTime.hour) && - integersEqual(leftDateTime.minute, rightDateTime.minute) && - integersEqual(leftDateTime.second, rightDateTime.second) && - integersEqual(leftDateTime.millisecond, rightDateTime.millisecond) && - decimalsEqual(leftDateTime.timezoneOffset, rightDateTime.timezoneOffset) + return integersEqual(left.year, right.year) && + integersEqual(left.month, right.month) && + integersEqual(left.day, right.day) && + integersEqual(left.hour, right.hour) && + integersEqual(left.minute, right.minute) && + integersEqual(left.second, right.second) && + integersEqual(left.millisecond, right.millisecond) && + decimalsEqual(left.timezoneOffset, right.timezoneOffset) } return false @@ -363,21 +335,13 @@ class SimpleElmEngine { if (left is Interval) { if (right is Interval) { - val leftInterval = left - val rightInterval = right - return booleansEqual( - leftInterval.lowClosedExpression, - rightInterval.lowClosedExpression - ) && - dateTimesEqual(leftInterval.low, rightInterval.low) && - leftInterval.isLowClosed() == rightInterval.isLowClosed() && - booleansEqual( - leftInterval.highClosedExpression, - rightInterval.highClosedExpression - ) && - dateTimesEqual(leftInterval.high, rightInterval.high) && - leftInterval.isHighClosed() == rightInterval.isHighClosed() + return booleansEqual(left.lowClosedExpression, right.lowClosedExpression) && + dateTimesEqual(left.low, right.low) && + left.isLowClosed() == right.isLowClosed() && + booleansEqual(left.highClosedExpression, right.highClosedExpression) && + dateTimesEqual(left.high, right.high) && + left.isHighClosed() == right.isHighClosed() } return false @@ -388,10 +352,8 @@ class SimpleElmEngine { // local parameter reference if (left is ParameterRef) { if (right is ParameterRef) { - val leftParameter = left - val rightParameter = right - return stringsEqual(leftParameter.libraryName, rightParameter.libraryName) && - stringsEqual(leftParameter.name, rightParameter.name) + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) } return false @@ -415,11 +377,9 @@ class SimpleElmEngine { if (left is ConceptRef) { if (right is ConceptRef) { - val leftConcept = left - val rightConcept = right // TODO: Needs to do the comparison on the URI, but I don't want to resolve here - return stringsEqual(leftConcept.libraryName, rightConcept.libraryName) && - stringsEqual(leftConcept.name, rightConcept.name) + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) } return false @@ -427,11 +387,9 @@ class SimpleElmEngine { if (left is CodeRef) { if (right is CodeRef) { - val leftCode = left - val rightCode = right // TODO: Needs to do the comparison on the URI, but I don't want to resolve here - return stringsEqual(leftCode.libraryName, rightCode.libraryName) && - stringsEqual(leftCode.name, rightCode.name) + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) } return false @@ -439,10 +397,8 @@ class SimpleElmEngine { if (left is Code) { if (right is Code) { - val leftCode = left - val rightCode = right - return stringsEqual(leftCode.code, rightCode.code) && - systemsEqual(leftCode.system, rightCode.system) + return stringsEqual(left.code, right.code) && + systemsEqual(left.system, right.system) } return false @@ -450,14 +406,10 @@ class SimpleElmEngine { if (left is Concept) { if (right is Concept) { - val leftConcept = left - val rightConcept = right - if (leftConcept.code != null && rightConcept.code != null) { - for (lc in leftConcept.code!!) { - for (rc in rightConcept.code!!) { - if (codesEqual(lc, rc)) { - return true - } + for (lc in left.code) { + for (rc in right.code) { + if (codesEqual(lc, rc)) { + return true } } } @@ -467,15 +419,11 @@ class SimpleElmEngine { } if (left is List) { - if (right is List) { - val leftList = left - val rightList = right - // TODO: Potentially use a hashSet to avoid order-dependence here - if (leftList.element!!.size == rightList.element!!.size) { - for (i in leftList.element!!.indices) { - if (!codesEqual(leftList.element!![i], rightList.element!![i])) { - return false - } + // TODO: Potentially use a hashSet to avoid order-dependence here + if (right is List && left.element.size == right.element.size) { + for (i in left.element.indices) { + if (!codesEqual(left.element[i], right.element[i])) { + return false } } } @@ -518,14 +466,9 @@ class SimpleElmEngine { // InCodeSystem if (left is InCodeSystem) { if (right is InCodeSystem) { - val inCodeSystemLeft = left - val inCodeSystemRight = right - return expressionsEqual(inCodeSystemLeft.code, inCodeSystemRight.code) && - systemsEqual(inCodeSystemLeft.codesystem, inCodeSystemRight.codesystem) && - expressionsEqual( - inCodeSystemLeft.codesystemExpression, - inCodeSystemRight.codesystemExpression - ) + return expressionsEqual(left.code, right.code) && + systemsEqual(left.codesystem, right.codesystem) && + expressionsEqual(left.codesystemExpression, right.codesystemExpression) } return false @@ -534,14 +477,9 @@ class SimpleElmEngine { // AnyInCodeSystem if (left is AnyInCodeSystem) { if (right is AnyInCodeSystem) { - val anyInCodeSystemLeft = left - val anyInCodeSystemRight = right - return expressionsEqual(anyInCodeSystemLeft.codes, anyInCodeSystemRight.codes) && - systemsEqual(anyInCodeSystemLeft.codesystem, anyInCodeSystemRight.codesystem) && - expressionsEqual( - anyInCodeSystemLeft.codesystemExpression, - anyInCodeSystemRight.codesystemExpression - ) + return expressionsEqual(left.codes, right.codes) && + systemsEqual(left.codesystem, right.codesystem) && + expressionsEqual(left.codesystemExpression, right.codesystemExpression) } return false @@ -550,11 +488,9 @@ class SimpleElmEngine { // InValueSet if (left is InValueSet) { if (right is InValueSet) { - val inLeft = left - val inRight = right - return expressionsEqual(inLeft.code, inRight.code) && - valueSetsEqual(inLeft.valueset, inRight.valueset) && - expressionsEqual(inLeft.valuesetExpression, inRight.valuesetExpression) + return expressionsEqual(left.code, right.code) && + valueSetsEqual(left.valueset, right.valueset) && + expressionsEqual(left.valuesetExpression, right.valuesetExpression) } return false @@ -563,11 +499,9 @@ class SimpleElmEngine { // AnyInValueSet if (left is AnyInValueSet) { if (right is AnyInValueSet) { - val inLeft = left - val inRight = right - return expressionsEqual(inLeft.codes, inRight.codes) && - valueSetsEqual(inLeft.valueset, inRight.valueset) && - expressionsEqual(inLeft.valuesetExpression, inRight.valuesetExpression) + return expressionsEqual(left.codes, right.codes) && + valueSetsEqual(left.valueset, right.valueset) && + expressionsEqual(left.valuesetExpression, right.valuesetExpression) } return false @@ -576,10 +510,8 @@ class SimpleElmEngine { // CalculateAge if (left is CalculateAge) { if (right is CalculateAge) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.operand, rightArg.operand) && - leftArg.precision == rightArg.precision + return expressionsEqual(left.operand, right.operand) && + left.precision == right.precision } return false @@ -588,11 +520,7 @@ class SimpleElmEngine { // Subsumes if (left is Subsumes) { if (right is Subsumes) { - if (operandsEqual(left, right)) { - return true - } - - return false + return operandsEqual(left, right) } return false @@ -601,11 +529,7 @@ class SimpleElmEngine { // SubsumedBy if (left is SubsumedBy) { if (right is SubsumedBy) { - if (operandsEqual(left, right)) { - return true - } - - return false + return operandsEqual(left, right) } return false @@ -645,26 +569,20 @@ class SimpleElmEngine { // Case if (left is Case) { if (right is Case) { - val leftArg = left - val rightArg = right - if (!expressionsEqual(leftArg.comparand, rightArg.comparand)) { + if (!expressionsEqual(left.comparand, right.comparand)) { return false } - if (!expressionsEqual(leftArg.`else`, rightArg.`else`)) { + if (!expressionsEqual(left.`else`, right.`else`)) { return false } - if ( - leftArg.caseItem != null && - rightArg.caseItem != null && - (leftArg.caseItem!!.size == rightArg.caseItem!!.size) - ) { - for (i in leftArg.caseItem!!.indices) { - val leftCaseItem = leftArg.caseItem!![i] - val rightCaseItem = rightArg.caseItem!![i] + if (left.caseItem.size == right.caseItem.size) { + for (i in left.caseItem.indices) { + val leftCaseItem = left.caseItem[i] + val rightCaseItem = right.caseItem[i] if ( - !expressionsEqual(leftCaseItem!!.`when`, rightCaseItem!!.`when`) || + !expressionsEqual(leftCaseItem.`when`, rightCaseItem.`when`) || !expressionsEqual(leftCaseItem.then, rightCaseItem.then) ) { return false @@ -690,23 +608,17 @@ class SimpleElmEngine { } // FunctionRef - if (left is FunctionRef) { - if (right is FunctionRef) { - val leftArg = left - val rightArg = right - return stringsEqual(leftArg.libraryName, rightArg.libraryName) && - stringsEqual(leftArg.name, rightArg.name) && - operandsEqual(leftArg, rightArg) - } + if (left is FunctionRef && right is FunctionRef) { + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) && + operandsEqual(left, right) } // ExpressionRef if (left is ExpressionRef) { if (right is ExpressionRef) { - val leftArg = left - val rightArg = right - return stringsEqual(leftArg.libraryName, rightArg.libraryName) && - stringsEqual(leftArg.name, rightArg.name) + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) } return false @@ -715,11 +627,9 @@ class SimpleElmEngine { // Filter if (left is Filter) { if (right is Filter) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.condition, rightArg.condition) && - stringsEqual(leftArg.scope, rightArg.scope) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.condition, right.condition) && + stringsEqual(left.scope, right.scope) } return false @@ -728,11 +638,9 @@ class SimpleElmEngine { // ForEach if (left is ForEach) { if (right is ForEach) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.element, rightArg.element) && - stringsEqual(leftArg.scope, rightArg.scope) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.element, right.element) && + stringsEqual(left.scope, right.scope) } return false @@ -741,10 +649,8 @@ class SimpleElmEngine { // IdentifierRef if (left is IdentifierRef) { if (right is IdentifierRef) { - val leftArg = left - val rightArg = right - return stringsEqual(leftArg.libraryName, rightArg.libraryName) && - stringsEqual(leftArg.name, rightArg.name) + return stringsEqual(left.libraryName, right.libraryName) && + stringsEqual(left.name, right.name) } return false @@ -753,11 +659,9 @@ class SimpleElmEngine { // If if (left is If) { if (right is If) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.condition, rightArg.condition) && - expressionsEqual(leftArg.then, rightArg.then) && - expressionsEqual(leftArg.`else`, rightArg.`else`) + return expressionsEqual(left.condition, right.condition) && + expressionsEqual(left.then, right.then) && + expressionsEqual(left.`else`, right.`else`) } return false @@ -766,22 +670,16 @@ class SimpleElmEngine { // Instance if (left is Instance) { if (right is Instance) { - val leftArg = left - val rightArg = right - if (!qnamesEqual(leftArg.classType, rightArg.classType)) { + if (!qnamesEqual(left.classType, right.classType)) { return false } - if ( - leftArg.element != null && - rightArg.element != null && - leftArg.element!!.size == rightArg.element!!.size - ) { - for (i in leftArg.element!!.indices) { - val leftElement = leftArg.element!![i] - val rightElement = rightArg.element!![i] + if (left.element.size == right.element.size) { + for (i in left.element.indices) { + val leftElement = left.element[i] + val rightElement = right.element[i] if ( - !stringsEqual(leftElement!!.name, rightElement!!.name) || + !stringsEqual(leftElement.name, rightElement.name) || !expressionsEqual(leftElement.value, rightElement.value) ) { return false @@ -826,11 +724,7 @@ class SimpleElmEngine { // Null if (left is Null) { - if (right is Null) { - return true - } - - return false + return right is Null } // OperandRef @@ -845,10 +739,7 @@ class SimpleElmEngine { // Property if (left is Property) { if (right is Property) { - val leftArg = left - val rightArg = right - return stringsEqual(leftArg.scope, rightArg.scope) && - stringsEqual(leftArg.path, rightArg.path) + return stringsEqual(left.scope, right.scope) && stringsEqual(left.path, right.path) } return false @@ -857,8 +748,7 @@ class SimpleElmEngine { // Query if (left is Query) { if (right is Query) { - val leftArg = left - val rightArg = right + // TODO: Implement Query equality } return false @@ -876,8 +766,7 @@ class SimpleElmEngine { // Repeat if (left is Repeat) { if (right is Repeat) { - val leftArg = left - val rightArg = right + // TODO: Implement Repeat equality } return false @@ -886,8 +775,7 @@ class SimpleElmEngine { // Sort if (left is Sort) { if (right is Sort) { - val leftArg = left - val rightArg = right + // TODO: Implement Sort equality } return false @@ -896,8 +784,7 @@ class SimpleElmEngine { // Total if (left is Total) { if (right is Total) { - val leftArg = left - val rightArg = right + // TODO: Implement Total equality } return false @@ -906,8 +793,7 @@ class SimpleElmEngine { // Tuple if (left is Tuple) { if (right is Tuple) { - val leftArg = left - val rightArg = right + // TODO: Implement Tuple equality } return false @@ -916,14 +802,10 @@ class SimpleElmEngine { return false } - fun operandsEqual(left: FunctionRef, right: FunctionRef): Boolean { - if ( - left.operand != null && - right.operand != null && - left.operand!!.size == right.operand!!.size - ) { - for (i in left.operand!!.indices) { - if (!expressionsEqual(left.operand!![i], right.operand!![i])) { + private fun operandsEqual(left: FunctionRef, right: FunctionRef): Boolean { + if (left.operand.size == right.operand.size) { + for (i in left.operand.indices) { + if (!expressionsEqual(left.operand[i], right.operand[i])) { return false } } @@ -934,14 +816,10 @@ class SimpleElmEngine { return false } - fun operandsEqual(left: BinaryExpression, right: BinaryExpression): Boolean { - if ( - left.operand != null && - right.operand != null && - left.operand!!.size == right.operand!!.size - ) { - for (i in left.operand!!.indices) { - if (!expressionsEqual(left.operand!![i], right.operand!![i])) { + private fun operandsEqual(left: BinaryExpression, right: BinaryExpression): Boolean { + if (left.operand.size == right.operand.size) { + for (i in left.operand.indices) { + if (!expressionsEqual(left.operand[i], right.operand[i])) { return false } } @@ -952,14 +830,10 @@ class SimpleElmEngine { return false } - fun operandsEqual(left: TernaryExpression, right: TernaryExpression): Boolean { - if ( - left.operand != null && - right.operand != null && - left.operand!!.size == right.operand!!.size - ) { - for (i in left.operand!!.indices) { - if (!expressionsEqual(left.operand!![i], right.operand!![i])) { + private fun operandsEqual(left: TernaryExpression, right: TernaryExpression): Boolean { + if (left.operand.size == right.operand.size) { + for (i in left.operand.indices) { + if (!expressionsEqual(left.operand[i], right.operand[i])) { return false } } @@ -970,14 +844,10 @@ class SimpleElmEngine { return false } - fun operandsEqual(left: NaryExpression, right: NaryExpression): Boolean { - if ( - left.operand != null && - right.operand != null && - left.operand!!.size == right.operand!!.size - ) { - for (i in left.operand!!.indices) { - if (!expressionsEqual(left.operand!![i], right.operand!![i])) { + private fun operandsEqual(left: NaryExpression, right: NaryExpression): Boolean { + if (left.operand.size == right.operand.size) { + for (i in left.operand.indices) { + if (!expressionsEqual(left.operand[i], right.operand[i])) { return false } } @@ -988,7 +858,10 @@ class SimpleElmEngine { return false } - fun operatorExpressionsEqual(left: OperatorExpression?, right: OperatorExpression?): Boolean { + private fun operatorExpressionsEqual( + left: OperatorExpression?, + right: OperatorExpression? + ): Boolean { if (left == null && right == null) { return true } @@ -1040,10 +913,8 @@ class SimpleElmEngine { // Round if (left is Round) { if (right is Round) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.operand, rightArg.operand) && - expressionsEqual(leftArg.precision, rightArg.precision) + return expressionsEqual(left.operand, right.operand) && + expressionsEqual(left.precision, right.precision) } return false @@ -1052,10 +923,8 @@ class SimpleElmEngine { // Combine if (left is Combine) { if (right is Combine) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.separator, rightArg.separator) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.separator, right.separator) } return false @@ -1064,10 +933,8 @@ class SimpleElmEngine { // Split if (left is Split) { if (right is Split) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.stringToSplit, rightArg.stringToSplit) && - expressionsEqual(leftArg.separator, rightArg.separator) + return expressionsEqual(left.stringToSplit, right.stringToSplit) && + expressionsEqual(left.separator, right.separator) } return false @@ -1076,10 +943,8 @@ class SimpleElmEngine { // SplitOnMatches if (left is SplitOnMatches) { if (right is SplitOnMatches) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.stringToSplit, rightArg.stringToSplit) && - expressionsEqual(leftArg.separatorPattern, rightArg.separatorPattern) + return expressionsEqual(left.stringToSplit, right.stringToSplit) && + expressionsEqual(left.separatorPattern, right.separatorPattern) } return false @@ -1088,10 +953,8 @@ class SimpleElmEngine { // PositionOf if (left is PositionOf) { if (right is PositionOf) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.string, rightArg.string) && - expressionsEqual(leftArg.pattern, rightArg.pattern) + return expressionsEqual(left.string, right.string) && + expressionsEqual(left.pattern, right.pattern) } return false @@ -1100,10 +963,8 @@ class SimpleElmEngine { // LastPositionOf if (left is LastPositionOf) { if (right is LastPositionOf) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.string, rightArg.string) && - expressionsEqual(leftArg.pattern, rightArg.pattern) + return expressionsEqual(left.string, right.string) && + expressionsEqual(left.pattern, right.pattern) } return false @@ -1112,11 +973,9 @@ class SimpleElmEngine { // Substring if (left is Substring) { if (right is Substring) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.stringToSub, rightArg.stringToSub) && - expressionsEqual(leftArg.startIndex, rightArg.startIndex) && - expressionsEqual(leftArg.length, rightArg.length) + return expressionsEqual(left.stringToSub, right.stringToSub) && + expressionsEqual(left.startIndex, right.startIndex) && + expressionsEqual(left.length, right.length) } return false @@ -1129,12 +988,10 @@ class SimpleElmEngine { // Time if (left is Time) { if (right is Time) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.hour, rightArg.hour) && - expressionsEqual(leftArg.minute, rightArg.minute) && - expressionsEqual(leftArg.second, rightArg.second) && - expressionsEqual(leftArg.millisecond, rightArg.millisecond) + return expressionsEqual(left.hour, right.hour) && + expressionsEqual(left.minute, right.minute) && + expressionsEqual(left.second, right.second) && + expressionsEqual(left.millisecond, right.millisecond) } return false @@ -1143,11 +1000,9 @@ class SimpleElmEngine { // Date if (left is Date) { if (right is Date) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.year, rightArg.year) && - expressionsEqual(leftArg.month, rightArg.month) && - expressionsEqual(leftArg.day, rightArg.day) + return expressionsEqual(left.year, right.year) && + expressionsEqual(left.month, right.month) && + expressionsEqual(left.day, right.day) } return false @@ -1156,16 +1011,14 @@ class SimpleElmEngine { // DateTime if (left is DateTime) { if (right is DateTime) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.year, rightArg.year) && - expressionsEqual(leftArg.month, rightArg.month) && - expressionsEqual(leftArg.day, rightArg.day) && - expressionsEqual(leftArg.hour, rightArg.hour) && - expressionsEqual(leftArg.minute, rightArg.minute) && - expressionsEqual(leftArg.second, rightArg.second) && - expressionsEqual(leftArg.millisecond, rightArg.millisecond) && - expressionsEqual(leftArg.timezoneOffset, rightArg.timezoneOffset) + return expressionsEqual(left.year, right.year) && + expressionsEqual(left.month, right.month) && + expressionsEqual(left.day, right.day) && + expressionsEqual(left.hour, right.hour) && + expressionsEqual(left.minute, right.minute) && + expressionsEqual(left.second, right.second) && + expressionsEqual(left.millisecond, right.millisecond) && + expressionsEqual(left.timezoneOffset, right.timezoneOffset) } return false @@ -1174,10 +1027,8 @@ class SimpleElmEngine { // First if (left is First) { if (right is First) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - stringsEqual(leftArg.orderBy, rightArg.orderBy) + return expressionsEqual(left.source, right.source) && + stringsEqual(left.orderBy, right.orderBy) } return false @@ -1186,10 +1037,8 @@ class SimpleElmEngine { // Last if (left is Last) { if (right is Last) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - stringsEqual(leftArg.orderBy, rightArg.orderBy) + return expressionsEqual(left.source, right.source) && + stringsEqual(left.orderBy, right.orderBy) } return false @@ -1198,10 +1047,8 @@ class SimpleElmEngine { // IndexOf if (left is IndexOf) { if (right is IndexOf) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.element, rightArg.element) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.element, right.element) } return false @@ -1210,11 +1057,9 @@ class SimpleElmEngine { // Slice if (left is Slice) { if (right is Slice) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.startIndex, rightArg.startIndex) && - expressionsEqual(leftArg.endIndex, rightArg.endIndex) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.startIndex, right.startIndex) && + expressionsEqual(left.endIndex, right.endIndex) } return false @@ -1241,13 +1086,11 @@ class SimpleElmEngine { // Message if (left is Message) { if (right is Message) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.source, rightArg.source) && - expressionsEqual(leftArg.code, rightArg.code) && - expressionsEqual(leftArg.condition, rightArg.condition) && - expressionsEqual(leftArg.message, rightArg.message) && - expressionsEqual(leftArg.severity, rightArg.severity) + return expressionsEqual(left.source, right.source) && + expressionsEqual(left.code, right.code) && + expressionsEqual(left.condition, right.condition) && + expressionsEqual(left.message, right.message) && + expressionsEqual(left.severity, right.severity) } return false @@ -1258,11 +1101,11 @@ class SimpleElmEngine { return true } - fun operandsEqual(left: UnaryExpression, right: UnaryExpression): Boolean { + private fun operandsEqual(left: UnaryExpression, right: UnaryExpression): Boolean { return expressionsEqual(left.operand, right.operand) } - fun unaryExpressionsEqual(left: UnaryExpression?, right: UnaryExpression?): Boolean { + private fun unaryExpressionsEqual(left: UnaryExpression?, right: UnaryExpression?): Boolean { if (left == null && right == null) { return true } @@ -1281,23 +1124,17 @@ class SimpleElmEngine { // Abs // As - if (left is As) { - if (right is As) { - val leftArg = left - val rightArg = right - return qnamesEqual(leftArg.asType, rightArg.asType) && - typeSpecifiersEqual(leftArg.asTypeSpecifier, rightArg.asTypeSpecifier) && - leftArg.isStrict() == rightArg.isStrict() - } + if (left is As && right is As) { + return qnamesEqual(left.asType, right.asType) && + typeSpecifiersEqual(left.asTypeSpecifier, right.asTypeSpecifier) && + left.isStrict() == right.isStrict() } // Ceiling // CanConvert if (left is CanConvert) { if (right is CanConvert) { - val leftArg = left - val rightArg = right - return qnamesEqual(leftArg.toType, rightArg.toType) && - typeSpecifiersEqual(leftArg.toTypeSpecifier, rightArg.toTypeSpecifier) + return qnamesEqual(left.toType, right.toType) && + typeSpecifiersEqual(left.toTypeSpecifier, right.toTypeSpecifier) } return false @@ -1305,10 +1142,8 @@ class SimpleElmEngine { // Convert if (left is Convert) { if (right is Convert) { - val leftArg = left - val rightArg = right - return qnamesEqual(leftArg.toType, rightArg.toType) && - typeSpecifiersEqual(leftArg.toTypeSpecifier, rightArg.toTypeSpecifier) + return qnamesEqual(left.toType, right.toType) && + typeSpecifiersEqual(left.toTypeSpecifier, right.toTypeSpecifier) } return false @@ -1340,10 +1175,8 @@ class SimpleElmEngine { // Is if (left is Is) { if (right is Is) { - val leftArg = left - val rightArg = right - return qnamesEqual(leftArg.isType, rightArg.isType) && - typeSpecifiersEqual(leftArg.isTypeSpecifier, rightArg.isTypeSpecifier) + return qnamesEqual(left.isType, right.isType) && + typeSpecifiersEqual(left.isTypeSpecifier, right.isTypeSpecifier) } return false } @@ -1388,7 +1221,7 @@ class SimpleElmEngine { return true } - fun binaryExpressionsEqual(left: BinaryExpression?, right: BinaryExpression?): Boolean { + private fun binaryExpressionsEqual(left: BinaryExpression?, right: BinaryExpression?): Boolean { if (left == null && right == null) { return true } @@ -1462,7 +1295,10 @@ class SimpleElmEngine { return true } - fun ternaryExpressionsEqual(left: TernaryExpression?, right: TernaryExpression?): Boolean { + private fun ternaryExpressionsEqual( + left: TernaryExpression?, + right: TernaryExpression? + ): Boolean { if (left == null && right == null) { return true } @@ -1483,7 +1319,7 @@ class SimpleElmEngine { return true } - fun naryExpressionsEqual(left: NaryExpression?, right: NaryExpression?): Boolean { + private fun naryExpressionsEqual(left: NaryExpression?, right: NaryExpression?): Boolean { if (left == null && right == null) { return true } @@ -1508,7 +1344,7 @@ class SimpleElmEngine { return false } - fun aggregateExpressionsEqual( + private fun aggregateExpressionsEqual( left: AggregateExpression?, right: AggregateExpression? ): Boolean { @@ -1529,13 +1365,9 @@ class SimpleElmEngine { } // Aggregate - if (left is Aggregate) { - if (right is Aggregate) { - val leftArg = left - val rightArg = right - return expressionsEqual(leftArg.initialValue, rightArg.initialValue) && - expressionsEqual(leftArg.iteration, rightArg.iteration) - } + if (left is Aggregate && right is Aggregate) { + return expressionsEqual(left.initialValue, right.initialValue) && + expressionsEqual(left.iteration, right.iteration) } // Count diff --git a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmClinicalVisitor.kt b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmClinicalVisitor.kt index 3dd75ca33..273325dec 100644 --- a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmClinicalVisitor.kt +++ b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmClinicalVisitor.kt @@ -225,8 +225,8 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica override fun visitRetrieve(elm: Retrieve, context: C): T { var result = visitFields(elm, context) - for (cfe in elm.codeFilter!!) { - val childResult = visitCodeFilterElement(cfe!!, context) + for (cfe in elm.codeFilter) { + val childResult = visitCodeFilterElement(cfe, context) result = aggregateResult(result, childResult) } @@ -238,8 +238,8 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica val childResult = visitExpression(elm.context!!, context) result = aggregateResult(result, childResult) } - for (dfe in elm.dateFilter!!) { - val childResult = visitDateFilterElement(dfe!!, context) + for (dfe in elm.dateFilter) { + val childResult = visitDateFilterElement(dfe, context) result = aggregateResult(result, childResult) } if (elm.dateRange != null) { @@ -252,13 +252,13 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica result = aggregateResult(result, childResult) } - for (ie in elm.include!!) { - val childResult = visitIncludeElement(ie!!, context) + for (ie in elm.include) { + val childResult = visitIncludeElement(ie, context) result = aggregateResult(result, childResult) } - for (ofe in elm.otherFilter!!) { - val childResult = visitOtherFilterElement(ofe!!, context) + for (ofe in elm.otherFilter) { + val childResult = visitOtherFilterElement(ofe, context) result = aggregateResult(result, childResult) } @@ -319,8 +319,8 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica */ override fun visitValueSetDef(elm: ValueSetDef, context: C): T { var result = visitFields(elm, context) - for (codeSystemRef in elm.codeSystem!!) { - val childResult = visitCodeSystemRef(codeSystemRef!!, context) + for (codeSystemRef in elm.codeSystem) { + val childResult = visitCodeSystemRef(codeSystemRef, context) result = aggregateResult(result, childResult) } @@ -355,8 +355,8 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica override fun visitConceptDef(elm: ConceptDef, context: C): T { var result = visitFields(elm, context) - for (cr in elm.code!!) { - val childResult = visitCodeRef(cr!!, context) + for (cr in elm.code) { + val childResult = visitCodeRef(cr, context) result = aggregateResult(result, childResult) } @@ -438,8 +438,8 @@ abstract class BaseElmClinicalVisitor : BaseElmVisitor(), ElmClinica override fun visitConcept(elm: Concept, context: C): T { var result = visitFields(elm, context) - for (c in elm.code!!) { - val childResult = visitCode(c!!, context) + for (c in elm.code) { + val childResult = visitCode(c, context) result = aggregateResult(result, childResult) } diff --git a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmLibraryVisitor.kt b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmLibraryVisitor.kt index 40afea805..90e58ad4d 100644 --- a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmLibraryVisitor.kt +++ b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmLibraryVisitor.kt @@ -36,47 +36,47 @@ abstract class BaseElmLibraryVisitor : override fun visitLibrary(elm: Library, context: C): T { var result = visitFields(elm, context) elm.usings?.def?.forEach { - val childResult = visitUsingDef(it!!, context) + val childResult = visitUsingDef(it, context) result = aggregateResult(result, childResult) } elm.includes?.def?.forEach { - val childResult = visitIncludeDef(it!!, context) + val childResult = visitIncludeDef(it, context) result = aggregateResult(result, childResult) } elm.codeSystems?.def?.forEach { - val childResult = visitCodeSystemDef(it!!, context) + val childResult = visitCodeSystemDef(it, context) result = aggregateResult(result, childResult) } elm.valueSets?.def?.forEach { - val childResult = visitValueSetDef(it!!, context) + val childResult = visitValueSetDef(it, context) result = aggregateResult(result, childResult) } elm.codes?.def?.forEach { - val childResult = visitElement(it!!, context) + val childResult = visitElement(it, context) result = aggregateResult(result, childResult) } elm.concepts?.def?.forEach { - val childResult = visitConceptDef(it!!, context) + val childResult = visitConceptDef(it, context) result = aggregateResult(result, childResult) } elm.parameters?.def?.forEach { - val childResult = visitParameterDef(it!!, context) + val childResult = visitParameterDef(it, context) result = aggregateResult(result, childResult) } elm.contexts?.def?.forEach { - val childResult = visitContextDef(it!!, context) + val childResult = visitContextDef(it, context) result = aggregateResult(result, childResult) } elm.statements?.def?.forEach { - val childResult = visitExpressionDef(it!!, context) + val childResult = visitExpressionDef(it, context) result = aggregateResult(result, childResult) } diff --git a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmVisitor.kt b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmVisitor.kt index e8f44c8c6..6e199228b 100644 --- a/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmVisitor.kt +++ b/Src/java/elm/src/main/kotlin/org/cqframework/cql/elm/visiting/BaseElmVisitor.kt @@ -398,8 +398,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitTupleTypeSpecifier(elm: TupleTypeSpecifier, context: C): T { var result = defaultResult(elm, context) - for (element in elm.element!!) { - val childResult = visitTupleElementDefinition(element!!, context) + for (element in elm.element) { + val childResult = visitTupleElementDefinition(element, context) result = aggregateResult(result, childResult) } return result @@ -416,8 +416,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitChoiceTypeSpecifier(elm: ChoiceTypeSpecifier, context: C): T { var result = defaultResult(elm, context) - for (choice in elm.choice!!) { - val childResult = visitTypeSpecifier(choice!!, context) + for (choice in elm.choice) { + val childResult = visitTypeSpecifier(choice, context) result = aggregateResult(result, childResult) } @@ -711,8 +711,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitFunctionDef(elm: FunctionDef, context: C): T { var result = visitFields(elm, context) - for (operand in elm.operand!!) { - val childResult = visitOperandDef(operand!!, context) + for (operand in elm.operand) { + val childResult = visitOperandDef(operand, context) result = aggregateResult(result, childResult) } @@ -746,13 +746,13 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitFunctionRef(elm: FunctionRef, context: C): T { var result = visitFields(elm, context) - for (element in elm.operand!!) { - val childResult = visitExpression(element!!, context) + for (element in elm.operand) { + val childResult = visitExpression(element, context) result = aggregateResult(result, childResult) } - for (s in elm.signature!!) { - val childResult = visitTypeSpecifier(s!!, context) + for (s in elm.signature) { + val childResult = visitTypeSpecifier(s, context) result = aggregateResult(result, childResult) } @@ -859,8 +859,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitTuple(elm: Tuple, context: C): T { var result = visitFields(elm, context) - for (element in elm.element!!) { - if (element!!.value != null) { + for (element in elm.element) { + if (element.value != null) { val childResult = visitExpression(element.value!!, context) result = aggregateResult(result, childResult) } @@ -895,8 +895,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitInstance(elm: Instance, context: C): T { var result = visitFields(elm, context) - for (element in elm.element!!) { - if (element!!.value != null) { + for (element in elm.element) { + if (element.value != null) { val childResult = visitExpression(element.value!!, context) result = aggregateResult(result, childResult) } @@ -965,8 +965,8 @@ abstract class BaseElmVisitor : ElmVisitor { result = aggregateResult(result, childResult) } - for (element in elm.element!!) { - val childResult = visitExpression(element!!, context) + for (element in elm.element) { + val childResult = visitExpression(element, context) result = aggregateResult(result, childResult) } @@ -1091,8 +1091,8 @@ abstract class BaseElmVisitor : ElmVisitor { result = aggregateResult(result, childResult) } - for (ci in elm.caseItem!!) { - val childResult = visitCaseItem(ci!!, context) + for (ci in elm.caseItem) { + val childResult = visitCaseItem(ci, context) result = aggregateResult(result, childResult) } @@ -2903,8 +2903,8 @@ abstract class BaseElmVisitor : ElmVisitor { val childResult = visitExpression(elm.source!!, context) result = aggregateResult(result, childResult) } - for (sbi in elm.by!!) { - val childResult = visitSortByItem(sbi!!, context) + for (sbi in elm.by) { + val childResult = visitSortByItem(sbi, context) result = aggregateResult(result, childResult) } @@ -3410,8 +3410,8 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitSortClause(elm: SortClause, context: C): T { var result = visitFields(elm, context) - for (sbi in elm.by!!) { - val childResult = visitSortByItem(sbi!!, context) + for (sbi in elm.by) { + val childResult = visitSortByItem(sbi, context) result = aggregateResult(result, childResult) } @@ -3470,17 +3470,17 @@ abstract class BaseElmVisitor : ElmVisitor { override fun visitQuery(elm: Query, context: C): T { var result = visitFields(elm, context) - for (source in elm.source!!) { - val childResult = visitAliasedQuerySource(source!!, context) + for (source in elm.source) { + val childResult = visitAliasedQuerySource(source, context) result = aggregateResult(result, childResult) } - for (let in elm.let!!) { - val childResult = visitLetClause(let!!, context) + for (let in elm.let) { + val childResult = visitLetClause(let, context) result = aggregateResult(result, childResult) } - for (r in elm.relationship!!) { - val childResult = visitRelationshipClause(r!!, context) + for (r in elm.relationship) { + val childResult = visitRelationshipClause(r, context) result = aggregateResult(result, childResult) } @@ -3570,8 +3570,8 @@ abstract class BaseElmVisitor : ElmVisitor { result = aggregateResult(result, childResult) } - for (s in elm.signature!!) { - val childResult = visitTypeSpecifier(s!!, context) + for (s in elm.signature) { + val childResult = visitTypeSpecifier(s, context) result = aggregateResult(result, childResult) } @@ -3624,8 +3624,8 @@ abstract class BaseElmVisitor : ElmVisitor { protected fun visitFields(elm: NaryExpression, context: C): T { var result = visitFields(elm as OperatorExpression, context) - for (e in elm.operand!!) { - val childResult = visitExpression(e!!, context) + for (e in elm.operand) { + val childResult = visitExpression(e, context) result = aggregateResult(result, childResult) } @@ -3642,8 +3642,8 @@ abstract class BaseElmVisitor : ElmVisitor { protected fun visitFields(elm: TernaryExpression, context: C): T { var result = visitFields(elm as OperatorExpression, context) - for (s in elm.operand!!) { - val childResult = visitExpression(s!!, context) + for (s in elm.operand) { + val childResult = visitExpression(s, context) result = aggregateResult(result, childResult) } @@ -3660,8 +3660,8 @@ abstract class BaseElmVisitor : ElmVisitor { protected fun visitFields(elm: OperatorExpression, context: C): T { var result = visitFields(elm as Expression, context) - for (s in elm.signature!!) { - val childResult = visitTypeSpecifier(s!!, context) + for (s in elm.signature) { + val childResult = visitTypeSpecifier(s, context) result = aggregateResult(result, childResult) } @@ -3678,8 +3678,8 @@ abstract class BaseElmVisitor : ElmVisitor { protected open fun visitFields(elm: BinaryExpression, context: C): T { var result = visitFields(elm as OperatorExpression, context) - for (e in elm.operand!!) { - val childResult = visitExpression(e!!, context) + for (e in elm.operand) { + val childResult = visitExpression(e, context) result = aggregateResult(result, childResult) } diff --git a/Src/java/model/src/main/kotlin/org/hl7/cql/model/ClassTypeElement.kt b/Src/java/model/src/main/kotlin/org/hl7/cql/model/ClassTypeElement.kt index c0e08c0b2..b4d3070df 100644 --- a/Src/java/model/src/main/kotlin/org/hl7/cql/model/ClassTypeElement.kt +++ b/Src/java/model/src/main/kotlin/org/hl7/cql/model/ClassTypeElement.kt @@ -1,7 +1,5 @@ package org.hl7.cql.model -import java.util.* - data class ClassTypeElement( val name: String, val type: DataType, @@ -21,12 +19,11 @@ data class ClassTypeElement( this.name == that.name && type.isSuperTypeOf(that.type) override fun toString(): String { - return "$name:$type$%s%s%s" - .format( - Locale.US, - if (this.prohibited) " (prohibited)" else "", - if (this.oneBased) " (one-based)" else "", - if (this.target != null) " (target: " + this.target + ")" else "" - ) + return """$name:$type + |${if (this.prohibited) " (prohibited)" else ""} + |${if (this.oneBased) " (one-based)" else ""} + |${if (this.target != null) " (target: " + this.target + ")" else ""}""" + .trimMargin() + .replace("\n", "") } } diff --git a/Src/java/model/src/main/kotlin/org/hl7/cql/model/NamespaceManager.kt b/Src/java/model/src/main/kotlin/org/hl7/cql/model/NamespaceManager.kt index 676539a9a..d9a78d02d 100644 --- a/Src/java/model/src/main/kotlin/org/hl7/cql/model/NamespaceManager.kt +++ b/Src/java/model/src/main/kotlin/org/hl7/cql/model/NamespaceManager.kt @@ -20,7 +20,7 @@ class NamespaceManager { addNamespace(namespaceInfo.name, namespaceInfo.uri) } - fun addNamespace(namespaceName: String, namespaceUri: String) { + private fun addNamespace(namespaceName: String, namespaceUri: String) { require(namespaceName.isNotEmpty()) { "namespaceName is required" } require(namespaceUri.isNotEmpty()) { "namespaceUri is required" } check(!namespaces.containsKey(namespaceName)) { diff --git a/Src/java/model/src/main/kotlin/org/hl7/cql/model/TupleTypeElement.kt b/Src/java/model/src/main/kotlin/org/hl7/cql/model/TupleTypeElement.kt index aee2da51d..546e6b0bd 100644 --- a/Src/java/model/src/main/kotlin/org/hl7/cql/model/TupleTypeElement.kt +++ b/Src/java/model/src/main/kotlin/org/hl7/cql/model/TupleTypeElement.kt @@ -15,7 +15,7 @@ data class TupleTypeElement( fun isSuperTypeOf(that: TupleTypeElement): Boolean = this.name == that.name && type.isSuperTypeOf(that.type) - override fun toString(): String = "${name}:${type}" + override fun toString(): String = "$name:$type" - fun toLabel(): String = "${name}: ${type}" + fun toLabel(): String = "$name: $type" }