Merge branch 'master' of https://github.com/hapifhir/org.hl7.fhir.core into HandleExtraProfiles

This commit is contained in:
Lloyd McKenzie 2024-06-02 13:55:47 -06:00
commit 4d07d5d1a3
302 changed files with 129796 additions and 20427 deletions

View File

@ -0,0 +1,34 @@
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#define figure and axes
fig, ax = plt.subplots(1,1)
#hide the axes
fig.patch.set_visible(False)
ax.axis('off')
ax.axis('tight')
#read data
df = pd.read_csv('i18n-coverage.csv')
#create table
table = ax.table(cellText=df.values, colLabels=df.columns, loc='center')
table.scale(1, 4)
table.auto_set_font_size(False)
table.set_fontsize(14)
fig.tight_layout()
fig.set_figheight(2)
fig.set_figwidth(4)
ax.set_title('Internationalization Phrase Coverage by Locale')
fig = plt.gcf()
plt.savefig('i18n-coverage-table.png',
bbox_inches='tight',
dpi=150
)

View File

@ -25,6 +25,6 @@ jobs:
id: bidi_check
uses: HL7/bidi-checker-action@v1.9
env:
IGNORE: dummy-package.tgz$
IGNORE: i18n-coverage-table\.png$|dummy-package.tgz$
- name: Get the output time
run: echo "The time was ${{ steps.bidi_check.outputs.time }}"

View File

@ -22,4 +22,4 @@
# License string includes nested brackets, causing parser breakage, but is a valid BSD license.
(BSD 3-Clause "New" or "Revised" License (BSD-3-Clause)) abego TreeLayout Core (org.abego.treelayout:org.abego.treelayout.core:1.0.3 - http://treelayout.sourceforge.net)
# License name includes brackets (javax.xml.bind)
(The Apache Software License, Version 2.0) Jackson module: Old JAXB Annotations (javax.xml.bind) (com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.16.0 - https://github.com/FasterXML/jackson-modules-base)
(The Apache Software License, Version 2.0) Jackson module: Old JAXB Annotations (javax.xml.bind) (com.fasterxml.jackson.module:jackson-module-jaxb-annotations:2.17.0 - https://github.com/FasterXML/jackson-modules-base)

2
.gitignore vendored
View File

@ -309,3 +309,5 @@ local.properties
org.hl7.fhir.r5/var/lib/.fhir/packages/
org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/DebugUtilities.java
org.hl7.fhir.utilities/src/main/resources copy/

View File

@ -204,6 +204,15 @@ compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r4', version: '(l
compile group: 'ca.uhn.hapi.fhir', name: 'hapi-fhir-structures-r5', version: '(latest version)'
```
## Internationalization
This project implements internationalization for its user tools and utilities for several locales using a combination of [GNU PO](https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html) and [Java Properties](https://docs.oracle.com/javase/tutorial/i18n/resbundle/propfile.html) files.
Translation from the core library's original English locale to other supported locales is an ongoing process. The current level of coverage is calculated by the number of translated phrases, and can be viewed in the following figure:
<p align="center">
<img alt="Table of Internationalization Coverage" src="/i18n-coverage-table.png" width="300">
</p>
## CI/CD
All integration and delivery done on Azure pipelines. Azure project can be viewed [here][Link-AzureProject].

View File

@ -1,38 +1,7 @@
## Validator Changes
* Validate fixed/pattern values are not changed in derived profiles
* Fix NPE validating some profiles
* FHIRPath validation: consider sub-extensions when checking extension($) use
* Fix validation of concept maps containing SCT
* Preserve message id from terminology service so editors can use it to remove hints and warnings
* no changes
## Other code changes
* Fix ConceptMap.group.target conversion from R3 to R5
* Fix NPE in list renderer
* fix bug showing 'required' instead of 'current' rendering additional bindings
* Fix bad references generating narratives in bundles
* Fix bug showing extension binding twice
* Various improvements to structure map validation to support cross-version mappings
* Add rendering for UsageContext and ContactDetail
* Fix broken link in xver IG for R2
* Fix bug rendering resources in Parameters resource
* Not-pretty xhtml gets line breaks before block tags to keep line length down (work around a jekyll issue)
* Improved ConceptMap rendering for cross-version IG
* Handle xhtml:div type for old FHIR version
* FML: strip '-' from rules names when parsing
* Update FML parsers to accept R5 metadata in R4 FML format
* Break out helper classes for Terminology Service Tester
## Security
* Add start of security notes
* Start moving file access to all go through ManagedFileAccess
## WHO Internationalization work:
* Add library to parse IETF Language definitions
* Move message translations to .po files as the master source & write convertor
* Much work making rendering i18n-able
* i18n for Patient renderer
* Refactor language handling in R5 renderers
* no changes

BIN
i18n-coverage-table.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

5
i18n-coverage.csv Normal file
View File

@ -0,0 +1,5 @@
Locale,Coverage #,Coverage %
de,835,42%
es,718,36%
ja,906,46%
nl,1376,69%
1 Locale Coverage # Coverage %
2 de 835 42%
3 es 718 36%
4 ja 906 46%
5 nl 1376 69%

View File

@ -125,4 +125,75 @@ jobs:
jdkArchitectureOption: 'x64'
options: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER) --settings $(Agent.TempDirectory)/settings.xml -pl "!org.hl7.fhir.report, !org.hl7.fhir.validation.cli" -Dmaven.test.skip -DdeployToGitHub'
mavenOptions: '-Xmx768m -Dmaven.resolver.transport=wagon'
publishJUnitResults: false
publishJUnitResults: false
- job: generate_i8n_csv_png_and_commit
dependsOn: setup
#- ${{ each module in parameters.modulesToTest.modules }}:
# - ubuntu_java_11_${{ module }}
variables:
# Normally this test outputs to console. This variable appears as env param
# I18N_COVERAGE_FILE, which tells the test to write the output to a file
# instead.
- name: i18n.coverage.file
value: ../i18n-coverage.csv
pool:
vmImage: "ubuntu-latest"
steps:
# For creating the snapshot release with maven, we need to build a fake settings.xml for it to read from.
# This is done for the master branch merges only.
- task: Cache@2
displayName: Cache maven artifacts
inputs:
key: maven | $(Build.BuildId) | artifacts
path: $(MAVEN_CACHE_FOLDER)
- template: cache-target-tasks-template.yml
parameters:
modules:
${{ parameters.modulesToCache.modules }}
- bash: |
git config --global user.email $(GIT_USER_EMAIL)
git config --global user.name $(GIT_USER_NAME)
displayName: 'Set up git'
# Install pip packages
- bash: |
pip3 install matplotlib
pip3 install numpy
pip3 install pandas
displayName: 'Set up python packages'
- task: Maven@3
inputs:
mavenPomFile: '$(System.DefaultWorkingDirectory)/pom.xml'
options: '-Dmaven.repo.local=$(MAVEN_CACHE_FOLDER) -pl org.hl7.fhir.utilities '
mavenOptions: '-Dtest=I18nCoverageTest#testPhraseCoverage'
javaHomeOption: 'JDKVersion'
jdkVersionOption: '1.11'
jdkArchitectureOption: 'x64'
goals: 'surefire:test'
displayName: 'Run i18n coverage test to generate csv'
- task: PythonScript@0
inputs:
scriptSource: 'filePath'
scriptPath: .azure/i18n-coverage-table/generate-i18n-coverage-table.py
arguments:
displayName: 'Make png table from coverage test csv'
# Verify png file generation
- bash: |
ls -l ./i18n-coverage-table.png
- bash: |
git fetch
git checkout master
git status
git add ./i18n-coverage.csv
git add ./i18n-coverage-table.png
git commit . -m "Updating i18n-coverage csv and png table ***NO_CI***"
git push https://$(GIT_PAT)@github.com/hapifhir/org.hl7.fhir.core.git
displayName: 'Push updated csv and plot to git.'

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -14,11 +14,11 @@ import javax.xml.parsers.ParserConfigurationException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.parser.JsonParser;
@ -233,8 +233,8 @@ public class PackageVisitor {
JsonObject manifest = JsonParser.parseObjectFromUrl(repo+"/package.manifest.json");
File co = ManagedFileAccess.file(Utilities.path(cache, pid+"."+manifest.asString("date")+".tgz"));
if (!co.exists()) {
SimpleHTTPClient fetcher = new SimpleHTTPClient();
HTTPResult res = fetcher.get(repo+"/package.tgz?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(repo+"/package.tgz?nocache=" + System.currentTimeMillis());
res.checkThrowException();
TextFile.bytesToFile(res.getContent(), co);
}
@ -330,8 +330,8 @@ public class PackageVisitor {
private void processFeed(Set<String> list, String str) throws IOException, ParserConfigurationException, SAXException {
System.out.println("Feed "+str);
try {
SimpleHTTPClient fetcher = new SimpleHTTPClient();
HTTPResult res = fetcher.get(str+"?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(str+"?nocache=" + System.currentTimeMillis());
res.checkThrowException();
Document xml = XMLUtil.parseToDom(res.getContent());
for (Element channel : XMLUtil.getNamedChildren(xml.getDocumentElement(), "channel")) {

View File

@ -5,6 +5,7 @@ import java.util.stream.Collectors;
import org.hl7.fhir.convertors.VersionConvertorConstants;
import org.hl7.fhir.convertors.context.ConversionContext30_50;
import org.hl7.fhir.convertors.context.ConversionContext30_50;
import org.hl7.fhir.convertors.conv30_50.VersionConvertor_30_50;
import org.hl7.fhir.convertors.conv30_50.datatypes30_50.complextypes30_50.Coding30_50;
import org.hl7.fhir.convertors.conv30_50.datatypes30_50.primitivetypes30_50.Boolean30_50;
@ -17,9 +18,17 @@ import org.hl7.fhir.convertors.conv30_50.datatypes30_50.primitivetypes30_50.Unsi
import org.hl7.fhir.convertors.conv30_50.datatypes30_50.primitivetypes30_50.Uri30_50;
import org.hl7.fhir.convertors.conv30_50.resources30_50.Enumerations30_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.dstu3.model.BooleanType;
import org.hl7.fhir.dstu3.model.Extension;
import org.hl7.fhir.dstu3.model.MarkdownType;
import org.hl7.fhir.dstu3.model.StringType;
import org.hl7.fhir.dstu3.model.UriType;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.UsageContext;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.utilities.Utilities;
public class ElementDefinition30_50 {
@ -643,7 +652,8 @@ public class ElementDefinition30_50 {
public static ElementDefinition.ElementDefinitionBindingComponent convertElementDefinitionBindingComponent(org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionBindingComponent src) throws FHIRException {
if (src == null) return null;
ElementDefinition.ElementDefinitionBindingComponent tgt = new ElementDefinition.ElementDefinitionBindingComponent();
ConversionContext30_50.INSTANCE.getVersionConvertor_30_50().copyElement(src, tgt, VersionConvertor_30_50.EXT_SRC_TYPE);
ConversionContext30_50.INSTANCE.getVersionConvertor_30_50().copyElement(src, tgt, VersionConvertor_30_50.EXT_SRC_TYPE,
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional");
if (src.hasStrength()) tgt.setStrengthElement(Enumerations30_50.convertBindingStrength(src.getStrengthElement()));
if (src.hasDescription()) tgt.setDescriptionElement(String30_50.convertStringToMarkdown(src.getDescriptionElement()));
if (src.hasValueSet()) {
@ -657,6 +667,9 @@ public class ElementDefinition30_50 {
}
tgt.setValueSet(VersionConvertorConstants.refToVS(tgt.getValueSet()));
}
for (org.hl7.fhir.dstu3.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional")) {
tgt.addAdditional(convertAdditional(ext));
}
return tgt;
}
@ -680,9 +693,64 @@ public class ElementDefinition30_50 {
else tgt.setValueSet(new org.hl7.fhir.dstu3.model.Reference(src.getValueSet()));
}
}
for (ElementDefinitionBindingAdditionalComponent ab : src.getAdditional()) {
tgt.addExtension(convertAdditional(ab));
}
return tgt;
}
private static ElementDefinitionBindingAdditionalComponent convertAdditional(Extension src) {
if (src == null) return null;
ElementDefinitionBindingAdditionalComponent tgt = new ElementDefinitionBindingAdditionalComponent();
ConversionContext30_50.INSTANCE.getVersionConvertor_30_50().copyElement(src, tgt, "valueSet", "purpose", "documentation", "shortDoco", "usage", "any");
if (src.hasExtension("purpose")) {
tgt.getPurposeElement().setValueAsString(src.getExtensionByUrl("purpose").getValue().primitiveValue());
}
if (src.hasExtension("valueSet")) {
tgt.setValueSetElement(Uri30_50.convertCanonical((UriType) src.getExtensionByUrl("valueSet").getValue()));
}
if (src.hasExtension("documentation")) {
tgt.setDocumentationElement(MarkDown30_50.convertMarkdown((MarkdownType) src.getExtensionByUrl("documentation").getValue()));
}
if (src.hasExtension("shortDoco")) {
tgt.setShortDocoElement(String30_50.convertString((StringType) src.getExtensionByUrl("shortDoco").getValue()));
}
for (Extension t : src.getExtensionsByUrl("usage")) {
tgt.addUsage(UsageContext30_50.convertUsageContext((org.hl7.fhir.dstu3.model.UsageContext) t.getValue()));
}
if (src.hasExtension("any")) {
tgt.setAnyElement(Boolean30_50.convertBoolean((BooleanType) src.getExtensionByUrl("any").getValue()));
}
return tgt;
}
private static Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
if (src == null) return null;
Extension tgt = new Extension();
ConversionContext30_50.INSTANCE.getVersionConvertor_30_50().copyElement(src, tgt);
if (src.hasPurpose()) {
tgt.addExtension(new Extension("purpose", new org.hl7.fhir.dstu3.model.CodeType(src.getPurposeElement().primitiveValue())));
}
if (src.hasValueSet()) {
tgt.addExtension(new Extension("valueSet", Uri30_50.convertCanonical(src.getValueSetElement())));
}
if (src.hasDocumentation()) {
tgt.addExtension(new Extension("documentation", MarkDown30_50.convertMarkdown(src.getDocumentationElement())));
}
if (src.hasShortDoco()) {
tgt.addExtension(new Extension("shortDoco", String30_50.convertString(src.getShortDocoElement())));
}
for (UsageContext t : src.getUsage()) {
tgt.addExtension(new Extension("usage", UsageContext30_50.convertUsageContext(t)));
}
if (src.hasAny()) {
tgt.addExtension(new Extension("any", Boolean30_50.convertBoolean(src.getAnyElement())));
}
return tgt;
}
public static ElementDefinition.ElementDefinitionMappingComponent convertElementDefinitionMappingComponent(org.hl7.fhir.dstu3.model.ElementDefinition.ElementDefinitionMappingComponent src) throws FHIRException {
if (src == null) return null;
ElementDefinition.ElementDefinitionMappingComponent tgt = new ElementDefinition.ElementDefinitionMappingComponent();

View File

@ -5,6 +5,7 @@ import java.util.stream.Collectors;
import org.hl7.fhir.convertors.context.ConversionContext40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.BackboneElement40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.general40_50.Coding40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.metadata40_50.UsageContext40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Boolean40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Canonical40_50;
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Code40_50;
@ -16,12 +17,22 @@ import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.UnsignedI
import org.hl7.fhir.convertors.conv40_50.datatypes40_50.primitive40_50.Uri40_50;
import org.hl7.fhir.convertors.conv40_50.resources40_50.Enumerations40_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.model.BooleanType;
import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.Extension;
import org.hl7.fhir.r4.model.MarkdownType;
import org.hl7.fhir.r4.model.StringType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.UsageContext;
public class ElementDefinition40_50 {
public static org.hl7.fhir.r5.model.ElementDefinition convertElementDefinition(org.hl7.fhir.r4.model.ElementDefinition src) throws FHIRException {
if (src == null) return null;
org.hl7.fhir.r5.model.ElementDefinition tgt = new org.hl7.fhir.r5.model.ElementDefinition();
BackboneElement40_50.copyBackboneElement(src, tgt, "http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.mustHaveValue", "http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.valueAlternatives");
BackboneElement40_50.copyBackboneElement(src, tgt,
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.mustHaveValue",
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.valueAlternatives");
if (src.hasPath()) tgt.setPathElement(String40_50.convertString(src.getPathElement()));
tgt.setRepresentation(src.getRepresentation().stream().map(ElementDefinition40_50::convertPropertyRepresentation).collect(Collectors.toList()));
if (src.hasSliceName()) tgt.setSliceNameElement(String40_50.convertString(src.getSliceNameElement()));
@ -604,10 +615,66 @@ public class ElementDefinition40_50 {
public static org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent convertElementDefinitionBindingComponent(org.hl7.fhir.r4.model.ElementDefinition.ElementDefinitionBindingComponent src) throws FHIRException {
if (src == null) return null;
org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent tgt = new org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent();
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt);
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt,
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional");
if (src.hasStrength()) tgt.setStrengthElement(Enumerations40_50.convertBindingStrength(src.getStrengthElement()));
if (src.hasDescription()) tgt.setDescriptionElement(String40_50.convertStringToMarkdown(src.getDescriptionElement()));
if (src.hasValueSet()) tgt.setValueSetElement(Canonical40_50.convertCanonical(src.getValueSetElement()));
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional")) {
tgt.addAdditional(convertAdditional(ext));
}
return tgt;
}
private static ElementDefinitionBindingAdditionalComponent convertAdditional(Extension src) {
if (src == null) return null;
ElementDefinitionBindingAdditionalComponent tgt = new ElementDefinitionBindingAdditionalComponent();
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt, "valueSet", "purpose", "documentation", "shortDoco", "usage", "any");
if (src.hasExtension("purpose")) {
tgt.getPurposeElement().setValueAsString(src.getExtensionByUrl("purpose").getValue().primitiveValue());
}
if (src.hasExtension("valueSet")) {
tgt.setValueSetElement(Canonical40_50.convertCanonical((CanonicalType) src.getExtensionByUrl("valueSet").getValue()));
}
if (src.hasExtension("documentation")) {
tgt.setDocumentationElement(MarkDown40_50.convertMarkdown((MarkdownType) src.getExtensionByUrl("documentation").getValue()));
}
if (src.hasExtension("shortDoco")) {
tgt.setShortDocoElement(String40_50.convertString((StringType) src.getExtensionByUrl("shortDoco").getValue()));
}
for (Extension t : src.getExtensionsByUrl("usage")) {
tgt.addUsage(UsageContext40_50.convertUsageContext((org.hl7.fhir.r4.model.UsageContext) t.getValue()));
}
if (src.hasExtension("any")) {
tgt.setAnyElement(Boolean40_50.convertBoolean((BooleanType) src.getExtensionByUrl("any").getValue()));
}
return tgt;
}
private static Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
if (src == null) return null;
Extension tgt = new Extension();
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt);
if (src.hasPurpose()) {
tgt.addExtension(new Extension("purpose", new CodeType(src.getPurposeElement().primitiveValue())));
}
if (src.hasValueSet()) {
tgt.addExtension(new Extension("valueSet", Canonical40_50.convertCanonical(src.getValueSetElement())));
}
if (src.hasDocumentation()) {
tgt.addExtension(new Extension("documentation", MarkDown40_50.convertMarkdown(src.getDocumentationElement())));
}
if (src.hasShortDoco()) {
tgt.addExtension(new Extension("shortDoco", String40_50.convertString(src.getShortDocoElement())));
}
for (UsageContext t : src.getUsage()) {
tgt.addExtension(new Extension("usage", UsageContext40_50.convertUsageContext(t)));
}
if (src.hasAny()) {
tgt.addExtension(new Extension("any", Boolean40_50.convertBoolean(src.getAnyElement())));
}
return tgt;
}
@ -618,6 +685,9 @@ public class ElementDefinition40_50 {
if (src.hasStrength()) tgt.setStrengthElement(Enumerations40_50.convertBindingStrength(src.getStrengthElement()));
if (src.hasDescription()) tgt.setDescriptionElement(String40_50.convertString(src.getDescriptionElement()));
if (src.hasValueSet()) tgt.setValueSetElement(Canonical40_50.convertCanonical(src.getValueSetElement()));
for (ElementDefinitionBindingAdditionalComponent ab : src.getAdditional()) {
tgt.addExtension(convertAdditional(ab));
}
return tgt;
}

View File

@ -3,6 +3,12 @@ package org.hl7.fhir.convertors.conv43_50.datatypes43_50.special43_50;
import java.util.stream.Collectors;
import org.hl7.fhir.convertors.context.ConversionContext43_50;
import org.hl7.fhir.convertors.context.ConversionContext43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.metadata43_50.UsageContext43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.Boolean43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.Canonical43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.MarkDown43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.String43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.BackboneElement43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.general43_50.Coding43_50;
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.Boolean43_50;
@ -16,6 +22,14 @@ import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.UnsignedI
import org.hl7.fhir.convertors.conv43_50.datatypes43_50.primitive43_50.Uri43_50;
import org.hl7.fhir.convertors.conv43_50.resources43_50.Enumerations43_50;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4b.model.BooleanType;
import org.hl7.fhir.r4b.model.CanonicalType;
import org.hl7.fhir.r4b.model.Extension;
import org.hl7.fhir.r4b.model.MarkdownType;
import org.hl7.fhir.r4b.model.StringType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.UsageContext;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
public class ElementDefinition43_50 {
public static org.hl7.fhir.r5.model.ElementDefinition convertElementDefinition(org.hl7.fhir.r4b.model.ElementDefinition src) throws FHIRException {
@ -605,10 +619,14 @@ public class ElementDefinition43_50 {
public static org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent convertElementDefinitionBindingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionBindingComponent src) throws FHIRException {
if (src == null) return null;
org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent tgt = new org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent();
ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().copyElement(src, tgt);
ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().copyElement(src, tgt,
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional");
if (src.hasStrength()) tgt.setStrengthElement(Enumerations43_50.convertBindingStrength(src.getStrengthElement()));
if (src.hasDescription()) tgt.setDescriptionElement(String43_50.convertStringToMarkdown(src.getDescriptionElement()));
if (src.hasValueSet()) tgt.setValueSetElement(Canonical43_50.convertCanonical(src.getValueSetElement()));
for (org.hl7.fhir.r4b.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional")) {
tgt.addAdditional(convertAdditional(ext));
}
return tgt;
}
@ -619,9 +637,64 @@ public class ElementDefinition43_50 {
if (src.hasStrength()) tgt.setStrengthElement(Enumerations43_50.convertBindingStrength(src.getStrengthElement()));
if (src.hasDescription()) tgt.setDescriptionElement(String43_50.convertString(src.getDescriptionElement()));
if (src.hasValueSet()) tgt.setValueSetElement(Canonical43_50.convertCanonical(src.getValueSetElement()));
for (ElementDefinitionBindingAdditionalComponent ab : src.getAdditional()) {
tgt.addExtension(convertAdditional(ab));
}
return tgt;
}
private static ElementDefinitionBindingAdditionalComponent convertAdditional(Extension src) {
if (src == null) return null;
ElementDefinitionBindingAdditionalComponent tgt = new ElementDefinitionBindingAdditionalComponent();
ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().copyElement(src, tgt, "valueSet", "purpose", "documentation", "shortDoco", "usage", "any");
if (src.hasExtension("purpose")) {
tgt.getPurposeElement().setValueAsString(src.getExtensionByUrl("purpose").getValue().primitiveValue());
}
if (src.hasExtension("valueSet")) {
tgt.setValueSetElement(Canonical43_50.convertCanonical((CanonicalType) src.getExtensionByUrl("valueSet").getValue()));
}
if (src.hasExtension("documentation")) {
tgt.setDocumentationElement(MarkDown43_50.convertMarkdown((MarkdownType) src.getExtensionByUrl("documentation").getValue()));
}
if (src.hasExtension("shortDoco")) {
tgt.setShortDocoElement(String43_50.convertString((StringType) src.getExtensionByUrl("shortDoco").getValue()));
}
for (Extension t : src.getExtensionsByUrl("usage")) {
tgt.addUsage(UsageContext43_50.convertUsageContext((org.hl7.fhir.r4b.model.UsageContext) t.getValue()));
}
if (src.hasExtension("any")) {
tgt.setAnyElement(Boolean43_50.convertBoolean((BooleanType) src.getExtensionByUrl("any").getValue()));
}
return tgt;
}
private static Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
if (src == null) return null;
Extension tgt = new Extension();
ConversionContext43_50.INSTANCE.getVersionConvertor_43_50().copyElement(src, tgt);
if (src.hasPurpose()) {
tgt.addExtension(new Extension("purpose", new CodeType(src.getPurposeElement().primitiveValue())));
}
if (src.hasValueSet()) {
tgt.addExtension(new Extension("valueSet", Canonical43_50.convertCanonical(src.getValueSetElement())));
}
if (src.hasDocumentation()) {
tgt.addExtension(new Extension("documentation", MarkDown43_50.convertMarkdown(src.getDocumentationElement())));
}
if (src.hasShortDoco()) {
tgt.addExtension(new Extension("shortDoco", String43_50.convertString(src.getShortDocoElement())));
}
for (UsageContext t : src.getUsage()) {
tgt.addExtension(new Extension("usage", UsageContext43_50.convertUsageContext(t)));
}
if (src.hasAny()) {
tgt.addExtension(new Extension("any", Boolean43_50.convertBoolean(src.getAnyElement())));
}
return tgt;
}
public static org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent convertElementDefinitionMappingComponent(org.hl7.fhir.r4b.model.ElementDefinition.ElementDefinitionMappingComponent src) throws FHIRException {
if (src == null) return null;
org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent tgt = new org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionMappingComponent();

View File

@ -37,12 +37,14 @@ import java.util.UUID;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_40_50;
import org.hl7.fhir.convertors.advisors.impl.BaseAdvisor_43_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_43_50;
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r4.formats.JsonParser;
import org.hl7.fhir.r4.formats.XmlParser;
import org.hl7.fhir.r4.model.Resource;
import org.hl7.fhir.r4b.formats.JsonParser;
import org.hl7.fhir.r4b.formats.XmlParser;
import org.hl7.fhir.r4b.model.Resource;
import org.hl7.fhir.r5.conformance.StructureDefinitionHacker;
import org.hl7.fhir.r5.context.IContextResourceLoader;
import org.hl7.fhir.r5.model.Bundle;
@ -57,7 +59,7 @@ import org.hl7.fhir.utilities.VersionUtilities;
public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoader {
private final BaseAdvisor_40_50 advisor = new BaseAdvisor_40_50();
private final BaseAdvisor_43_50 advisor = new BaseAdvisor_43_50();
private String version;
public R4BToR5Loader(List<String> types, ILoaderKnowledgeProviderR5 lkp, String version) { // might be 4B
@ -72,7 +74,7 @@ public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoade
r4 = new JsonParser().parse(stream);
else
r4 = new XmlParser().parse(stream);
org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4, advisor);
org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(r4, advisor);
Bundle b;
if (r5 instanceof Bundle)
@ -116,7 +118,7 @@ public class R4BToR5Loader extends BaseLoaderR5 implements IContextResourceLoade
r4 = new JsonParser().parse(stream);
else
r4 = new XmlParser().parse(stream);
org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_40_50.convertResource(r4);
org.hl7.fhir.r5.model.Resource r5 = VersionConvertorFactory_43_50.convertResource(r4);
setPath(r5);
if (!advisor.getCslist().isEmpty()) {

View File

@ -40,11 +40,11 @@ import javax.xml.parsers.DocumentBuilderFactory;
import org.hl7.fhir.convertors.misc.adl.ADLImporter;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.xml.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@ -125,8 +125,8 @@ public class CKMImporter {
}
private Document loadXml(String address) throws Exception {
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(address, "application/xml");
HTTPResult res = ManagedWebAccess.get(address, "application/xml");
res.checkThrowException();
InputStream xml = new ByteArrayInputStream(res.getContent());

View File

@ -25,10 +25,10 @@ import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r4.model.ValueSet.FilterOperator;
import org.hl7.fhir.r4.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r4.utils.ToolingExtensions;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonObject;
import org.hl7.fhir.utilities.json.parser.JsonParser;
@ -380,7 +380,7 @@ public class ICD11Generator {
cs.setPublisher("WHO");
cs.setCopyright("Consult WHO For terms of use");
cs.setCaseSensitive(true);
cs.setHierarchyMeaning(CodeSystemHierarchyMeaning.ISA); // though we aren't going to have a heirarchy
cs.setHierarchyMeaning(CodeSystemHierarchyMeaning.ISA); // though we aren't going to have a hierarchy
// cs.setCompositional(true);
// cs.setVersionNeeded(true);
cs.setValueSet("http://id.who.int/icd11/ValueSet/all-foundation");
@ -395,10 +395,7 @@ public class ICD11Generator {
private JsonObject fetchJson(String source) throws IOException {
SimpleHTTPClient http = new SimpleHTTPClient();
http.addHeader("API-Version", "v2");
http.addHeader("Accept-Language", "en");
HTTPResult res = http.get(source, "application/json");
HTTPResult res = ManagedWebAccess.builder().withAccept("application/json").withHeader("API-Version", "v2").withHeader("Accept-Language", "en").get(source);
res.checkThrowException();
return JsonParser.parseObject(res.getContent());
}

View File

@ -0,0 +1,56 @@
package org.hl7.fhir.convertors.misc;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.DirectoryVisitor;
import org.hl7.fhir.utilities.filesystem.DirectoryVisitor.IDirectoryVisitorImplementation;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.npm.NpmPackage;
public class SpecMapUnpacker {
public static void main(String[] args) throws IOException {
new SpecMapUnpacker().unpack(args[0]);
}
public class SpecMapScanner implements IDirectoryVisitorImplementation {
@Override
public boolean enterDirectory(File directory) throws IOException {
return true;
}
@Override
public boolean visitFile(File file) throws IOException {
System.out.println("Look at "+file.getAbsolutePath());
try {
NpmPackage npm = NpmPackage.fromPackage(ManagedFileAccess.inStream(file));
if (npm.hasFile("other", "spec.internals")) {
byte[] cnt = TextFile.streamToBytes(npm.load("other", "spec.internals"));
TextFile.bytesToFile(cnt, Utilities.path(Utilities.getDirectoryForFile(file.getAbsolutePath()), "page-map.json"));
System.out.println(" ...extracted");
return true;
} else {
System.out.println(" ...not found");
return false;
}
} catch (Exception e) {
System.out.println(" ...error: "+e.getMessage());
return false;
}
}
}
private void unpack(String path) throws IOException {
System.out.println("Scanning "+path);
int count = DirectoryVisitor.visitDirectory(new SpecMapScanner(), path, "tgz");
System.out.println("Done. "+count+" files extracted");
}
}

View File

@ -92,6 +92,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
t = System.currentTimeMillis();
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("Unable to fetch OID " + oid + ": " + e.getMessage());
errs.put(oid, e.getMessage());
}
@ -113,66 +114,91 @@ public class VSACImporter extends OIDBasedValueSetImporter {
private boolean processOid(String dest, boolean onlyNew, Map<String, String> errs, FHIRToolingClient fhirToolingClient, String oid)
throws IOException, InterruptedException, FileNotFoundException {
while (true) {
boolean ok = true;
long t = System.currentTimeMillis();
ValueSet vs = null;
try {
vs = fhirToolingClient.read(ValueSet.class, oid);
} catch (Exception e) {
errs.put(oid, "Read: " +e.getMessage());
System.out.println("Read "+oid+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e.getMessage());
return false;
if (e.getMessage().contains("timed out")) {
ok = false;
} else {
errs.put(oid, "Read: " +e.getMessage());
System.out.println("Read "+oid+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e.getMessage());
return false;
}
}
t = System.currentTimeMillis();
try {
Parameters p = new Parameters();
p.addParameter("url", new UriType(vs.getUrl()));
ValueSet vse = fhirToolingClient.expandValueset(vs, p);
vs.setExpansion(vse.getExpansion());
} catch (Exception e) {
errs.put(oid, "Expansion: " +e.getMessage());
System.out.println("Expand "+oid+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e.getMessage());
}
while (isIncomplete(vs.getExpansion())) {
Parameters p = new Parameters();
int offset = vs.getExpansion().getParameter("offset").getValueIntegerType().getValue() + vs.getExpansion().getParameter("count").getValueIntegerType().getValue();
p.addParameter("offset", offset);
p.addParameter("url", new UriType(vs.getUrl()));
if (ok) {
t = System.currentTimeMillis();
try {
ValueSet vse = fhirToolingClient.expandValueset(vs, p);
vs.getExpansion().getContains().addAll(vse.getExpansion().getContains());
vs.getExpansion().setParameter(vse.getExpansion().getParameter());
} catch (Exception e2) {
errs.put(oid, "Expansion: " +e2.getMessage()+" @ "+offset);
System.out.println("Expand "+oid+" @ "+offset+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e2.getMessage());
}
}
vs.getExpansion().setOffsetElement(null);
vs.getExpansion().getParameter().clear();
if (vs.hasTitle()) {
if (vs.getTitle().equals(vs.getDescription())) {
vs.setTitle(vs.getName());
} else {
// System.out.println(oid);
// System.out.println(" name: "+vs.getName());
// System.out.println(" title: "+vs.getTitle());
// System.out.println(" desc: "+vs.getDescription());
Parameters p = new Parameters();
p.addParameter("url", new UriType(vs.getUrl()));
ValueSet vse = fhirToolingClient.expandValueset(null, p);
vs.setExpansion(vse.getExpansion());
} catch (Exception e) {
if (e.getMessage().contains("timed out")) {
ok = false;
} else {
errs.put(oid, "Expansion: " +e.getMessage());
System.out.println("Expand "+oid+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e.getMessage());
return false;
}
}
} else {
vs.setTitle(vs.getName());
}
vs.setName(makeValidName(vs.getName()));
JurisdictionUtilities.setJurisdictionCountry(vs.getJurisdiction(), "US");
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
return true;
if (ok) {
while (isIncomplete(vs.getExpansion())) {
Parameters p = new Parameters();
int offset = vs.getExpansion().getParameter("offset").getValueIntegerType().getValue() + vs.getExpansion().getParameter("count").getValueIntegerType().getValue();
p.addParameter("offset", offset);
p.addParameter("url", new UriType(vs.getUrl()));
t = System.currentTimeMillis();
try {
ValueSet vse = fhirToolingClient.expandValueset(null, p);
vs.getExpansion().getContains().addAll(vse.getExpansion().getContains());
vs.getExpansion().setParameter(vse.getExpansion().getParameter());
} catch (Exception e2) {
if (e2.getMessage().contains("timed out")) {
ok = false;
break;
} else {
errs.put(oid, "Expansion: " +e2.getMessage()+" @ "+offset);
System.out.println("Expand "+oid+" @ "+offset+" failed @ "+Utilities.describeDuration(System.currentTimeMillis()-t)+"ms: "+e2.getMessage());
return false;
}
}
}
}
if (ok) {
vs.getExpansion().setOffsetElement(null);
vs.getExpansion().getParameter().clear();
if (vs.hasTitle()) {
if (vs.getTitle().equals(vs.getDescription())) {
vs.setTitle(vs.getName());
} else {
// System.out.println(oid);
// System.out.println(" name: "+vs.getName());
// System.out.println(" title: "+vs.getTitle());
// System.out.println(" desc: "+vs.getDescription());
}
} else {
vs.setTitle(vs.getName());
}
if (vs.getUrl().startsWith("https://")) {
System.out.println("URL is https: "+vs.getUrl());
}
vs.setName(makeValidName(vs.getName()));
JurisdictionUtilities.setJurisdictionCountry(vs.getJurisdiction(), "US");
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
return true;
}
}
}
private boolean isIncomplete(ValueSetExpansionComponent expansion) {
IntegerType c = expansion.getParameter("count").getValueIntegerType();
IntegerType offset = expansion.getParameter("offset").getValueIntegerType();
IntegerType c = expansion.getParameter("count") != null ? expansion.getParameter("count").getValueIntegerType() : new IntegerType(0);
IntegerType offset = expansion.getParameter("offset") != null ? expansion.getParameter("offset").getValueIntegerType() : new IntegerType(0);
return c.getValue() + offset.getValue() < expansion.getTotal();
}

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/*
@ -36,6 +37,7 @@ import java.util.Map;
import org.hl7.fhir.convertors.conv10_50.resources10_50.TerminologyCapabilities10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.dstu2.model.Resource;
import org.hl7.fhir.dstu2.utils.client.FHIRToolingClient;
import org.hl7.fhir.exceptions.FHIRException;
@ -45,6 +47,7 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.utilities.FhirPublication;
@ -165,6 +168,11 @@ public class TerminologyClientR2 implements ITerminologyClient {
return (Parameters) VersionConvertorFactory_10_50.convertResource(client.lookupCode(params));
}
@Override
public Parameters lookupCode(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_10_50.convertResource(client.lookupCode((org.hl7.fhir.dstu2.model.Parameters) VersionConvertorFactory_10_50.convertResource(params)));
}
@Override
public int getRetryCount() throws FHIRException {
return client.getRetryCount();
@ -246,4 +254,9 @@ public class TerminologyClientR2 implements ITerminologyClient {
return result == null ? null : (Bundle) VersionConvertorFactory_10_50.convertResource(result);
}
@Override
public Parameters translate(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_10_50.convertResource(client.translate((org.hl7.fhir.dstu2.model.Parameters) VersionConvertorFactory_10_50.convertResource(params)));
}
}

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.convertors.txClient;
import java.net.URISyntaxException;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
/*
@ -36,6 +37,7 @@ import java.util.Map;
import org.hl7.fhir.convertors.conv30_50.resources30_50.TerminologyCapabilities30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.dstu3.utils.client.FHIRToolingClient;
import org.hl7.fhir.exceptions.FHIRException;
@ -45,6 +47,7 @@ import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.utilities.FhirPublication;
@ -155,6 +158,11 @@ public class TerminologyClientR3 implements ITerminologyClient {
return (Parameters) VersionConvertorFactory_30_50.convertResource(client.lookupCode(params));
}
@Override
public Parameters lookupCode(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_30_50.convertResource(client.lookupCode((org.hl7.fhir.dstu3.model.Parameters) VersionConvertorFactory_30_50.convertResource(params)));
}
@Override
public int getRetryCount() throws FHIRException {
return client.getRetryCount();
@ -249,4 +257,9 @@ public class TerminologyClientR3 implements ITerminologyClient {
return (Parameters) VersionConvertorFactory_30_50.convertResource(p2);
}
@Override
public Parameters translate(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_30_50.convertResource(client.transform((org.hl7.fhir.dstu3.model.Parameters) VersionConvertorFactory_30_50.convertResource(params)));
}
}

View File

@ -18,6 +18,7 @@ import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.TerminologyCapabilities;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.terminologies.client.ITerminologyClient;
import org.hl7.fhir.r5.utils.client.network.ClientHeaders;
import org.hl7.fhir.utilities.FhirPublication;
@ -181,6 +182,11 @@ public class TerminologyClientR4 implements ITerminologyClient {
return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode(params));
}
@Override
public Parameters lookupCode(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_40_50.convertResource(client.lookupCode((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params)));
}
@Override
public int getRetryCount() throws FHIRException {
return client.getRetryCount();
@ -268,5 +274,10 @@ public class TerminologyClientR4 implements ITerminologyClient {
org.hl7.fhir.r4.model.Bundle result = client.search(type, criteria);
return result == null ? null : (Bundle) VersionConvertorFactory_40_50.convertResource(result);
}
@Override
public Parameters translate(Parameters params) throws FHIRException {
return (Parameters) VersionConvertorFactory_40_50.convertResource(client.translate((org.hl7.fhir.r4.model.Parameters) VersionConvertorFactory_40_50.convertResource(params)));
}
}

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -307,7 +307,6 @@ public class ClientUtils {
request.addHeader("Accept", format);
request.addHeader("Content-Type", format + ";charset=" + DEFAULT_CHARSET);
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
if (headers != null) {
for (Header header : headers) {
request.addHeader(header);

View File

@ -742,6 +742,46 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
return (Parameters) result.getPayload();
}
public Parameters lookupCode(Parameters p) {
recordUse();
ResourceRequest<Resource> result = utils.issuePostRequest(
resourceAddress.resolveOperationUri(ValueSet.class, "lookup"),
utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())),
withVer(getPreferredResourceFormat(), "1.0"),
timeoutNormal);
result.addErrorStatus(410);// gone
result.addErrorStatus(404);// unknown
result.addErrorStatus(405);
result.addErrorStatus(422);// Unprocessable Entity
result.addSuccessStatus(200);
result.addSuccessStatus(201);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
(OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public Parameters translate(Parameters p) {
recordUse();
ResourceRequest<Resource> result = utils.issuePostRequest(
resourceAddress.resolveOperationUri(ConceptMap.class, "translate"),
utils.getResourceAsByteArray(p, false, isJson(getPreferredResourceFormat())),
withVer(getPreferredResourceFormat(), "1.0"),
timeoutNormal);
result.addErrorStatus(410);// gone
result.addErrorStatus(404);// unknown
result.addErrorStatus(405);
result.addErrorStatus(422);// Unprocessable Entity
result.addSuccessStatus(200);
result.addSuccessStatus(201);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
(OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
List<Header> headers = null;

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -263,7 +263,6 @@ public class ClientUtils {
request.addHeader("Accept", format);
request.addHeader("Content-Type", format + ";charset=" + DEFAULT_CHARSET);
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
if (headers != null) {
for (Header header : headers) {
request.addHeader(header);

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -107,7 +107,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
private IWorkerContext context;
private boolean canBeHeirarchy = true;
private boolean canBeHierarchy = true;
private Set<String> excludeKeys = new HashSet<String>();
private Set<String> excludeSystems = new HashSet<String>();
private ValueSetExpanderFactory factory;
@ -151,13 +151,13 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
String s = key(n);
if (map.containsKey(s) || excludeKeys.contains(s)) {
canBeHeirarchy = false;
canBeHierarchy = false;
} else {
codes.add(n);
map.put(s, n);
total++;
}
if (canBeHeirarchy && parent != null) {
if (canBeHierarchy && parent != null) {
parent.getContains().add(n);
} else {
roots.add(n);
@ -198,7 +198,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
ValueSetExpansionContainsComponent np = null;
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
boolean inc = CodeSystemUtilities.isInactive(cs, def);
if (canBeHeirarchy || !abs)
if (canBeHierarchy || !abs)
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), profile, abs, inc, filters);
for (ConceptDefinitionComponent c : def.getConcept())
addCodeAndDescendents(cs, system, c, np, profile, filters);
@ -280,7 +280,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (source.hasCompose())
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), profile);
if (canBeHeirarchy) {
if (canBeHierarchy) {
for (ValueSetExpansionContainsComponent c : roots) {
focus.getExpansion().getContains().add(c);
}
@ -288,7 +288,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
for (ValueSetExpansionContainsComponent c : codes) {
if (map.containsKey(key(c)) && !c.getAbstract()) { // we may have added abstract codes earlier while we still thought it might be heirarchical, but later we gave up, so now ignore them
focus.getExpansion().getContains().add(c);
c.getContains().clear(); // make sure any heirarchy is wiped
c.getContains().clear(); // make sure any hierarchy is wiped
}
}
}
@ -321,12 +321,6 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
return res;
}
private void addToHeirarchy(List<ValueSetExpansionContainsComponent> target, List<ValueSetExpansionContainsComponent> source) {
for (ValueSetExpansionContainsComponent s : source) {
target.add(s);
}
}
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
if (def == null)
@ -350,13 +344,13 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
// Exclude comes first because we build up a map of things to exclude
for (ConceptSetComponent inc : compose.getExclude())
excludeCodes(inc, params);
canBeHeirarchy = !profile.getExcludeNested() && excludeKeys.isEmpty() && excludeSystems.isEmpty();
canBeHierarchy = !profile.getExcludeNested() && excludeKeys.isEmpty() && excludeSystems.isEmpty();
boolean first = true;
for (ConceptSetComponent inc : compose.getInclude()) {
if (first == true)
first = false;
else
canBeHeirarchy = false;
canBeHierarchy = false;
includeCodes(inc, params, profile);
}
@ -381,7 +375,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (!existsInParams(params, p.getName(), p.getValue()))
params.add(p);
}
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a heirarchy
canBeHierarchy = false; // if we're importing a value set, we have to be combining, so we won't try for a hierarchy
return vso.getValueset();
}
@ -406,7 +400,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
} else {
CodeSystem cs = context.fetchCodeSystem(inc.getSystem());
if ((cs == null || cs.getContent() != CodeSystemContentMode.COMPLETE) && context.supportsSystem(inc.getSystem())) {
addCodes(context.expandVS(inc, canBeHeirarchy), params, profile, imports);
addCodes(context.expandVS(inc, canBeHierarchy), params, profile, imports);
return;
}
@ -430,14 +424,14 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
}
if (!inc.getConcept().isEmpty()) {
canBeHeirarchy = false;
canBeHierarchy = false;
for (ConceptReferenceComponent c : inc.getConcept()) {
addCode(inc.getSystem(), c.getCode(), Utilities.noString(c.getDisplay()) ? getCodeDisplay(cs, c.getCode()) : c.getDisplay(), null, convertDesignations(c.getDesignation()), profile, false,
CodeSystemUtilities.isInactive(cs, c.getCode()), imports);
}
}
if (inc.getFilter().size() > 1) {
canBeHeirarchy = false; // which will bt the case if we get around to supporting this
canBeHierarchy = false; // which will bt the case if we get around to supporting this
throw new TerminologyServiceException("Multiple filters not handled yet"); // need to and them, and this isn't done yet. But this shouldn't arise in non loinc and snomed value sets
}
if (inc.getFilter().size() == 1) {
@ -457,7 +451,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
addCodeAndDescendents(cs, inc.getSystem(), c, null, profile, imports);
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
// gg; note: wtf is this: if the filter is display=v, look up the code 'v', and see if it's diplsay is 'v'?
canBeHeirarchy = false;
canBeHierarchy = false;
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
if (def != null) {
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {

View File

@ -251,7 +251,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"Update " + resource.fhirType() + "/" + resource.getId(),
@ -279,7 +279,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result = null;
try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"Update " + resource.fhirType() + "/" + id,
@ -316,7 +316,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result;
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
if (complex) {
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true);
if (client.getLogger() != null) {
client.getLogger().logRequest("POST", url.toString(), null, body);
}
@ -349,7 +349,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
recordUse();
Bundle transactionResult = null;
try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "3.0"), "transaction", timeoutOperation + (timeoutEntry * batch.getEntry().size()));
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(), ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat()), false), withVer(getPreferredResourceFormat(), "3.0"), "transaction", timeoutOperation + (timeoutEntry * batch.getEntry().size()));
} catch (Exception e) {
handleException("An error occurred trying to process this transaction request", e);
}
@ -362,7 +362,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "3.0"), generateHeaders(),
"POST " + resourceClass.getName() + (id != null ? "/" + id : "") + "/$validate", timeoutLong);
if (result.isUnsuccessfulRequest()) {
@ -431,7 +431,44 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
}
return (Parameters) result.getPayload();
}
public Parameters lookupCode(Parameters p) {
recordUse();
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"CodeSystem/$lookup",
timeoutNormal);
} catch (IOException e) {
e.printStackTrace();
}
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public Parameters transform(Parameters p) {
recordUse();
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ConceptMap.class, "transform"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"ConceptMap/$transform",
timeoutNormal);
} catch (IOException e) {
e.printStackTrace();
}
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(), (OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
@ -440,7 +477,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"ValueSet/$expand?url=" + source.getUrl(),
@ -465,7 +502,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"Closure?name=" + name,
@ -487,7 +524,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
org.hl7.fhir.dstu3.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "3.0"),
generateHeaders(),
"UpdateClosure?name=" + name,

View File

@ -14,7 +14,7 @@ import org.hl7.fhir.dstu3.utils.client.EFhirClientException;
public class ByteUtils {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson) {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson, boolean noXhtml) {
ByteArrayOutputStream baos = null;
byte[] byteArray = null;
try {
@ -26,6 +26,9 @@ public class ByteUtils {
parser = new XmlParser();
}
parser.setOutputStyle(pretty ? IParser.OutputStyle.PRETTY : IParser.OutputStyle.NORMAL);
if (noXhtml) {
parser.setSuppressXhtml("Narrative removed");
}
parser.compose(baos, resource);
baos.close();
byteArray = baos.toByteArray();

View File

@ -84,7 +84,6 @@ public class FhirRequestBuilder {
/**
* Adds necessary headers for all REST requests.
* <li>User-Agent : hapi-fhir-tooling-client</li>
* <li>Accept-Charset : {@link FhirRequestBuilder#DEFAULT_CHARSET}</li>
*
* @param request {@link Request.Builder} to add default headers to.
*/
@ -92,7 +91,6 @@ public class FhirRequestBuilder {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
/**

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -66,11 +66,11 @@ import org.hl7.fhir.r4.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r4.utils.DefinitionNavigator;
import org.hl7.fhir.r4.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.Source;
@ -1383,8 +1383,8 @@ public class ProfileComparer {
File f = ManagedFileAccess.file(local);
if (f.exists())
return TextFile.fileToString(f);
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source);
HTTPResult res = ManagedWebAccess.get(source);
res.checkThrowException();
String result = TextFile.bytesToString(res.getContent());
TextFile.stringToFile(result, f);

View File

@ -50,7 +50,7 @@ public class ExpressionNode {
Empty, Not, Exists, SubsetOf, SupersetOf, IsDistinct, Distinct, Count, Where, Select, All, Repeat, Aggregate,
Item /* implicit from name[] */, As, Is, Single, First, Last, Tail, Skip, Take, Union, Combine, Intersect, Exclude,
Iif, Upper, Lower, ToChars, IndexOf, Substring, StartsWith, EndsWith, Matches, MatchesFull, ReplaceMatches,
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse,
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, DefineVariable, Check, Today, Now, Resolve, Extension, AllFalse,
AnyFalse, AllTrue, AnyTrue, HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString,
ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToDate, ConvertsToTime, ToBoolean, ToInteger,
ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo, Round, Sqrt, Abs, Ceiling, Exp, Floor, Ln, Log,
@ -60,7 +60,7 @@ public class ExpressionNode {
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
// Local extensions to FHIRPath
HtmlChecks1, HtmlChecks2, AliasAs, Alias, Comparable;
HtmlChecks1, HtmlChecks2, Comparable;
public static Function fromCode(String name) {
if (name.equals("empty"))
@ -151,6 +151,8 @@ public class ExpressionNode {
return Function.MemberOf;
if (name.equals("trace"))
return Function.Trace;
if (name.equals("defineVariable"))
return Function.DefineVariable;
if (name.equals("check"))
return Function.Check;
if (name.equals("today"))
@ -171,10 +173,6 @@ public class ExpressionNode {
return Function.AnyTrue;
if (name.equals("hasValue"))
return Function.HasValue;
if (name.equals("alias"))
return Function.Alias;
if (name.equals("aliasAs"))
return Function.AliasAs;
if (name.equals("htmlChecks"))
return Function.HtmlChecks1;
if (name.equals("htmlchecks"))
@ -353,6 +351,8 @@ public class ExpressionNode {
return "memberOf";
case Trace:
return "trace";
case DefineVariable :
return "defineVariable";
case Check:
return "check";
case Today:
@ -373,10 +373,6 @@ public class ExpressionNode {
return "anyTrue";
case HasValue:
return "hasValue";
case Alias:
return "alias";
case AliasAs:
return "aliasAs";
case Encode:
return "encode";
case Decode:

View File

@ -139,6 +139,7 @@ public class FHIRPathEngine {
/**
* A constant reference - e.g. a reference to a name that must be resolved in
* context. The % will be removed from the constant name before this is invoked.
* Variables created with defineVariable will not be processed by resolveConstant (or resolveConstantType)
*
* This will also be called if the host invokes the FluentPath engine with a
* context of null
@ -604,7 +605,7 @@ public class FHIRPathEngine {
}
log = new StringBuilder();
return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null,
base != null && base.isResource() ? base : null, base, null, base), list, ExpressionNode, true);
base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true);
}
/**
@ -623,7 +624,7 @@ public class FHIRPathEngine {
}
log = new StringBuilder();
return execute(
new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, null, base),
new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, base),
list, exp, true);
}
@ -642,7 +643,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list,
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list,
ExpressionNode, true);
}
@ -661,7 +662,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list,
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list,
expressionNode, true);
}
@ -681,7 +682,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list, exp, true);
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list, exp, true);
}
/**
@ -848,16 +849,14 @@ public class FHIRPathEngine {
private Base context;
private Base thisItem;
private List<Base> total;
private Map<String, Base> aliases;
private int index;
private Map<String, List<Base>> definedVariables;
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Map<String, Base> aliases,
Base thisItem) {
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Base thisItem) {
this.appInfo = appInfo;
this.context = context;
this.focusResource = resource;
this.rootResource = rootResource;
this.aliases = aliases;
this.thisItem = thisItem;
this.index = 0;
}
@ -886,26 +885,34 @@ public class FHIRPathEngine {
return new IntegerType(index);
}
public void addAlias(String name, List<Base> focus) throws FHIRException {
if (aliases == null) {
aliases = new HashMap<String, Base>();
} else {
aliases = new HashMap<String, Base>(aliases); // clone it, since it's going to change
}
if (focus.size() > 1) {
throw makeException(null, I18nConstants.FHIRPATH_ALIAS_COLLECTION);
}
aliases.put(name, focus.size() == 0 ? null : focus.get(0));
}
public Base getAlias(String name) {
return aliases == null ? null : aliases.get(name);
}
public ExecutionContext setIndex(int i) {
index = i;
return this;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public List<Base> getDefinedVariable(String name) {
return definedVariables == null ? makeNull() : definedVariables.get(name);
}
public void setDefinedVariable(String name, List<Base> value) {
if (isSystemVariable(name))
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, List<Base>>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private class ExecutionTypeContext {
@ -914,6 +921,7 @@ public class FHIRPathEngine {
private TypeDetails context;
private TypeDetails thisItem;
private TypeDetails total;
private Map<String, TypeDetails> definedVariables;
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
super();
@ -932,6 +940,29 @@ public class FHIRPathEngine {
return thisItem;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public TypeDetails getDefinedVariable(String name) {
return definedVariables == null ? null : definedVariables.get(name);
}
public void setDefinedVariable(String name, TypeDetails value) {
if (isSystemVariable(name))
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, TypeDetails>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
@ -1333,6 +1364,8 @@ public class FHIRPathEngine {
return checkParamCount(lexer, location, exp, 1);
case Trace:
return checkParamCount(lexer, location, exp, 1, 2);
case DefineVariable:
return checkParamCount(lexer, location, exp, 1, 2);
case Check:
return checkParamCount(lexer, location, exp, 2);
case Today:
@ -1353,10 +1386,6 @@ public class FHIRPathEngine {
return checkParamCount(lexer, location, exp, 0);
case HasValue:
return checkParamCount(lexer, location, exp, 0);
case Alias:
return checkParamCount(lexer, location, exp, 1);
case AliasAs:
return checkParamCount(lexer, location, exp, 1);
case Encode:
return checkParamCount(lexer, location, exp, 1);
case Decode:
@ -1442,9 +1471,10 @@ public class FHIRPathEngine {
return false;
}
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry)
private List<Base> execute(ExecutionContext inContext, List<Base> focus, ExpressionNode exp, boolean atEntry)
throws FHIRException {
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
ExecutionContext context = contextForParameter(inContext);
List<Base> work = new ArrayList<Base>();
switch (exp.getKind()) {
case Unary:
@ -1488,6 +1518,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
List<Base> work2 = preOperate(work, last.getOperation(), exp);
if (work2 != null) {
work = work2;
@ -1551,9 +1582,10 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, exp.getName());
}
private TypeDetails executeType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, boolean atEntry)
private TypeDetails executeType(ExecutionTypeContext inContext, TypeDetails focus, ExpressionNode exp, boolean atEntry)
throws PathEngineException, DefinitionException {
TypeDetails result = new TypeDetails(null);
ExecutionTypeContext context = contextForParameter(inContext);
TypeDetails result = new TypeDetails(null);
switch (exp.getKind()) {
case Name:
if (atEntry && exp.getName().equals("$this")) {
@ -1597,6 +1629,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
TypeDetails work;
if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
work = executeTypeName(context, focus, next, atEntry);
@ -1621,6 +1654,10 @@ public class FHIRPathEngine {
}
FHIRConstant c = (FHIRConstant) constant;
if (c.getValue().startsWith("%")) {
String varName = c.getValue().substring(1);
if (context.hasDefinedVariable(varName)) {
return context.getDefinedVariable(varName);
}
return resolveConstant(context, c.getValue(), beforeContext, expr, explicitConstant);
} else if (c.getValue().startsWith("@")) {
return new ArrayList<Base>(Arrays.asList(processDateConstant(context.appInfo, c.getValue().substring(1), expr)));
@ -1691,6 +1728,22 @@ public class FHIRPathEngine {
}
}
static boolean isSystemVariable(String name){
if (name.equals("sct"))
return true;
if (name.equals("loinc"))
return true;
if (name.equals("ucum"))
return true;
if (name.equals("resource"))
return true;
if (name.equals("rootResource"))
return true;
if (name.equals("context"))
return true;
return false;
}
private List<Base> resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr, boolean explicitConstant)
throws PathEngineException {
if (s.equals("%sct")) {
@ -3134,8 +3187,14 @@ public class FHIRPathEngine {
} else if (s.startsWith("%`ext-")) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
} else if (hostServices == null) {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
} else {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
return hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
}
}
@ -3432,6 +3491,25 @@ public class FHIRPathEngine {
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case DefineVariable : {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.UNORDERED, TypeDetails.FP_String));
// set the type of the variable
// Actually evaluate the value of the first parameter (to get the name of the variable if possible)
// and if have that, set it into the context
ExpressionNode p = exp.getParameters().get(0);
if (p.getKind() == Kind.Constant && p.getConstant() != null) {
String varName = exp.getParameters().get(0).getConstant().primitiveValue();
if (varName != null) {
if (paramTypes.size() > 1)
context.setDefinedVariable(varName, paramTypes.get(1));
else
context.setDefinedVariable(varName, focus);
}
} else {
// this variable is not a constant, so we can't analyze what name it could have
}
return focus;
}
case Check: {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
@ -3466,14 +3544,6 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Comparable:
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
case AliasAs:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
case Encode:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
@ -3623,7 +3693,7 @@ public class FHIRPathEngine {
|| exp.getFunction() == Function.All || exp.getFunction() == Function.Select
|| exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
case 1:
return exp.getFunction() == Function.Trace;
return exp.getFunction() == Function.Trace || exp.getFunction() == Function.DefineVariable;
default:
return false;
}
@ -3831,6 +3901,8 @@ public class FHIRPathEngine {
return funcMemberOf(context, focus, exp);
case Trace:
return funcTrace(context, focus, exp);
case DefineVariable:
return funcDefineVariable(context, focus, exp);
case Check:
return funcCheck(context, focus, exp);
case Today:
@ -3851,8 +3923,6 @@ public class FHIRPathEngine {
return funcAllTrue(context, focus, exp);
case HasValue:
return funcHasValue(context, focus, exp);
case AliasAs:
return funcAliasAs(context, focus, exp);
case Encode:
return funcEncode(context, focus, exp);
case Decode:
@ -3867,8 +3937,6 @@ public class FHIRPathEngine {
return funcSplit(context, focus, exp);
case Join:
return funcJoin(context, focus, exp);
case Alias:
return funcAlias(context, focus, exp);
case HtmlChecks1:
return funcHtmlChecks1(context, focus, exp);
case HtmlChecks2:
@ -4417,24 +4485,6 @@ public class FHIRPathEngine {
return result;
}
private List<Base> funcAliasAs(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
context.addAlias(name, focus);
return focus;
}
private List<Base> funcAlias(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> res = new ArrayList<Base>();
Base b = context.getAlias(name);
if (b != null) {
res.add(b);
}
return res;
}
private List<Base> funcHtmlChecks1(ExecutionContext context, List<Base> focus, ExpressionNode exp)
throws FHIRException {
// todo: actually check the HTML
@ -4585,12 +4635,50 @@ public class FHIRPathEngine {
}
private ExecutionContext changeThis(ExecutionContext context, Base newThis) {
return new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
context.aliases, newThis);
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionContext contextForParameter(ExecutionContext context) {
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.thisItem);
newContext.total = context.total;
newContext.index = context.index;
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
return new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private List<Base> funcNow(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
@ -5417,6 +5505,20 @@ public class FHIRPathEngine {
return focus;
}
private List<Base> funcDefineVariable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> value;
if (exp.getParameters().size() == 2) {
value = execute(context, focus, exp.getParameters().get(1), true);
} else {
value = focus;
}
// stash the variable into the context
context.setDefinedVariable(name, value);
return focus;
}
private List<Base> funcCheck(ExecutionContext context, List<Base> focus, ExpressionNode expr) throws FHIRException {
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
if (!convertToBoolean(n1)) {
@ -6278,7 +6380,7 @@ public class FHIRPathEngine {
sd = fetchStructureByType(element, expr);
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND,
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND,
element.getElement().getType().get(0).getProfile(), element.getElement().getId());
}
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());

View File

@ -299,7 +299,7 @@ public class CodeSystemUtilities {
}
// see http://hl7.org/fhir/R4/codesystem.html#hierachy
// returns additional parents not in the heirarchy
// returns additional parents not in the hierarchy
public static List<String> getOtherChildren(CodeSystem cs, ConceptDefinitionComponent c) {
List<String> res = new ArrayList<String>();
for (ConceptPropertyComponent p : c.getProperty()) {

View File

@ -106,7 +106,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
private IWorkerContext context;
private boolean canBeHeirarchy = true;
private boolean canBeHierarchy = true;
private Set<String> excludeKeys = new HashSet<String>();
private Set<String> excludeSystems = new HashSet<String>();
private ValueSet focus;
@ -152,13 +152,13 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
String s = key(n);
if (map.containsKey(s) || excludeKeys.contains(s)) {
canBeHeirarchy = false;
canBeHierarchy = false;
} else {
codes.add(n);
map.put(s, n);
total++;
}
if (canBeHeirarchy && parent != null) {
if (canBeHierarchy && parent != null) {
parent.getContains().add(n);
} else {
roots.add(n);
@ -227,7 +227,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
ValueSetExpansionContainsComponent np = null;
boolean abs = CodeSystemUtilities.isNotSelectable(cs, def);
boolean inc = CodeSystemUtilities.isInactive(cs, def);
if (canBeHeirarchy || !abs)
if (canBeHierarchy || !abs)
np = addCode(system, def.getCode(), def.getDisplay(), parent, def.getDesignation(), expParams, abs, inc,
filters);
for (ConceptDefinitionComponent c : def.getConcept())
@ -343,7 +343,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (source.hasCompose())
handleCompose(source.getCompose(), focus.getExpansion().getParameter(), expParams, source.getUrl());
if (canBeHeirarchy) {
if (canBeHierarchy) {
for (ValueSetExpansionContainsComponent c : roots) {
focus.getExpansion().getContains().add(c);
}
@ -353,7 +353,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
// thought it might be heirarchical, but later we gave up, so
// now ignore them
focus.getExpansion().getContains().add(c);
c.getContains().clear(); // make sure any heirarchy is wiped
c.getContains().clear(); // make sure any hierarchy is wiped
}
}
}
@ -372,13 +372,6 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
return res;
}
private void addToHeirarchy(List<ValueSetExpansionContainsComponent> target,
List<ValueSetExpansionContainsComponent> source) {
for (ValueSetExpansionContainsComponent s : source) {
target.add(s);
}
}
private String getCodeDisplay(CodeSystem cs, String code) throws TerminologyServiceException {
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), code);
if (def == null)
@ -403,14 +396,14 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
// Exclude comes first because we build up a map of things to exclude
for (ConceptSetComponent inc : compose.getExclude())
excludeCodes(inc, params, ctxt);
canBeHeirarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty();
canBeHierarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty();
boolean first = true;
for (ConceptSetComponent inc : compose.getInclude()) {
if (first == true)
first = false;
else
canBeHeirarchy = false;
includeCodes(inc, params, expParams, canBeHeirarchy);
canBeHierarchy = false;
includeCodes(inc, params, expParams, canBeHierarchy);
}
}
@ -433,8 +426,8 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
if (!existsInParams(params, p.getName(), p.getValue()))
params.add(p);
}
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for
// a heirarchy
canBeHierarchy = false; // if we're importing a value set, we have to be combining, so we won't try for
// a hierarchy
return vso.getValueset();
}
@ -518,7 +511,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
}
if (!inc.getConcept().isEmpty()) {
canBeHeirarchy = false;
canBeHierarchy = false;
for (ConceptReferenceComponent c : inc.getConcept()) {
c.checkNoModifiers("Code in Code System", "expanding");
addCode(inc.getSystem(), c.getCode(),
@ -528,7 +521,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
}
}
if (inc.getFilter().size() > 1) {
canBeHeirarchy = false; // which will bt the case if we get around to supporting this
canBeHierarchy = false; // which will bt the case if we get around to supporting this
throw new TerminologyServiceException("Multiple filters not handled yet"); // need to and them, and this isn't
// done yet. But this shouldn't arise
// in non loinc and snomed value sets
@ -562,7 +555,7 @@ public class ValueSetExpanderSimple implements ValueSetExpander {
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
// gg; note: wtf is this: if the filter is display=v, look up the code 'v', and
// see if it's diplsay is 'v'?
canBeHeirarchy = false;
canBeHierarchy = false;
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
if (def != null) {
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {

View File

@ -243,7 +243,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
try {
result = client.issuePutRequest(
resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "Update " + resource.fhirType() + "/" + resource.getId(),
timeoutOperation);
if (result.isUnsuccessfulRequest()) {
@ -273,7 +273,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result = null;
try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "Update " + resource.fhirType() + "/" + id,
timeoutOperation);
if (result.isUnsuccessfulRequest()) {
@ -311,7 +311,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result;
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
if (complex) {
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true);
result = client.issuePostRequest(url, body, withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(),
"POST " + resourceClass.getName() + "/$" + name, timeoutLong);
} else {
@ -336,7 +336,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
Bundle transactionResult = null;
try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(),
ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "4.0"), "transaction", timeoutOperation + (timeoutEntry * batch.getEntry().size()));
} catch (Exception e) {
handleException("An error occurred trying to process this transaction request", e);
@ -350,7 +350,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
ResourceRequest<T> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(),
"POST " + resourceClass.getName() + (id != null ? "/" + id : "") + "/$validate", timeoutLong);
if (result.isUnsuccessfulRequest()) {
@ -418,15 +418,51 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
}
return (Parameters) result.getPayload();
}
public Parameters lookupCode(Parameters p) {
recordUse();
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(CodeSystem.class, "lookup"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "CodeSystem/$lookup", timeoutNormal);
} catch (IOException e) {
throw new FHIRException(e);
}
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
(OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public Parameters translate(Parameters p) {
recordUse();
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ConceptMap.class, "translate"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "ConceptMap/$translate", timeoutNormal);
} catch (IOException e) {
throw new FHIRException(e);
}
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
(OperationOutcome) result.getPayload());
}
return (Parameters) result.getPayload();
}
public ValueSet expandValueset(ValueSet source, Parameters expParams) {
recordUse();
Parameters p = expParams == null ? new Parameters() : expParams.copy();
p.addParameter().setName("valueSet").setResource(source);
if (source != null) {
p.addParameter().setName("valueSet").setResource(source);
}
org.hl7.fhir.r4.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())), withVer(getPreferredResourceFormat(), "4.0"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true), withVer(getPreferredResourceFormat(), "4.0"),
generateHeaders(), source == null ? "ValueSet/$expand" : "ValueSet/$expand?url=" + source.getUrl(),
timeoutExpand);
if (result.isUnsuccessfulRequest()) {
@ -457,7 +493,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
try {
result = client.issuePostRequest(
resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "Closure?name=" + name, timeoutNormal);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
@ -478,7 +514,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient {
try {
result = client.issuePostRequest(
resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
withVer(getPreferredResourceFormat(), "4.0"), generateHeaders(), "UpdateClosure?name=" + name, timeoutOperation);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),

View File

@ -14,7 +14,7 @@ import org.hl7.fhir.r4.utils.client.EFhirClientException;
public class ByteUtils {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson) {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson, boolean noXhtml) {
ByteArrayOutputStream baos = null;
byte[] byteArray = null;
try {
@ -26,6 +26,9 @@ public class ByteUtils {
parser = new XmlParser();
}
parser.setOutputStyle(pretty ? IParser.OutputStyle.PRETTY : IParser.OutputStyle.NORMAL);
if (noXhtml) {
parser.setSuppressXhtml("Narrative removed");
}
parser.compose(baos, resource);
baos.close();
byteArray = baos.toByteArray();

View File

@ -88,7 +88,6 @@ public class FhirRequestBuilder {
/**
* Adds necessary headers for all REST requests.
* <li>User-Agent : hapi-fhir-tooling-client</li>
* <li>Accept-Charset : {@link FhirRequestBuilder#DEFAULT_CHARSET}</li>
*
* @param request {@link Request.Builder} to add default headers to.
*/
@ -96,7 +95,6 @@ public class FhirRequestBuilder {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
/**
@ -284,7 +282,7 @@ public class FhirRequestBuilder {
reqid = response.header("X-Request-Id");
}
if (reqid != null) {
s = s + " ["+reqid+"]";
s = s + " [x-request-id: "+reqid+"]";
}
System.out.println("Error from "+source+": " + s);
throw new EFhirClientException("Error from "+source+": " + ResourceUtilities.getErrorDescription(error), error);

View File

@ -1558,7 +1558,6 @@
<xs:attribute name="onsubmit" type="Script"/>
<xs:attribute name="onreset" type="Script"/>
<xs:attribute name="accept" type="ContentTypes"/>
<xs:attribute name="accept-charset" type="Charsets"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

View File

@ -895,11 +895,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS));
} else if (unsupportedCodeSystems.contains(codeKey)) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,
formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, t.getCoding().getSystem()),
formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, t.getCoding().getSystem()),
TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED));
} else if (noTerminologyServer) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,
formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES),
formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, t.getCoding().getCode(), t.getCoding().getSystem()),
TerminologyServiceErrorClass.NOSERVICE));
}
}
@ -1012,14 +1012,14 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
if (unsupportedCodeSystems.contains(codeKey)) {
return new ValidationResult(IssueSeverity.ERROR,
formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, code.getSystem()),
formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, code.getSystem()),
TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
}
// if that failed, we try to validate on the server
if (noTerminologyServer) {
return new ValidationResult(IssueSeverity.ERROR,
formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES),
formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, code.getCode(), code.getSystem()),
TerminologyServiceErrorClass.NOSERVICE);
}
String csumm = txCache != null ? txCache.summary(code) : null;

View File

@ -50,7 +50,7 @@ public class ExpressionNode {
Empty, Not, Exists, SubsetOf, SupersetOf, IsDistinct, Distinct, Count, Where, Select, All, Repeat, Aggregate,
Item /* implicit from name[] */, As, Is, Single, First, Last, Tail, Skip, Take, Union, Combine, Intersect, Exclude,
Iif, Upper, Lower, ToChars, IndexOf, Substring, StartsWith, EndsWith, Matches, MatchesFull, ReplaceMatches,
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse,
Contains, Replace, Length, Children, Descendants, MemberOf, Trace, DefineVariable, Check, Today, Now, Resolve, Extension, AllFalse,
AnyFalse, AllTrue, AnyTrue, HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString,
ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToDate, ConvertsToTime, ToBoolean, ToInteger,
ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo, Round, Sqrt, Abs, Ceiling, Exp, Floor, Ln, Log,
@ -60,7 +60,7 @@ public class ExpressionNode {
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
// Local extensions to FHIRPath
HtmlChecks1, HtmlChecks2, AliasAs, Alias, Comparable;
HtmlChecks1, HtmlChecks2, Comparable;
public static Function fromCode(String name) {
if (name.equals("empty"))
@ -151,6 +151,8 @@ public class ExpressionNode {
return Function.MemberOf;
if (name.equals("trace"))
return Function.Trace;
if (name.equals("defineVariable"))
return Function.DefineVariable;
if (name.equals("check"))
return Function.Check;
if (name.equals("today"))
@ -171,10 +173,6 @@ public class ExpressionNode {
return Function.AnyTrue;
if (name.equals("hasValue"))
return Function.HasValue;
if (name.equals("alias"))
return Function.Alias;
if (name.equals("aliasAs"))
return Function.AliasAs;
if (name.equals("htmlChecks"))
return Function.HtmlChecks1;
if (name.equals("htmlchecks"))
@ -353,6 +351,8 @@ public class ExpressionNode {
return "memberOf";
case Trace:
return "trace";
case DefineVariable :
return "defineVariable";
case Check:
return "check";
case Today:
@ -373,10 +373,6 @@ public class ExpressionNode {
return "anyTrue";
case HasValue:
return "hasValue";
case Alias:
return "alias";
case AliasAs:
return "aliasAs";
case Encode:
return "encode";
case Decode:

View File

@ -140,6 +140,7 @@ public class FHIRPathEngine {
/**
* A constant reference - e.g. a reference to a name that must be resolved in
* context. The % will be removed from the constant name before this is invoked.
* Variables created with defineVariable will not be processed by resolveConstant (or resolveConstantType)
*
* This will also be called if the host invokes the FluentPath engine with a
* context of null
@ -605,7 +606,7 @@ public class FHIRPathEngine {
}
log = new StringBuilder();
return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null,
base != null && base.isResource() ? base : null, base, null, base), list, ExpressionNode, true);
base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true);
}
/**
@ -624,7 +625,7 @@ public class FHIRPathEngine {
}
log = new StringBuilder();
return execute(
new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, null, base),
new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, base),
list, exp, true);
}
@ -643,7 +644,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list,
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list,
ExpressionNode, true);
}
@ -662,7 +663,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list,
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list,
expressionNode, true);
}
@ -682,7 +683,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list, exp, true);
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list, exp, true);
}
/**
@ -849,16 +850,14 @@ public class FHIRPathEngine {
private Base context;
private Base thisItem;
private List<Base> total;
private Map<String, Base> aliases;
private int index;
private Map<String, List<Base>> definedVariables;
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Map<String, Base> aliases,
Base thisItem) {
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Base thisItem) {
this.appInfo = appInfo;
this.context = context;
this.focusResource = resource;
this.rootResource = rootResource;
this.aliases = aliases;
this.thisItem = thisItem;
this.index = 0;
}
@ -887,26 +886,34 @@ public class FHIRPathEngine {
return new IntegerType(index);
}
public void addAlias(String name, List<Base> focus) throws FHIRException {
if (aliases == null) {
aliases = new HashMap<String, Base>();
} else {
aliases = new HashMap<String, Base>(aliases); // clone it, since it's going to change
}
if (focus.size() > 1) {
throw makeException(null, I18nConstants.FHIRPATH_ALIAS_COLLECTION);
}
aliases.put(name, focus.size() == 0 ? null : focus.get(0));
}
public Base getAlias(String name) {
return aliases == null ? null : aliases.get(name);
}
public ExecutionContext setIndex(int i) {
index = i;
return this;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public List<Base> getDefinedVariable(String name) {
return definedVariables == null ? makeNull() : definedVariables.get(name);
}
public void setDefinedVariable(String name, List<Base> value) {
if (isSystemVariable(name))
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, List<Base>>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private class ExecutionTypeContext {
@ -915,6 +922,7 @@ public class FHIRPathEngine {
private TypeDetails context;
private TypeDetails thisItem;
private TypeDetails total;
private Map<String, TypeDetails> definedVariables;
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
super();
@ -933,6 +941,29 @@ public class FHIRPathEngine {
return thisItem;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public TypeDetails getDefinedVariable(String name) {
return definedVariables == null ? null : definedVariables.get(name);
}
public void setDefinedVariable(String name, TypeDetails value) {
if (isSystemVariable(name))
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, TypeDetails>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
@ -1333,6 +1364,8 @@ public class FHIRPathEngine {
return checkParamCount(lexer, location, exp, 1);
case Trace:
return checkParamCount(lexer, location, exp, 1, 2);
case DefineVariable:
return checkParamCount(lexer, location, exp, 1, 2);
case Check:
return checkParamCount(lexer, location, exp, 2);
case Today:
@ -1353,10 +1386,6 @@ public class FHIRPathEngine {
return checkParamCount(lexer, location, exp, 0);
case HasValue:
return checkParamCount(lexer, location, exp, 0);
case Alias:
return checkParamCount(lexer, location, exp, 1);
case AliasAs:
return checkParamCount(lexer, location, exp, 1);
case Encode:
return checkParamCount(lexer, location, exp, 1);
case Decode:
@ -1442,9 +1471,10 @@ public class FHIRPathEngine {
return false;
}
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry)
private List<Base> execute(ExecutionContext inContext, List<Base> focus, ExpressionNode exp, boolean atEntry)
throws FHIRException {
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
ExecutionContext context = contextForParameter(inContext);
List<Base> work = new ArrayList<Base>();
switch (exp.getKind()) {
case Unary:
@ -1488,6 +1518,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
List<Base> work2 = preOperate(work, last.getOperation(), exp);
if (work2 != null) {
work = work2;
@ -1551,8 +1582,9 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, exp.getName());
}
private TypeDetails executeType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, boolean atEntry)
private TypeDetails executeType(ExecutionTypeContext inContext, TypeDetails focus, ExpressionNode exp, boolean atEntry)
throws PathEngineException, DefinitionException {
ExecutionTypeContext context = contextForParameter(inContext);
TypeDetails result = new TypeDetails(null);
switch (exp.getKind()) {
case Name:
@ -1597,6 +1629,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
TypeDetails work;
if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
work = executeTypeName(context, focus, next, atEntry);
@ -1622,6 +1655,10 @@ public class FHIRPathEngine {
}
FHIRConstant c = (FHIRConstant) constant;
if (c.getValue().startsWith("%")) {
String varName = c.getValue().substring(1);
if (context.hasDefinedVariable(varName)) {
return context.getDefinedVariable(varName);
}
return resolveConstant(context, c.getValue(), beforeContext, expr, explicitConstant);
} else if (c.getValue().startsWith("@")) {
return new ArrayList<Base>(Arrays.asList(processDateConstant(context.appInfo, c.getValue().substring(1), expr)));
@ -1692,6 +1729,22 @@ public class FHIRPathEngine {
}
}
static boolean isSystemVariable(String name){
if (name.equals("sct"))
return true;
if (name.equals("loinc"))
return true;
if (name.equals("ucum"))
return true;
if (name.equals("resource"))
return true;
if (name.equals("rootResource"))
return true;
if (name.equals("context"))
return true;
return false;
}
private List<Base> resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr, boolean explicitConstant)
throws PathEngineException {
if (s.equals("%sct")) {
@ -3136,8 +3189,14 @@ public class FHIRPathEngine {
} else if (s.startsWith("%`ext-")) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
} else if (hostServices == null) {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
} else {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
return hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
}
}
@ -3434,6 +3493,25 @@ public class FHIRPathEngine {
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case DefineVariable : {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.UNORDERED, TypeDetails.FP_String));
// set the type of the variable
// Actually evaluate the value of the first parameter (to get the name of the variable if possible)
// and if have that, set it into the context
ExpressionNode p = exp.getParameters().get(0);
if (p.getKind() == Kind.Constant && p.getConstant() != null) {
String varName = exp.getParameters().get(0).getConstant().primitiveValue();
if (varName != null) {
if (paramTypes.size() > 1)
context.setDefinedVariable(varName, paramTypes.get(1));
else
context.setDefinedVariable(varName, focus);
}
} else {
// this variable is not a constant, so we can't analyze what name it could have
}
return focus;
}
case Check: {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
@ -3468,14 +3546,6 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Comparable:
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
case AliasAs:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
case Encode:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes,
new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
@ -3625,7 +3695,7 @@ public class FHIRPathEngine {
|| exp.getFunction() == Function.All || exp.getFunction() == Function.Select
|| exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
case 1:
return exp.getFunction() == Function.Trace;
return exp.getFunction() == Function.Trace || exp.getFunction() == Function.DefineVariable;
default:
return false;
}
@ -3833,6 +3903,8 @@ public class FHIRPathEngine {
return funcMemberOf(context, focus, exp);
case Trace:
return funcTrace(context, focus, exp);
case DefineVariable:
return funcDefineVariable(context, focus, exp);
case Check:
return funcCheck(context, focus, exp);
case Today:
@ -3853,8 +3925,6 @@ public class FHIRPathEngine {
return funcAllTrue(context, focus, exp);
case HasValue:
return funcHasValue(context, focus, exp);
case AliasAs:
return funcAliasAs(context, focus, exp);
case Encode:
return funcEncode(context, focus, exp);
case Decode:
@ -3869,8 +3939,6 @@ public class FHIRPathEngine {
return funcSplit(context, focus, exp);
case Join:
return funcJoin(context, focus, exp);
case Alias:
return funcAlias(context, focus, exp);
case HtmlChecks1:
return funcHtmlChecks1(context, focus, exp);
case HtmlChecks2:
@ -4427,24 +4495,6 @@ public class FHIRPathEngine {
return result;
}
private List<Base> funcAliasAs(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
context.addAlias(name, focus);
return focus;
}
private List<Base> funcAlias(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> res = new ArrayList<Base>();
Base b = context.getAlias(name);
if (b != null) {
res.add(b);
}
return res;
}
private List<Base> funcHtmlChecks1(ExecutionContext context, List<Base> focus, ExpressionNode exp)
throws FHIRException {
// todo: actually check the HTML
@ -4587,12 +4637,50 @@ public class FHIRPathEngine {
}
private ExecutionContext changeThis(ExecutionContext context, Base newThis) {
return new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
context.aliases, newThis);
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context,
newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionContext contextForParameter(ExecutionContext context) {
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.thisItem);
newContext.total = context.total;
newContext.index = context.index;
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
return new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private List<Base> funcNow(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
@ -5420,6 +5508,20 @@ public class FHIRPathEngine {
return focus;
}
private List<Base> funcDefineVariable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> value;
if (exp.getParameters().size() == 2) {
value = execute(context, focus, exp.getParameters().get(1), true);
} else {
value = focus;
}
// stash the variable into the context
context.setDefinedVariable(name, value);
return focus;
}
private List<Base> funcCheck(ExecutionContext context, List<Base> focus, ExpressionNode expr) throws FHIRException {
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
if (!convertToBoolean(n1)) {
@ -6281,7 +6383,7 @@ public class FHIRPathEngine {
sd = fetchStructureByType(element, expr);
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND,
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND,
element.getElement().getType().get(0).getProfile(), element.getElement().getId());
}
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());

View File

@ -420,7 +420,7 @@ public class CodeSystemUtilities {
}
// see http://hl7.org/fhir/R4/codesystem.html#hierachy
// returns additional parents not in the heirarchy
// returns additional parents not in the hierarchy
public static List<String> getOtherChildren(CodeSystem cs, ConceptDefinitionComponent c) {
List<String> res = new ArrayList<String>();
for (ConceptPropertyComponent p : c.getProperty()) {

View File

@ -22,13 +22,13 @@ import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.IniFile;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
public class TerminologyCacheManager {
@ -87,8 +87,7 @@ public class TerminologyCacheManager {
try {
System.out.println("Initialise terminology cache from " + source);
SimpleHTTPClient http = new SimpleHTTPClient();
HTTPResult res = http.get(source + "?nocache=" + System.currentTimeMillis());
HTTPResult res = ManagedWebAccess.get(source + "?nocache=" + System.currentTimeMillis());
res.checkThrowException();
unzip(new ByteArrayInputStream(res.getContent()), cacheFolder);
} catch (Exception e) {
@ -100,7 +99,7 @@ public class TerminologyCacheManager {
try (ZipInputStream zipIn = new ZipInputStream(is)) {
for (ZipEntry ze; (ze = zipIn.getNextEntry()) != null;) {
Path path = Path.of(Utilities.path(targetDir, ze.getName())).normalize();
String pathString = path.toFile().getAbsolutePath();
String pathString = ManagedFileAccess.fromPath(path).getAbsolutePath();
if (!path.startsWith(Path.of(targetDir).normalize())) {
// see: https://snyk.io/research/zip-slip-vulnerability
throw new RuntimeException("Entry with an illegal path: " + ze.getName());
@ -156,11 +155,10 @@ public class TerminologyCacheManager {
// post it to
String url = "https://tx.fhir.org/post/tx-cache/" + ghOrg + "/" + ghRepo + "/" + ghBranch + ".zip";
System.out.println("Sending tx-cache to " + url + " (" + Utilities.describeSize(bs.toByteArray().length) + ")");
SimpleHTTPClient http = new SimpleHTTPClient();
http.setAuthenticationMode(SimpleHTTPClient.AuthenticationMode.BASIC);
http.setUsername(token.substring(0, token.indexOf(':')));
http.setPassword(token.substring(token.indexOf(':') + 1));
HTTPResult res = http.put(url, "application/zip", bs.toByteArray(), null); // accept doesn't matter
HTTPResult res = ManagedWebAccess.builder()
.withBasicAuth(token.substring(0, token.indexOf(':')), token.substring(token.indexOf(':') + 1))
.withAccept("application/zip").put(url, bs.toByteArray(), null);
if (res.getCode() >= 300) {
System.out.println("sending cache failed: " + res.getCode());
} else {

View File

@ -702,7 +702,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
|| res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED
|| res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
if (warnings != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
warnings.add(context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system));
warnings.add(context.formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, system));
}
return null;
}

View File

@ -183,7 +183,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
private List<ValueSetExpansionContainsComponent> roots = new ArrayList<ValueSet.ValueSetExpansionContainsComponent>();
private Map<String, ValueSetExpansionContainsComponent> map = new HashMap<String, ValueSet.ValueSetExpansionContainsComponent>();
private IWorkerContext context;
private boolean canBeHeirarchy = true;
private boolean canBeHierarchy = true;
private boolean includeAbstract = true;
private Set<String> excludeKeys = new HashSet<String>();
private Set<String> excludeSystems = new HashSet<String>();
@ -238,13 +238,13 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
String s = key(n);
if (map.containsKey(s) || excludeKeys.contains(s)) {
canBeHeirarchy = false;
canBeHierarchy = false;
} else {
codes.add(n);
map.put(s, n);
total++;
}
if (canBeHeirarchy && parent != null) {
if (canBeHierarchy && parent != null) {
parent.getContains().add(n);
} else {
roots.add(n);
@ -446,7 +446,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
handleCompose(source.getCompose(), focus.getExpansion(), expParams, source.getUrl(),
focus.getExpansion().getExtension());
if (canBeHeirarchy) {
if (canBeHierarchy) {
for (ValueSetExpansionContainsComponent c : roots) {
focus.getExpansion().getContains().add(c);
}
@ -457,7 +457,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
// might be heirarchical, but later we
// gave up, so now ignore them
focus.getExpansion().getContains().add(c);
c.getContains().clear(); // make sure any heirarchy is wiped
c.getContains().clear(); // make sure any hierarchy is wiped
}
}
}
@ -493,15 +493,15 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
// Exclude comes first because we build up a map of things to exclude
for (ConceptSetComponent inc : compose.getExclude())
excludeCodes(inc, exp.getParameter(), ctxt);
canBeHeirarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty();
canBeHierarchy = !expParams.getParameterBool("excludeNested") && excludeKeys.isEmpty() && excludeSystems.isEmpty();
includeAbstract = !expParams.getParameterBool("excludeNotForUI");
boolean first = true;
for (ConceptSetComponent inc : compose.getInclude()) {
if (first == true)
first = false;
else
canBeHeirarchy = false;
includeCodes(inc, exp, expParams, canBeHeirarchy, extensions);
canBeHierarchy = false;
includeCodes(inc, exp, expParams, canBeHierarchy, extensions);
}
}
@ -540,8 +540,8 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
exp.getParameter().add(p);
}
copyExpansion(vso.getValueset().getExpansion().getContains());
canBeHeirarchy = false; // if we're importing a value set, we have to be combining, so we won't try for
// a heirarchy
canBeHierarchy = false; // if we're importing a value set, we have to be combining, so we won't try for
// a hierarchy
return vso.getValueset();
}
@ -681,7 +681,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
}
if (!inc.getConcept().isEmpty()) {
canBeHeirarchy = false;
canBeHierarchy = false;
for (ConceptReferenceComponent c : inc.getConcept()) {
c.checkNoModifiers("Code in Code System", "expanding");
ConceptDefinitionComponent def = CodeSystemUtilities.findCode(cs.getConcept(), c.getCode());
@ -705,7 +705,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
}
}
if (inc.getFilter().size() > 1) {
canBeHeirarchy = false; // which will bt the case if we get around to supporting this
canBeHierarchy = false; // which will bt the case if we get around to supporting this
throw failTSE("Multiple filters not handled yet"); // need to and them, and this isn't done yet. But this
// shouldn't arise in non loinc and snomed value sets
}
@ -745,7 +745,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
} else if ("display".equals(fc.getProperty()) && fc.getOp() == FilterOperator.EQUAL) {
// gg; note: wtf is this: if the filter is display=v, look up the code 'v', and
// see if it's diplsay is 'v'?
canBeHeirarchy = false;
canBeHierarchy = false;
ConceptDefinitionComponent def = getConceptForCode(cs.getConcept(), fc.getValue());
if (def != null) {
if (isNotBlank(def.getDisplay()) && isNotBlank(fc.getValue())) {

View File

@ -237,7 +237,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
try {
result = client.issuePutRequest(
resourceAddress.resolveGetUriFromResourceClassAndId(resource.getClass(), resource.getId()),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
getPreferredResourceFormat(), generateHeaders(), "Update " + resource.fhirType() + "/" + resource.getId(),
timeoutOperation);
if (result.isUnsuccessfulRequest()) {
@ -266,7 +266,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
ResourceRequest<T> result = null;
try {
result = client.issuePutRequest(resourceAddress.resolveGetUriFromResourceClassAndId(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
getPreferredResourceFormat(), generateHeaders(), "Update " + resource.fhirType() + "/" + id,
timeoutOperation);
if (result.isUnsuccessfulRequest()) {
@ -304,7 +304,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
ResourceRequest<T> result;
URI url = resourceAddress.resolveOperationURLFromClass(resourceClass, name, ps);
if (complex) {
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()));
byte[] body = ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true);
result = client.issuePostRequest(url, body, getPreferredResourceFormat(), generateHeaders(),
"POST " + resourceClass.getName() + "/$" + name, timeoutLong);
} else {
@ -333,7 +333,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
Bundle transactionResult = null;
try {
transactionResult = client.postBatchRequest(resourceAddress.getBaseServiceUri(),
ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(batch, false, isJson(getPreferredResourceFormat()), false),
getPreferredResourceFormat(), generateHeaders(), "transaction",
timeoutOperation + (timeoutEntry * batch.getEntry().size()));
} catch (Exception e) {
@ -347,7 +347,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
ResourceRequest<T> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveValidateUri(resourceClass, id),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(resource, false, isJson(getPreferredResourceFormat()), false),
getPreferredResourceFormat(), generateHeaders(),
"POST " + resourceClass.getName() + (id != null ? "/" + id : "") + "/$validate", timeoutLong);
if (result.isUnsuccessfulRequest()) {
@ -405,7 +405,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
org.hl7.fhir.r4b.utils.client.network.ResourceRequest<Resource> result = null;
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand"),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true), getPreferredResourceFormat(),
generateHeaders(), "ValueSet/$expand?url=" + source.getUrl(), timeoutExpand);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
@ -442,7 +442,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
try {
result = client.issuePostRequest(resourceAddress.resolveOperationUri(ValueSet.class, "expand", params),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat())), getPreferredResourceFormat(),
ByteUtils.resourceToByteArray(p, false, isJson(getPreferredResourceFormat()), true), getPreferredResourceFormat(),
generateHeaders(), "ValueSet/$expand?url=" + source.getUrl(), timeoutExpand);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
@ -465,7 +465,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
try {
result = client.issuePostRequest(
resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
getPreferredResourceFormat(), generateHeaders(), "Closure?name=" + name, timeoutNormal);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),
@ -485,7 +485,7 @@ public class FHIRToolingClient extends FHIRBaseToolingClient{
try {
result = client.issuePostRequest(
resourceAddress.resolveOperationUri(null, "closure", new HashMap<String, String>()),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat())),
ByteUtils.resourceToByteArray(params, false, isJson(getPreferredResourceFormat()), true),
getPreferredResourceFormat(), generateHeaders(), "UpdateClosure?name=" + name, timeoutOperation);
if (result.isUnsuccessfulRequest()) {
throw new EFhirClientException("Server returned error code " + result.getHttpStatus(),

View File

@ -15,7 +15,7 @@ import java.util.Map;
public class ByteUtils {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson) {
public static <T extends Resource> byte[] resourceToByteArray(T resource, boolean pretty, boolean isJson, boolean noXhtml) {
ByteArrayOutputStream baos = null;
byte[] byteArray = null;
try {
@ -27,6 +27,9 @@ public class ByteUtils {
parser = new XmlParser();
}
parser.setOutputStyle(pretty ? IParser.OutputStyle.PRETTY : IParser.OutputStyle.NORMAL);
if (noXhtml) {
parser.setSuppressXhtml("Narrative removed");
}
parser.compose(baos, resource);
baos.close();
byteArray = baos.toByteArray();

View File

@ -78,7 +78,6 @@ public class FhirRequestBuilder {
/**
* Adds necessary headers for all REST requests.
* <li>User-Agent : hapi-fhir-tooling-client</li>
* <li>Accept-Charset : {@link FhirRequestBuilder#DEFAULT_CHARSET}</li>
*
* @param request {@link Request.Builder} to add default headers to.
*/
@ -86,7 +85,6 @@ public class FhirRequestBuilder {
if (headers == null || !headers.names().contains("User-Agent")) {
request.addHeader("User-Agent", "hapi-fhir-tooling-client");
}
request.addHeader("Accept-Charset", DEFAULT_CHARSET);
}
/**

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.r4b.terminologies;
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
import org.hl7.fhir.utilities.tests.ResourceLoaderTests;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -26,13 +27,13 @@ public class TerminologyCacheManagerTests implements ResourceLoaderTests {
@BeforeAll
public void beforeAll() throws IOException {
tempDir = Files.createTempDirectory("terminology-cache-manager");
tempDir.resolve("child").toFile().mkdir();
ManagedFileAccess.fromPath(tempDir.resolve("child")).mkdir();
}
@Test
public void testNormalZip() throws IOException {
InputStream normalInputStream = getResourceAsInputStream("zip-slip", "zip-normal.zip");
TerminologyCacheManager.unzip(normalInputStream, tempDir.toFile().getAbsolutePath());
TerminologyCacheManager.unzip(normalInputStream, ManagedFileAccess.fromPath(tempDir).getAbsolutePath());
Path expectedFilePath = tempDir.resolve("zip-normal").resolve("depth1").resolve("test.txt");
String actualContent = Files.readString(expectedFilePath);
@ -51,7 +52,7 @@ public class TerminologyCacheManagerTests implements ResourceLoaderTests {
public void testLoadFromClasspathZipSlip(String fileName, String expectedMessage) {
RuntimeException thrown = Assertions.assertThrows(RuntimeException.class, () -> {
InputStream slipInputStream = getResourceAsInputStream("zip-slip", fileName);
TerminologyCacheManager.unzip(slipInputStream, tempDir.toFile().getAbsolutePath());
TerminologyCacheManager.unzip(slipInputStream, ManagedFileAccess.fromPath(tempDir).getAbsolutePath());
// Code under test
});
assertNotNull(thrown);

View File

@ -96,7 +96,7 @@ class ClientTest {
@Test
@DisplayName("PUT request, test payload received by server matches sent.")
void test_put() throws IOException, URISyntaxException, InterruptedException {
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false);
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false, false);
// Mock server response of 200, with the same resource payload returned that we
// included in the PUT request
server.enqueue(new MockResponse().setResponseCode(200).setBody(new String(payload)));
@ -111,7 +111,7 @@ class ClientTest {
@Test
@DisplayName("POST request, test payload received by server matches sent.")
void test_post() throws IOException, URISyntaxException, InterruptedException {
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false);
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false, false);
// Mock server response of 200, with the same resource payload returned that we
// included in the PUT request
server.enqueue(new MockResponse().setResponseCode(200).setBody(new String(payload)));
@ -126,7 +126,7 @@ class ClientTest {
@Test
@DisplayName("Testing the logger works.")
void test_logger() throws IOException, URISyntaxException, InterruptedException {
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false);
byte[] payload = ByteUtils.resourceToByteArray(patient, true, false, false);
server.enqueue(new MockResponse().setResponseCode(200).setBody(new String(payload)));
HTMLClientLogger mockLogger = Mockito.mock(HTMLClientLogger.class);
client.setLogger(mockLogger);

View File

@ -26,9 +26,6 @@ class FhirRequestBuilderTest {
Assertions.assertEquals("hapi-fhir-tooling-client", headersMap.get("User-Agent").get(0),
"User-Agent header not populated with expected value \"hapi-fhir-tooling-client\".");
Assertions.assertNotNull(headersMap.get("Accept-Charset"), "Accept-Charset header null.");
Assertions.assertEquals(FhirRequestBuilder.DEFAULT_CHARSET, headersMap.get("Accept-Charset").get(0),
"Accept-Charset header not populated with expected value " + FhirRequestBuilder.DEFAULT_CHARSET);
}
@Test

View File

@ -5,7 +5,7 @@
<parent>
<groupId>ca.uhn.hapi.fhir</groupId>
<artifactId>org.hl7.fhir.core</artifactId>
<version>6.3.4</version>
<version>6.3.11-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -176,7 +176,6 @@
<dependency>
<groupId>com.nimbusds</groupId>
<artifactId>nimbus-jose-jwt</artifactId>
<version>9.30.2</version>
</dependency>
<dependency>

View File

@ -25,6 +25,8 @@ import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
public class ComparisonSession {
@ -39,8 +41,9 @@ public class ComparisonSession {
private String title;
private ProfileKnowledgeProvider pkpLeft;
private ProfileKnowledgeProvider pkpRight;
private RenderingI18nContext i18n;
public ComparisonSession(IWorkerContext contextLeft, IWorkerContext contextRight, String title, ProfileKnowledgeProvider pkpLeft, ProfileKnowledgeProvider pkpRight) {
public ComparisonSession(RenderingI18nContext i18n, IWorkerContext contextLeft, IWorkerContext contextRight, String title, ProfileKnowledgeProvider pkpLeft, ProfileKnowledgeProvider pkpRight) {
super();
this.contextLeft = contextLeft;
this.contextRight = contextRight;
@ -48,6 +51,7 @@ public class ComparisonSession {
this.title = title;
this.pkpLeft = pkpLeft;
this.pkpRight = pkpRight;
this.i18n = i18n;
debug = false;
}
@ -175,6 +179,10 @@ public class ComparisonSession {
return annotate;
}
public RenderingI18nContext getI18n() {
return i18n;
}
public void setAnnotate(boolean annotate) {
this.annotate = annotate;
}

View File

@ -42,7 +42,6 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
import org.hl7.fhir.r5.utils.DefinitionNavigator;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.RenderingI18nContext;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.utilities.validation.ValidationMessage.IssueSeverity;
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
@ -1252,7 +1251,7 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
}
public XhtmlNode renderStructure(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(new RenderingI18nContext(), Utilities.path("[tmp]", "compare"), false, true);
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(session.getI18n(), Utilities.path("[tmp]", "compare"), false, true);
TableModel model = gen.initComparisonTable(corePath, id);
genElementComp(null /* come back to this later */, gen, model.getRows(), comp.combined, corePath, prefix, null, true);
return gen.generate(model, prefix, 0, null);
@ -1289,32 +1288,32 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
boolean ext = false;
if (tail(path).equals("extension")) {
if (elementIsComplex(combined))
row.setIcon("icon_extension_complex.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_COMPLEX);
row.setIcon("icon_extension_complex.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_COMPLEX));
else
row.setIcon("icon_extension_simple.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_SIMPLE);
row.setIcon("icon_extension_simple.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_SIMPLE));
ext = true;
} else if (tail(path).equals("modifierExtension")) {
if (elementIsComplex(combined))
row.setIcon("icon_modifier_extension_complex.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_COMPLEX);
row.setIcon("icon_modifier_extension_complex.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_COMPLEX));
else
row.setIcon("icon_modifier_extension_simple.png", HierarchicalTableGenerator.TEXT_ICON_EXTENSION_SIMPLE);
row.setIcon("icon_modifier_extension_simple.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_EXTENSION_SIMPLE));
} else if (hasChoice(combined)) {
if (allAreReference(combined))
row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE);
row.setIcon("icon_reference.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_REFERENCE));
else {
row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE);
row.setIcon("icon_choice.gif", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_CHOICE));
typesRow = row;
}
} else if (combined.either().getDef().hasContentReference())
row.setIcon("icon_reuse.png", HierarchicalTableGenerator.TEXT_ICON_REUSE);
row.setIcon("icon_reuse.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_REUSE));
else if (isPrimitive(combined))
row.setIcon("icon_primitive.png", HierarchicalTableGenerator.TEXT_ICON_PRIMITIVE);
row.setIcon("icon_primitive.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_PRIMITIVE));
else if (hasTarget(combined))
row.setIcon("icon_reference.png", HierarchicalTableGenerator.TEXT_ICON_REFERENCE);
row.setIcon("icon_reference.png", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_REFERENCE));
else if (isDataType(combined))
row.setIcon("icon_datatype.gif", HierarchicalTableGenerator.TEXT_ICON_DATATYPE);
row.setIcon("icon_datatype.gif", session.getI18n().formatPhrase(RenderingContext.TEXT_ICON_DATATYPE));
else
row.setIcon("icon_resource.png", HierarchicalTableGenerator.TEXT_ICON_RESOURCE);
row.setIcon("icon_resource.png", session.getI18n().formatPhrase(RenderingContext.GENERAL_RESOURCE));
String ref = defPath == null ? null : defPath + combined.either().getDef().getId();
String sName = tail(path);
String sn = getSliceName(combined);
@ -1335,12 +1334,12 @@ public class StructureDefinitionComparer extends CanonicalResourceComparer imple
nc = sdrRight.genElementNameCell(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, false, ext, used , ref, sName, null);
}
if (combined.hasLeft()) {
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, null, children.size() > 0), leftColor);
frame(sdrLeft.genElementCells(gen, combined.getLeft().getDef(), "??", true, corePath, prefix, root, false, false, combined.getLeft().getSrc(), typesRow, row, true, ext, used , ref, sName, nc, false, false, sdrLeft.getContext(), children.size() > 0), leftColor);
} else {
frame(spacers(row, 4, gen), leftColor);
}
if (combined.hasRight()) {
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, null, children.size() > 0), rightColor);
frame(sdrRight.genElementCells(gen, combined.getRight().getDef(), "??", true, corePath, prefix, root, false, false, combined.getRight().getSrc(), typesRow, row, true, ext, used, ref, sName, nc, false, false, sdrRight.getContext(), children.size() > 0), rightColor);
} else {
frame(spacers(row, 4, gen), rightColor);
}

View File

@ -559,7 +559,7 @@ public class ProfilePathProcessor {
}
}
if (!allowedTypes.isEmpty()) {
if (currentBasePath.contains("xtension.value")) {
if (currentBasePath.contains("xtension.value") && shortCut) {
for (Iterator<ElementDefinition.TypeRefComponent> iter = elementDefinition.getType().iterator(); iter.hasNext(); ) {
ElementDefinition.TypeRefComponent tr = iter.next();
if (allowedTypes.contains(tr.getCode())) {
@ -595,7 +595,8 @@ public class ProfilePathProcessor {
} else if (diffMatches.get(0).hasType()
&& diffMatches.get(0).getType().size() == 1
&& diffMatches.get(0).getType().get(0).hasProfile()
&& !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
&& !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())
&& !(currentBase.getType().get(0).hasProfile() && currentBase.getType().get(0).getProfile().get(0).primitiveValue().equals(diffMatches.get(0).getType().get(0).getProfile().get(0).primitiveValue()))) {
CanonicalType firstTypeProfile = diffMatches.get(0).getType().get(0).getProfile().get(0);
StructureDefinition firstTypeStructureDefinition = profileUtilities.getContext().fetchResource(StructureDefinition.class, firstTypeProfile.getValue());
if (firstTypeStructureDefinition == null && profileUtilities.getXver() != null && profileUtilities.getXver().matchingUrl(firstTypeProfile.getValue())) {

View File

@ -700,9 +700,11 @@ public class ProfileUtilities {
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE__FOR_, base.getBaseDefinition(), base.getUrl()));
checkNotGenerating(sdb, "an extension base");
generateSnapshot(sdb, base, base.getUrl(), (sdb.hasWebPath()) ? Utilities.extractBaseUrl(sdb.getWebPath()) : webUrl, base.getName());
}
fixTypeOfResourceId(base);
if (base.hasExtension(ToolingExtensions.EXT_TYPE_PARAMETER)) {
checkTypeParameters(base, derived);
}
if (snapshotStack.contains(derived.getUrl())) {
throw new DefinitionException(context.formatMessage(I18nConstants.CIRCULAR_SNAPSHOT_REFERENCES_DETECTED_CANNOT_GENERATE_SNAPSHOT_STACK__, snapshotStack.toString()));
@ -976,6 +978,29 @@ public class ProfileUtilities {
}
private void checkTypeParameters(StructureDefinition base, StructureDefinition derived) {
String bt = ToolingExtensions.readStringExtension(base, ToolingExtensions.EXT_TYPE_PARAMETER);
if (!derived.hasExtension(ToolingExtensions.EXT_TYPE_PARAMETER)) {
throw new DefinitionException(context.formatMessage(I18nConstants.SD_TYPE_PARAMETER_MISSING, base.getVersionedUrl(), bt, derived.getVersionedUrl()));
}
String dt = ToolingExtensions.readStringExtension(derived, ToolingExtensions.EXT_TYPE_PARAMETER);
StructureDefinition bsd = context.fetchTypeDefinition(bt);
StructureDefinition dsd = context.fetchTypeDefinition(dt);
if (bsd == null) {
throw new DefinitionException(context.formatMessage(I18nConstants.SD_TYPE_PARAMETER_UNKNOWN, base.getVersionedUrl(), bt));
}
if (dsd == null) {
throw new DefinitionException(context.formatMessage(I18nConstants.SD_TYPE_PARAMETER_UNKNOWN, derived.getVersionedUrl(), dt));
}
StructureDefinition t = dsd;
while (t != bsd && t != null) {
t = context.fetchResource(StructureDefinition.class, t.getBaseDefinition());
}
if (t == null) {
throw new DefinitionException(context.formatMessage(I18nConstants.SD_TYPE_PARAMETER_INVALID, base.getVersionedUrl(), bt, derived.getVersionedUrl(), dt));
}
}
private XVerExtensionManager makeXVer() {
if (xver == null) {
xver = new XVerExtensionManager(context);

View File

@ -76,6 +76,7 @@ import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.IdType;
import org.hl7.fhir.r5.model.Identifier;
import org.hl7.fhir.r5.model.IntegerType;
@ -124,6 +125,7 @@ import org.hl7.fhir.r5.terminologies.utilities.TerminologyOperationContext.Termi
import org.hl7.fhir.r5.terminologies.utilities.TerminologyServiceErrorClass;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.CacheToken;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedCodeSystem;
import org.hl7.fhir.r5.terminologies.utilities.TerminologyCache.SourcedValueSet;
import org.hl7.fhir.r5.terminologies.validation.VSCheckerException;
import org.hl7.fhir.r5.terminologies.validation.ValueSetValidator;
@ -157,9 +159,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
class OIDSource {
private String folder;
private Connection db;
protected OIDSource(String folder) {
private String pid;
protected OIDSource(String folder, String pid) {
super();
this.folder = folder;
this.pid = pid;
}
}
@ -261,7 +265,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private UcumService ucumService;
protected Map<String, byte[]> binaries = new HashMap<String, byte[]>();
protected Map<String, Set<String>> oidCacheManual = new HashMap<>();
protected Map<String, Set<OIDDefinition>> oidCacheManual = new HashMap<>();
protected List<OIDSource> oidSources = new ArrayList<>();
protected Map<String, Map<String, ValidationResult>> validationCache = new HashMap<String, Map<String,ValidationResult>>();
@ -273,7 +277,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected boolean canRunWithoutTerminology;
protected boolean noTerminologyServer;
private int expandCodesLimit = 1000;
protected ILoggingService logger = new SystemOutLoggingService();
protected org.hl7.fhir.r5.context.ILoggingService logger = new SystemOutLoggingService();
protected Parameters expParameters;
private Map<String, PackageInformation> packages = new HashMap<>();
@ -495,7 +499,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (!oidCacheManual.containsKey(s)) {
oidCacheManual.put(s, new HashSet<>());
}
oidCacheManual.get(s).add(url);
oidCacheManual.get(s).add(new OIDDefinition(r.fhirType(), s, url, ((CanonicalResource) r).getVersion(), null));
}
}
}
@ -803,7 +807,10 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
public boolean isServerSideSystem(String url) {
boolean check = supportsSystem(url);
return check && supportedCodeSystems.contains(url);
}
protected void txLog(String msg) {
@ -1073,9 +1080,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (!options.isUseServer()) {
t.setResult(new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, null));
} else if (unsupportedCodeSystems.contains(codeKey)) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, null));
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, null));
} else if (noTerminologyServer) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, null));
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, t.getCoding().getCode(), t.getCoding().getSystem()), TerminologyServiceErrorClass.NOSERVICE, null));
}
}
}
@ -1181,9 +1188,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (!options.isUseServer()) {
t.setResult(new ValidationResult(IssueSeverity.WARNING,formatMessage(I18nConstants.UNABLE_TO_VALIDATE_CODE_WITHOUT_USING_SERVER), TerminologyServiceErrorClass.BLOCKED_BY_OPTIONS, null));
} else if (unsupportedCodeSystems.contains(codeKey)) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, null));
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, t.getCoding().getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, null));
} else if (noTerminologyServer) {
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, null));
t.setResult(new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, t.getCoding().getCode(), t.getCoding().getSystem()), TerminologyServiceErrorClass.NOSERVICE, null));
}
}
}
@ -1334,12 +1341,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
String codeKey = getCodeKey(code);
if (unsupportedCodeSystems.contains(codeKey)) {
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, code.getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues);
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.UNKNOWN_CODESYSTEM, code.getSystem()), TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED, issues);
}
// if that failed, we try to validate on the server
if (noTerminologyServer) {
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES), TerminologyServiceErrorClass.NOSERVICE, issues);
return new ValidationResult(IssueSeverity.ERROR,formatMessage(I18nConstants.ERROR_VALIDATING_CODE_RUNNING_WITHOUT_TERMINOLOGY_SERVICES, code.getCode(), code.getSystem()), TerminologyServiceErrorClass.NOSERVICE, issues);
}
Set<String> systems = findRelevantSystems(code, vs);
@ -1476,9 +1483,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected Parameters constructParameters(ValidationOptions options, Coding coding) {
Parameters pIn = new Parameters();
pIn.addParameter().setName("coding").setValue(coding);
if (options.isGuessSystem()) {
pIn.addParameter().setName("inferSystem").setValue(new BooleanType(true));
pIn.addParameter().setName("code").setValue(coding.getCodeElement());
} else {
pIn.addParameter().setName("coding").setValue(coding);
}
setTerminologyOptions(options, pIn);
return pIn;
@ -1493,9 +1502,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected Parameters constructParameters(ValidationOptions options, CodingValidationRequest codingValidationRequest, ValueSet valueSet) {
Parameters pIn = new Parameters();
pIn.addParameter().setName("coding").setValue(codingValidationRequest.getCoding());
if (options.isGuessSystem()) {
pIn.addParameter().setName("inferSystem").setValue(new BooleanType(true));
pIn.addParameter().setName("code").setValue(codingValidationRequest.getCoding().getCodeElement());
} else {
pIn.addParameter().setName("coding").setValue(codingValidationRequest.getCoding());
}
if (valueSet != null) {
pIn.addParameter().setName("valueSet").setResource(valueSet);
@ -1507,9 +1518,11 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected Parameters constructParameters(ValidationOptions options, CodingValidationRequest codingValidationRequest, String vsUrl) {
Parameters pIn = new Parameters();
pIn.addParameter().setName("coding").setValue(codingValidationRequest.getCoding());
if (options.isGuessSystem()) {
pIn.addParameter().setName("inferSystem").setValue(new BooleanType(true));
pIn.addParameter().setName("code").setValue(codingValidationRequest.getCoding().getCodeElement());
} else {
pIn.addParameter().setName("coding").setValue(codingValidationRequest.getCoding());
}
if (vsUrl != null) {
pIn.addParameter().setName("url").setValue(new CanonicalType(vsUrl));
@ -1775,12 +1788,25 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (vs != null && !hasCanonicalResource(pin, "tx-resource", vs.getVUrl())) {
cache = checkAddToParams(tc, pin, vs) || cache;
addDependentResources(tc, pin, vs);
for (Extension ext : vs.getExtensionsByUrl(ToolingExtensions.EXT_VS_CS_SUPPL_NEEDED)) {
if (ext.hasValueCanonicalType()) {
String url = ext.getValueCanonicalType().asStringValue();
CodeSystem supp = fetchResource(CodeSystem.class, url);
if (supp != null) {
cache = checkAddToParams(tc, pin, supp) || cache;
}
}
}
}
}
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src);
if (cs != null && !hasCanonicalResource(pin, "tx-resource", cs.getVUrl()) && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
cache = checkAddToParams(tc, pin, cs) || cache;
// todo: supplements
}
for (CodeSystem supp : fetchResourcesByType(CodeSystem.class)) {
if (supp.getContent() == CodeSystemContentMode.SUPPLEMENT && supp.getSupplements().equals(inc.getSystem())) {
cache = checkAddToParams(tc, pin, supp) || cache;
}
}
return cache;
}
@ -1965,7 +1991,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
this.canRunWithoutTerminology = canRunWithoutTerminology;
}
public void setLogger(@Nonnull ILoggingService logger) {
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger) {
this.logger = logger;
}
@ -2515,7 +2541,8 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
String[] parts = uri.split("\\/");
if (!Utilities.noString(type) && parts.length == 1) {
if (allResourcesById.containsKey(type)) {
return allResourcesById.get(type).get(parts[0]).getResource();
ResourceProxy res = allResourcesById.get(type).get(parts[0]);
return res == null ? null : res.getResource();
} else {
return null;
}
@ -2789,7 +2816,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
@Override
public ILoggingService getLogger() {
public org.hl7.fhir.r5.context.ILoggingService getLogger() {
return logger;
}
@ -3094,62 +3121,67 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
@Override
public Set<String> urlsForOid(boolean codeSystem, String oid) {
Set<String> set = urlsForOid(codeSystem, oid, true);
if (set.size() > 1) {
set = urlsForOid(codeSystem, oid, false);
public OIDSummary urlsForOid(String oid, String resourceType) {
OIDSummary set = urlsForOid(oid, resourceType, true);
if (set.getDefinitions().size() > 1) {
set = urlsForOid(oid, resourceType, false);
}
return set;
}
public Set<String> urlsForOid(boolean codeSystem, String oid, boolean retired) {
if (oid == null) {
return null;
}
Set<String> urls = new HashSet<>();
if (oidCacheManual.containsKey(oid)) {
urls.addAll(oidCacheManual.get(oid));
}
for (OIDSource os : oidSources) {
if (os.db == null) {
os.db = connectToOidSource(os.folder);
public OIDSummary urlsForOid(String oid, String resourceType, boolean retired) {
OIDSummary summary = new OIDSummary();
if (oid != null) {
if (oidCacheManual.containsKey(oid)) {
summary.addOIDs(oidCacheManual.get(oid));
}
if (os.db != null) {
try {
PreparedStatement psql = os.db.prepareStatement("Select URL, Status from OIDMap where OID = ?");
psql.setString(1, oid);
ResultSet rs = psql.executeQuery();
while (rs.next()) {
if (retired || !"retired".equals(rs.getString(2))) {
urls.add(rs.getString(1));
}
}
} catch (Exception e) {
// nothing, there would alreagy have been an error
// e.printStackTrace();
for (OIDSource os : oidSources) {
if (os.db == null) {
os.db = connectToOidSource(os.folder);
}
if (os.db != null) {
try {
PreparedStatement psql = resourceType == null ?
os.db.prepareStatement("Select TYPE, URL, VERSION, Status from OIDMap where OID = ?") :
os.db.prepareStatement("Select TYPE, URL, VERSION, Status from OIDMap where TYPE = '"+resourceType+"' and OID = ?");
psql.setString(1, oid);
ResultSet rs = psql.executeQuery();
while (rs.next()) {
if (retired || !"retired".equals(rs.getString(4))) {
String rt = rs.getString(1);
String url = rs.getString(2);
String version = rs.getString(3);
summary.addOID(new OIDDefinition(rt, oid, url, version, os.pid));
}
}
} catch (Exception e) {
// nothing, there would alreagy have been an error
// e.printStackTrace();
}
}
}
switch (oid) {
case "2.16.840.1.113883.6.1" :
summary.addOID(new OIDDefinition("CodeSystem", "2.16.840.1.113883.6.1", "http://loinc.org", null, null));
break;
case "2.16.840.1.113883.6.8" :
summary.addOID(new OIDDefinition("CodeSystem", "2.16.840.1.113883.6.8", "http://unitsofmeasure.org", null, null));
break;
case "2.16.840.1.113883.6.96" :
summary.addOID(new OIDDefinition("CodeSystem", "2.16.840.1.113883.6.96", "http://snomed.info/sct", null, null));
break;
default:
}
}
switch (oid) {
case "2.16.840.1.113883.6.1" :
urls.add("http://loinc.org");
break;
case "2.16.840.1.113883.6.8" :
urls.add("http://unitsofmeasure.org");
break;
case "2.16.840.1.113883.6.96" :
urls.add("http://snomed.info/sct");
break;
default:
}
return urls;
summary.sort();
return summary;
}
private Connection connectToOidSource(String folder) {
try {
File ff = ManagedFileAccess.file(folder);
File of = ManagedFileAccess.file(Utilities.path(ff.getAbsolutePath(), ".oid-map.db"));
File of = ManagedFileAccess.file(Utilities.path(ff.getAbsolutePath(), ".oid-map-2.db"));
if (!of.exists()) {
OidIndexBuilder oidBuilder = new OidIndexBuilder(ff, of);
oidBuilder.build();
@ -3210,6 +3242,28 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
cacheResource(svs.getVs());
return (T) svs.getVs();
}
} else if (class_ == CodeSystem.class) {
SourcedCodeSystem scs = null;
if (txCache.hasCodeSystem(canonical)) {
scs = txCache.getCodeSystem(canonical);
} else {
scs = terminologyClientManager.findCodeSystemOnServer(canonical);
txCache.cacheCodeSystem(canonical, scs);
}
if (scs != null) {
String web = ToolingExtensions.readStringExtension(scs.getCs(), ToolingExtensions.EXT_WEB_SOURCE);
if (web == null) {
web = Utilities.pathURL(scs.getServer(), "ValueSet", scs.getCs().getIdBase());
}
scs.getCs().setWebPath(web);
scs.getCs().setUserData("External.Link", scs.getServer()); // so we can render it differently
}
if (scs == null) {
return null;
} else {
cacheResource(scs.getCs());
return (T) scs.getCs();
}
} else {
throw new Error("Not supported");
}

View File

@ -2,8 +2,12 @@ package org.hl7.fhir.r5.context;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
/*
Copyright (c) 2011+, HL7, Inc.
@ -45,6 +49,8 @@ import org.fhir.ucum.UcumService;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinition;
import org.hl7.fhir.r5.context.IWorkerContext.OIDDefinitionComparer;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.formats.IParser;
import org.hl7.fhir.r5.formats.ParserType;
@ -70,6 +76,7 @@ import org.hl7.fhir.r5.terminologies.utilities.CodingValidationRequest;
import org.hl7.fhir.r5.terminologies.utilities.ValidationResult;
import org.hl7.fhir.r5.utils.validation.IResourceValidator;
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.FhirPublication;
import org.hl7.fhir.utilities.TimeTracker;
import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
@ -102,6 +109,133 @@ import javax.annotation.Nonnull;
public interface IWorkerContext {
/**
@deprecated This interface only exists to provide backward compatibility for the following two projects:
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
<a href="https://github.com/cqframework/clinical_quality_language/">clinical_quality-language</a>
Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards
compatibility with core version 6.1.2.2
**/
@Deprecated(forRemoval = true)
public interface ILoggingService extends org.hl7.fhir.r5.context.ILoggingService{
}
public class OIDDefinitionComparer implements Comparator<OIDDefinition> {
@Override
public int compare(OIDDefinition o1, OIDDefinition o2) {
if (o1.getUrl().equals(o2.getUrl())) {
return -o1.getVersion().compareTo(o2.getVersion());
} else {
return o1.getUrl().compareTo(o2.getUrl());
}
}
}
public class OIDDefinition {
private String type;
private String oid;
private String url;
private String version;
private String packageSrc;
protected OIDDefinition(String type, String oid, String url, String version, String packageSrc) {
super();
this.type = type;
this.oid = oid;
this.url = url;
this.version = version == null ? "" : version;
this.packageSrc = packageSrc;
}
public String getType() {
return type;
}
public String getOid() {
return oid;
}
public String getUrl() {
return url;
}
public String getVersion() {
return version;
}
public String getPackageSrc() {
return packageSrc;
}
public String summary() {
return url+(version == null ? "" : "|"+version)+(packageSrc != null ? "("+packageSrc+")" : "");
}
public boolean matches(OIDDefinition t) {
return url.equals(t.url) && version.equals(t.version);
}
}
public class OIDSummary {
private List<OIDDefinition> definitions = new ArrayList<>();
private List<String> urls = new ArrayList<>();
public void addOID(OIDDefinition d) {
for (OIDDefinition t : definitions) {
if (d.matches(t)) {
return;
}
}
definitions.add(d);
if (!urls.contains(d.getUrl())) {
urls.add(d.getUrl());
}
}
public void addOIDs(Collection<OIDDefinition> collection) {
for (OIDDefinition t : collection) {
addOID(t);
}
}
public List<OIDDefinition> getDefinitions() {
return definitions;
}
public void sort() {
Collections.sort(definitions, new OIDDefinitionComparer());
Collections.sort(urls);
}
public String describe() {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (OIDDefinition d : definitions) {
b.append(d.summary());
}
return b.toString();
}
public String chooseBestUrl() {
for (OIDDefinition d : definitions) {
if (d.getPackageSrc() == null) {
return d.getUrl();
}
}
for (OIDDefinition d : definitions) {
if (d.getUrl().startsWith("http://hl7.org/fhir/")) {
return d.getUrl();
}
}
for (OIDDefinition d : definitions) {
if (!d.getUrl().contains("vsac")) {
return d.getUrl();
}
}
return null;
}
public int urlCount() {
return urls.size();
}
public String getUrl() {
return urls.iterator().next();
}
}
/**
* Get the version of the base definitions loaded in context
* This *does not* have to be 5.0 (R5) - the context can load other versions
@ -508,8 +642,8 @@ public interface IWorkerContext {
// todo: figure these out
public Map<String, NamingSystem> getNSUrlMap();
public void setLogger(@Nonnull ILoggingService logger);
public ILoggingService getLogger();
public void setLogger(@Nonnull org.hl7.fhir.r5.context.ILoggingService logger);
public org.hl7.fhir.r5.context.ILoggingService getLogger();
public boolean isNoTerminologyServer();
public Set<String> getCodeSystemsUsed();
@ -634,7 +768,13 @@ public interface IWorkerContext {
public boolean isForPublication();
public void setForPublication(boolean value);
public Set<String> urlsForOid(boolean codeSystem, String oid);
/**
*
* @param oid
* @param resourceType - null to search on all resource types
* @return
*/
public OIDSummary urlsForOid(String oid, String resourceType);
/**
* this first does a fetch resource, and if nothing is found, looks in the
@ -656,4 +796,6 @@ public interface IWorkerContext {
*/
public Boolean subsumes(ValidationOptions options, Coding parent, Coding child);
public boolean isServerSideSystem(String url);
}

View File

@ -6,6 +6,7 @@ import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.HashSet;
import java.util.Set;
@ -33,11 +34,13 @@ public class OidIndexBuilder {
Statement stmt = db.createStatement();
stmt.execute("CREATE TABLE OIDMap (\r\n"+
"OID nvarchar NOT NULL,\r\n"+
"TYPE nvarchar NOT NULL,\r\n"+
"URL nvarchar NOT NULL,\r\n"+
"VERSION nvarchar NOT NULL,\r\n"+
"Status nvarchar NOT NULL,\r\n"+
"PRIMARY KEY (OID, URL))\r\n");
PreparedStatement psql = db.prepareStatement("Insert into OIDMap (OID, URL, Status) values (?, ?, ?)");;
PreparedStatement psql = db.prepareStatement("Insert into OIDMap (OID, TYPE, URL, VERSION, Status) values (?, ?, ?, ?, ?)");
for (File f : folder.listFiles()) {
if (!f.getName().startsWith(".") && f.getName().endsWith(".json")) {
try {
@ -61,6 +64,7 @@ public class OidIndexBuilder {
Set<String> oids = new HashSet<String>();
String url = null;
String status = json.asString("status");
String version = json.asString("version");
if ("NamingSystem".equals(rt)) {
for (JsonObject id : json.getJsonObjects("uniqueId")) {
String t = id.asString("type");
@ -73,7 +77,7 @@ public class OidIndexBuilder {
}
if (url != null) {
for (String s : oids) {
addOid(psql, matches, s, url, status);
addOid(psql, matches, s, rt, url, version, status);
}
}
} else {
@ -97,7 +101,7 @@ public class OidIndexBuilder {
}
if (!oids.isEmpty()) {
for (String s : oids) {
addOid(psql, matches, s, url, status);
addOid(psql, matches, s, rt, url, version, status);
}
}
}
@ -105,13 +109,19 @@ public class OidIndexBuilder {
}
}
private void addOid(PreparedStatement psql, Set<String> matches, String oid, String url, String status) throws SQLException {
private void addOid(PreparedStatement psql, Set<String> matches, String oid, String type, String url, String version, String status) throws SQLException {
String key = oid+"@"+url;
if (!matches.contains(key)) {
matches.add(key);
psql.setString(1, oid);
psql.setString(2, url);
psql.setString(3, status);
psql.setString(2, type);
psql.setString(3, url);
if (version == null) {
psql.setNull(4, Types.NVARCHAR);
} else {
psql.setString(4, version);
}
psql.setString(5, status);
psql.execute();
}

View File

@ -214,7 +214,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
private final boolean allowLoadingDuplicates;
@With
private final ILoggingService loggingService;
private final org.hl7.fhir.r5.context.ILoggingService loggingService;
public SimpleWorkerContextBuilder() {
cacheTerminologyClientErrors = false;
@ -332,12 +332,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
loadBytes(name, stream);
}
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client) {
public void connectToTSServer(ITerminologyClientFactory factory, ITerminologyClient client, boolean useEcosystem) {
terminologyClientManager.setFactory(factory);
if (txLog == null) {
txLog = client.getLogger();
}
TerminologyClientContext tcc = terminologyClientManager.setMasterClient(client);
TerminologyClientContext tcc = terminologyClientManager.setMasterClient(client, useEcosystem);
txLog("Connect to "+client.getAddress());
try {
tcc.initialize();
@ -357,7 +357,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
}
public void connectToTSServer(ITerminologyClientFactory factory, String address, String software, String log) {
public void connectToTSServer(ITerminologyClientFactory factory, String address, String software, String log, boolean useEcosystem) {
try {
terminologyClientManager.setFactory(factory);
if (log != null && (log.endsWith(".htm") || log.endsWith(".html"))) {
@ -369,7 +369,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
// txFactory.makeClient("Tx-Server", txServer, "fhir/publisher", null)
// terminologyClientManager.setLogger(txLog);
// terminologyClientManager.setUserAgent(userAgent);
connectToTSServer(factory, client);
connectToTSServer(factory, client, useEcosystem);
} catch (Exception e) {
e.printStackTrace();
@ -509,7 +509,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
String of = pi.getFolders().get("package").getFolderPath();
if (of != null) {
oidSources.add(new OIDSource(of));
oidSources.add(new OIDSource(of, pi.vid()));
}
if ((types == null || types.size() == 0) && loader != null) {

View File

@ -165,6 +165,10 @@ public class JsonParser extends ParserBase {
}
public Element parse(List<ValidationMessage> errors, JsonObject object) throws FHIRException {
return parse(errors, object, null);
}
public Element parse(List<ValidationMessage> errors, JsonObject object, String statedPath) throws FHIRException {
if (object == null) {
System.out.println("What?");
}
@ -187,16 +191,16 @@ public class JsonParser extends ParserBase {
return null;
}
}
path = name;
path = statedPath == null ? name : statedPath;
} else {
name = sd.getType();
path = sd.getTypeTail();
path = statedPath == null ? sd.getTypeTail() : statedPath;
}
baseElement = new Element(name, new Property(context, sd.getSnapshot().getElement().get(0), sd, this.getProfileUtilities(), this.getContextUtilities())).setFormat(FhirFormat.JSON);
checkObject(errors, object, baseElement, path);
baseElement.markLocation(line(object), col(object));
baseElement.setType(name);
baseElement.setPath(baseElement.fhirTypeRoot());
baseElement.setPath(statedPath == null ? baseElement.fhirTypeRoot() : statedPath);
parseChildren(errors, path, object, baseElement, true, null);
baseElement.numberChildren();
return baseElement;
@ -273,7 +277,7 @@ public class JsonParser extends ParserBase {
} else {
JsonProperty p = getFoundJsonPropertyByName(e.getName(), children);
if (p != null) {
logError(errors, "2022-11-26", line(e.getValue()), col(e.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY, e.getName()), IssueSeverity.ERROR);
logError(errors, "2022-11-26", line(e.getValue()), col(e.getValue()), path, IssueType.INVALID, context.formatMessage(I18nConstants.DUPLICATE_JSON_PROPERTY_KEY, e.getName()), IssueSeverity.ERROR);
} else {
logError(errors, ValidationMessage.NO_RULE_DATE, line(e.getValue()), col(e.getValue()), path, IssueType.STRUCTURE, context.formatMessage(I18nConstants.UNRECOGNISED_PROPERTY_, e.getName()), IssueSeverity.ERROR);
}

View File

@ -19,10 +19,14 @@ import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionConstraintComponent;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.MarkdownType;
import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.i18n.AcceptLanguageHeader;
@ -55,8 +59,9 @@ public class LanguageUtils {
private static final String ORPHAN_TRANSLATIONS_NAME = "translations.orphans";
private static final String SUPPLEMENT_NAME = "translations.supplement";
private static final String SUPPLEMENT_SOURCE_RESOURCE = "translations.supplemented";
private static final String SUPPLEMENT_SOURCE_TRANSLATIONS = "translations.source-list";
IWorkerContext context;
private List<String> crlist;
@ -124,13 +129,17 @@ public class LanguageUtils {
}
private String pathForElement(Element element) {
String bp = element.getBasePath();
return pathForElement(bp, element.getProperty().getStructure().getType());
}
private String pathForElement(String path, String type) {
// special case support for metadata elements prior to R5:
if (crlist == null) {
crlist = new ContextUtilities(context).getCanonicalResourceNames();
}
String bp = element.getBasePath();
if (crlist.contains(element.getProperty().getStructure().getType())) {
String fp = bp.replace(element.getProperty().getStructure().getType()+".", "CanonicalResource.");
if (crlist.contains(type)) {
String fp = path.replace(type+".", "CanonicalResource.");
if (Utilities.existsInList(fp,
"CanonicalResource.url", "CanonicalResource.identifier", "CanonicalResource.version", "CanonicalResource.name",
"CanonicalResource.title", "CanonicalResource.status", "CanonicalResource.experimental", "CanonicalResource.date",
@ -139,7 +148,7 @@ public class LanguageUtils {
return fp;
}
}
return bp;
return path;
}
@ -163,6 +172,22 @@ public class LanguageUtils {
return r;
}
public int importFromTranslations(Resource resource, List<TranslationUnit> translations, List<ValidationMessage> messages) {
Set<TranslationUnit> usedUnits = new HashSet<>();
int r = 0;
if (resource.fhirType().equals("StructureDefinition")) {
// todo... r = importFromTranslationsForSD(null, resource, translations, usedUnits);
} else {
r = importResourceFromTranslations(null, resource, translations, usedUnits, resource.fhirType());
}
for (TranslationUnit t : translations) {
if (!usedUnits.contains(t)) {
messages.add(new ValidationMessage(Source.Publisher, IssueType.INFORMATIONAL, t.getId(), "Unused '"+t.getLanguage()+"' translation '"+t.getSrcText()+"' -> '"+t.getTgtText()+"'", IssueSeverity.INFORMATION));
}
}
return r;
}
/*
* */
@ -220,12 +245,48 @@ public class LanguageUtils {
return r;
}
private int importResourceFromTranslations(Base parent, Base element, List<TranslationUnit> translations, Set<TranslationUnit> usedUnits, String path) {
int t = 0;
if (element.isPrimitive() && isTranslatable(element, path) && element instanceof org.hl7.fhir.r5.model.Element) {
org.hl7.fhir.r5.model.Element e = (org.hl7.fhir.r5.model.Element) element;
String base = element.primitiveValue();
if (base != null) {
String epath = pathForElement(path, element.fhirType());
Set<TranslationUnit> tlist = findTranslations(epath, base, translations);
for (TranslationUnit translation : tlist) {
t++;
if (!handleAsSpecial(parent, element, translation)) {
ToolingExtensions.setLanguageTranslation(e, translation.getLanguage(), translation.getTgtText());
usedUnits.add(translation);
}
}
}
}
for (Property c : element.children()) {
for (Base v : c.getValues()) {
if (!c.getName().equals("designation")) {
t = t + importResourceFromTranslations(element, v, translations, usedUnits, path+"."+c.getName());
}
}
}
return t;
}
private boolean handleAsSpecial(Base parent, Base element, TranslationUnit translation) {
return false;
}
private boolean isTranslatable(Base element, String path) {
return Utilities.existsInList(element.fhirType(), "string", "markdown");
}
private int importFromTranslations(Element parent, Element element, List<TranslationUnit> translations, Set<TranslationUnit> usedUnits) {
int t = 0;
if (element.isPrimitive() && isTranslatable(element)) {
String base = element.primitiveValue();
if (base != null) {
Set<TranslationUnit> tlist = findTranslations(pathForElement(element), base, translations);
String path = pathForElement(element);
Set<TranslationUnit> tlist = findTranslations(path, base, translations);
for (TranslationUnit translation : tlist) {
t++;
if (!handleAsSpecial(parent, element, translation)) {
@ -235,7 +296,7 @@ public class LanguageUtils {
}
}
}
for (Element c: element.getChildren()) {
for (Element c : element.getChildren()) {
if (!c.getName().equals("designation")) {
t = t + importFromTranslations(element, c, translations, usedUnits);
}
@ -331,19 +392,64 @@ public class LanguageUtils {
return dstLang == null || srcLang == null ? false : dstLang.startsWith(srcLang) || "*".equals(srcLang);
}
public static void fillSupplement(CodeSystem cs, List<TranslationUnit> list) {
cs.setUserData(SUPPLEMENT_NAME, "true");
public void fillSupplement(CodeSystem csSrc, CodeSystem csDst, List<TranslationUnit> list) {
csDst.setUserData(SUPPLEMENT_SOURCE_RESOURCE, csSrc);
csDst.setUserData(SUPPLEMENT_SOURCE_TRANSLATIONS, list);
for (TranslationUnit tu : list) {
ConceptDefinitionComponent cd = CodeSystemUtilities.getCode(cs, tu.getId());
if (cd != null && cd.hasDisplay() && cd.getDisplay().equals(tu.getSrcText())) {
cd.addDesignation().setLanguage(tu.getLanguage()).setValue(tu.getTgtText());
} else {
addOrphanTranslation(cs, tu);
String code = tu.getId();
String subCode = null;
if (code.contains("@")) {
subCode = code.substring(code.indexOf("@")+1);
code = code.substring(0, code.indexOf("@"));
}
ConceptDefinitionComponent cdSrc = CodeSystemUtilities.getCode(csSrc, tu.getId());
if (cdSrc == null) {
addOrphanTranslation(csSrc, tu);
} else {
ConceptDefinitionComponent cdDst = CodeSystemUtilities.getCode(csDst, cdSrc.getCode());
if (cdDst == null) {
cdDst = csDst.addConcept().setCode(cdSrc.getCode());
}
String tt = tu.getTgtText();
if (tt.startsWith("!!")) {
tt = tt.substring(3);
}
if (subCode == null) {
cdDst.setDisplay(tt);
} else if ("definition".equals(subCode)) {
cdDst.setDefinition(tt);
} else {
boolean found = false;
for (ConceptDefinitionDesignationComponent d : cdSrc.getDesignation()) {
if (d.hasUse() && subCode.equals(d.getUse().getCode())) {
found = true;
cdDst.addDesignation().setUse(d.getUse()).setLanguage(tu.getLanguage()).setValue(tt); //.setUserData(SUPPLEMENT_SOURCE, tu);
break;
}
}
if (!found) {
for (Extension e : cdSrc.getExtension()) {
if (subCode.equals(tail(e.getUrl()))) {
found = true;
cdDst.addExtension().setUrl(e.getUrl()).setValue(
e.getValue().fhirType().equals("markdown") ? new MarkdownType(tt) : new StringType(tt)); //.setUserData(SUPPLEMENT_SOURCE, tu);
break;
}
}
}
if (!found) {
addOrphanTranslation(csSrc, tu);
}
}
}
}
}
private static void addOrphanTranslation(CodeSystem cs, TranslationUnit tu) {
private String tail(String url) {
return url.contains("/") ? url.substring(url.lastIndexOf("/")+1) : url;
}
private void addOrphanTranslation(CodeSystem cs, TranslationUnit tu) {
List<TranslationUnit> list = (List<TranslationUnit>) cs.getUserData(ORPHAN_TRANSLATIONS_NAME);
if (list == null) {
list = new ArrayList<>();
@ -352,7 +458,7 @@ public class LanguageUtils {
list.add(tu);
}
public static String nameForLang(String lang) {
public String nameForLang(String lang) {
// todo: replace with structures from loading languages properly
switch (lang) {
case "en" : return "English";
@ -363,7 +469,7 @@ public class LanguageUtils {
return Utilities.capitalize(lang);
}
public static String titleForLang(String lang) {
public String titleForLang(String lang) {
// todo: replace with structures from loading languages properly
switch (lang) {
case "en" : return "English";
@ -374,29 +480,42 @@ public class LanguageUtils {
return Utilities.capitalize(lang);
}
public static boolean handlesAsResource(Resource resource) {
return (resource instanceof CodeSystem && resource.hasUserData(SUPPLEMENT_NAME)) || (resource instanceof StructureDefinition);
public boolean handlesAsResource(Resource resource) {
return (resource instanceof CodeSystem && resource.hasUserData(SUPPLEMENT_SOURCE_RESOURCE)) || (resource instanceof StructureDefinition);
}
public static boolean handlesAsElement(Element element) {
public boolean handlesAsElement(Element element) {
return true; // for now...
}
public static List<TranslationUnit> generateTranslations(Resource res, String lang) {
public List<TranslationUnit> generateTranslations(Resource res, String lang) {
List<TranslationUnit> list = new ArrayList<>();
if (res instanceof StructureDefinition) {
StructureDefinition sd = (StructureDefinition) res;
generateTranslations(list, sd, lang);
if (res.hasUserData(ORPHAN_TRANSLATIONS_NAME)) {
List<TranslationUnit> orphans = (List<TranslationUnit>) res.getUserData(ORPHAN_TRANSLATIONS_NAME);
for (TranslationUnit t : orphans) {
list.add(new TranslationUnit(lang, "!!"+t.getId(), t.getContext1(), t.getSrcText(), t.getTgtText()));
}
}
} else {
CodeSystem cs = (CodeSystem) res;
CodeSystem cs = (CodeSystem) res.getUserData(SUPPLEMENT_SOURCE_RESOURCE);
List<TranslationUnit> inputs = res.hasUserData(SUPPLEMENT_SOURCE_TRANSLATIONS) ? (List<TranslationUnit>) res.getUserData(SUPPLEMENT_SOURCE_TRANSLATIONS) : new ArrayList<>();
for (ConceptDefinitionComponent cd : cs.getConcept()) {
generateTranslations(list, cd, lang);
generateTranslations(list, cd, lang, inputs);
}
if (cs.hasUserData(ORPHAN_TRANSLATIONS_NAME)) {
List<TranslationUnit> orphans = (List<TranslationUnit>) cs.getUserData(ORPHAN_TRANSLATIONS_NAME);
for (TranslationUnit t : orphans) {
list.add(new TranslationUnit(lang, "!!"+t.getId(), t.getContext1(), t.getSrcText(), t.getTgtText()));
}
}
}
return list;
}
private static void generateTranslations(List<TranslationUnit> list, StructureDefinition sd, String lang) {
private void generateTranslations(List<TranslationUnit> list, StructureDefinition sd, String lang) {
addToList(list, lang, sd, "name", "name", sd.getNameElement());
addToList(list, lang, sd, "title", "title", sd.getTitleElement());
addToList(list, lang, sd, "publisher", "publisher", sd.getPublisherElement());
@ -426,34 +545,49 @@ public class LanguageUtils {
}
}
private static void addToList(List<TranslationUnit> list, String lang, Base ctxt, String name, String propName, DataType value) {
private void addToList(List<TranslationUnit> list, String lang, Base ctxt, String name, String propName, DataType value) {
if (value != null && value.hasPrimitiveValue()) {
list.add(new TranslationUnit(lang, name, ctxt.getNamedProperty(propName).getDefinition(), value.primitiveValue(), value.getTranslation(lang)));
}
}
private static void generateTranslations(List<TranslationUnit> list, ConceptDefinitionComponent cd, String lang) {
String code = cd.getCode();
String display = cd.getDisplay();
String target = null;
for (ConceptDefinitionDesignationComponent d : cd.getDesignation()) {
if (target == null && !d.hasUse() && d.hasLanguage() && lang.equals(d.getLanguage())) {
target = d.getValue();
}
private void generateTranslations(List<TranslationUnit> list, ConceptDefinitionComponent cd, String lang, List<TranslationUnit> inputs) {
// we generate translation units for the display, the definition, and any designations and extensions that we find
// the id of the designation is the use.code (there will be a use) and for the extension, the tail of the extension URL
// todo: do we need to worry about name clashes? why would we, and more importantly, how would we solve that?
addTranslationUnit(list, cd.getCode(), cd.getDisplay(), lang, inputs);
if (cd.hasDefinition()) {
addTranslationUnit(list, cd.getCode()+"@definition", cd.getDefinition(), lang, inputs);
}
for (ConceptDefinitionDesignationComponent d : cd.getDesignation()) {
if (target == null && d.hasLanguage() && lang.equals(d.getLanguage())) {
target = d.getValue();
}
addTranslationUnit(list, cd.getCode()+"@"+d.getUse().getCode(), d.getValue(), lang, inputs);
}
list.add(new TranslationUnit(lang, code, getDefinition(cd), display, target));
for (ConceptDefinitionComponent cd1 : cd.getConcept()) {
generateTranslations(list, cd1, lang);
for (Extension e : cd.getExtension()) {
addTranslationUnit(list, cd.getCode()+"@"+tail(e.getUrl()), e.getValue().primitiveValue(), lang, inputs);
}
}
private static String getDefinition(ConceptDefinitionComponent cd) {
private void addTranslationUnit(List<TranslationUnit> list, String id, String srcText, String lang, List<TranslationUnit> inputs) {
TranslationUnit existing = null;
for (TranslationUnit t : inputs) {
if (id.equals(t.getId())) {
existing = t;
break;
}
}
// not sure what to do with context?
if (existing == null) {
list.add(new TranslationUnit(lang, id, null, srcText, null));
} else if (srcText.equals(existing.getSrcText())) {
list.add(new TranslationUnit(lang, id, null, srcText, existing.getTgtText()));
} else {
list.add(new TranslationUnit(lang, id, null, srcText, "!!"+existing.getTgtText()).setOriginal(existing.getSrcText()));
}
}
private String getDefinition(ConceptDefinitionComponent cd) {
ConceptPropertyComponent v = CodeSystemUtilities.getProperty(cd, "translation-context");
if (v != null && v.hasValue()) {
return v.getValue().primitiveValue();
@ -462,15 +596,15 @@ public class LanguageUtils {
}
}
public static List<TranslationUnit> generateTranslations(Element e, String lang) {
public List<TranslationUnit> generateTranslations(Element e, String lang) {
List<TranslationUnit> list = new ArrayList<>();
generateTranslations(e, lang, list);
return list;
}
private static void generateTranslations(Element e, String lang, List<TranslationUnit> list) {
private void generateTranslations(Element e, String lang, List<TranslationUnit> list) {
if (e.getProperty().isTranslatable()) {
String id = e.getProperty().getDefinition().getPath();
String id = pathForElement(e); // .getProperty().getDefinition().getPath();
String context = e.getProperty().getDefinition().getDefinition();
String src = e.primitiveValue();
String tgt = getTranslation(e, lang);
@ -484,7 +618,7 @@ public class LanguageUtils {
}
private static String getTranslation(Element e, String lang) {
private String getTranslation(Element e, String lang) {
if (!e.hasChildren()) {
return null;
}
@ -507,5 +641,22 @@ public class LanguageUtils {
}
return null;
}
public boolean switchLanguage(Element e, String lang) {
if (e.getProperty().isTranslatable()) {
String cnt = getTranslation(e, lang);
e.removeExtension(ToolingExtensions.EXT_TRANSLATION);
if (cnt != null) {
e.setValue(cnt);
}
}
if (e.hasChildren()) {
for (Element c : e.getChildren()) {
if (!switchLanguage(c, lang)) {
return false;
}
}
}
return true;
}
}

View File

@ -167,7 +167,7 @@ public class SHCParser extends ParserBase {
return res;
}
// ok. all checks passed, we can now validate the bundle
bnd.setElement(jsonParser.parse(bnd.getErrors(), cs.getJsonObject("fhirBundle")));
bnd.setElement(jsonParser.parse(bnd.getErrors(), cs.getJsonObject("fhirBundle"), path));
bnd.setElementPath(path);
}
return res;

View File

@ -29,11 +29,11 @@ import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.test.utils.TestingUtilities;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.SimpleHTTPClient;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.SimpleHTTPClient.HTTPResult;
import org.hl7.fhir.utilities.http.HTTPResult;
import org.hl7.fhir.utilities.http.ManagedWebAccess;
import org.hl7.fhir.utilities.json.model.JsonArray;
import org.hl7.fhir.utilities.json.model.JsonElement;
import org.hl7.fhir.utilities.json.model.JsonElementType;
@ -287,9 +287,7 @@ public class SHLParser extends ParserBase {
private HTTPResult fetchFile(String url, String ct) throws IOException {
SimpleHTTPClient fetcher = new SimpleHTTPClient();
fetcher.addHeader("Accept", ct);
HTTPResult res = fetcher.get(url);
HTTPResult res = ManagedWebAccess.get(url, ct);
res.checkThrowException();
return res;
}
@ -298,10 +296,10 @@ public class SHLParser extends ParserBase {
if (testMode) {
return new HTTPResult(url, 200, "OK", "application/json", TextFile.streamToBytes(TestingUtilities.loadTestResourceStream("validator", "shlink.manifest.json")));
}
SimpleHTTPClient fetcher = new SimpleHTTPClient();
JsonObject j = new JsonObject();
j.add("recipient", "FHIR Validator");
HTTPResult res = fetcher.post(url, "application/json", org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j), "application/json");
HTTPResult res = ManagedWebAccess.post(url, org.hl7.fhir.utilities.json.parser.JsonParser.composeBytes(j), "application/json", "application/json");
res.checkThrowException();
return res;
}

View File

@ -51,7 +51,7 @@ public class ExpressionNode {
Empty, Not, Exists, SubsetOf, SupersetOf, IsDistinct, Distinct, Count, Where, Select, All, Repeat, Aggregate, Item /*implicit from name[]*/, As, Is, Single,
First, Last, Tail, Skip, Take, Union, Combine, Intersect, Exclude, Iif, Upper, Lower, ToChars, IndexOf, Substring, StartsWith, EndsWith, Matches, MatchesFull, ReplaceMatches, Contains, Replace, Length,
Children, Descendants, MemberOf, Trace, Check, Today, Now, Resolve, Extension, AllFalse, AnyFalse, AllTrue, AnyTrue,
Children, Descendants, MemberOf, Trace, DefineVariable, Check, Today, Now, Resolve, Extension, AllFalse, AnyFalse, AllTrue, AnyTrue,
HasValue, OfType, Type, ConvertsToBoolean, ConvertsToInteger, ConvertsToString, ConvertsToDecimal, ConvertsToQuantity, ConvertsToDateTime, ConvertsToDate, ConvertsToTime, ToBoolean, ToInteger, ToString, ToDecimal, ToQuantity, ToDateTime, ToTime, ConformsTo,
Round, Sqrt, Abs, Ceiling, Exp, Floor, Ln, Log, Power, Truncate,
@ -59,7 +59,7 @@ public class ExpressionNode {
Encode, Decode, Escape, Unescape, Trim, Split, Join, LowBoundary, HighBoundary, Precision,
// Local extensions to FHIRPath
HtmlChecks1, HtmlChecks2, AliasAs, Alias, Comparable, hasTemplateIdOf;
HtmlChecks1, HtmlChecks2, Comparable, hasTemplateIdOf;
public static Function fromCode(String name) {
if (name.equals("empty")) return Function.Empty;
@ -106,6 +106,7 @@ public class ExpressionNode {
if (name.equals("descendants")) return Function.Descendants;
if (name.equals("memberOf")) return Function.MemberOf;
if (name.equals("trace")) return Function.Trace;
if (name.equals("defineVariable")) return Function.DefineVariable;
if (name.equals("check")) return Function.Check;
if (name.equals("today")) return Function.Today;
if (name.equals("now")) return Function.Now;
@ -116,8 +117,6 @@ public class ExpressionNode {
if (name.equals("allTrue")) return Function.AllTrue;
if (name.equals("anyTrue")) return Function.AnyTrue;
if (name.equals("hasValue")) return Function.HasValue;
if (name.equals("alias")) return Function.Alias;
if (name.equals("aliasAs")) return Function.AliasAs;
if (name.equals("htmlChecks")) return Function.HtmlChecks1;
if (name.equals("htmlchecks")) return Function.HtmlChecks1; // support change of care from R3
if (name.equals("htmlChecks2")) return Function.HtmlChecks2;
@ -211,6 +210,7 @@ public class ExpressionNode {
case Descendants : return "descendants";
case MemberOf : return "memberOf";
case Trace : return "trace";
case DefineVariable : return "defineVariable";
case Check : return "check";
case Today : return "today";
case Now : return "now";
@ -221,8 +221,6 @@ public class ExpressionNode {
case AllTrue : return "allTrue";
case AnyTrue : return "anyTrue";
case HasValue : return "hasValue";
case Alias : return "alias";
case AliasAs : return "aliasAs";
case Encode : return "encode";
case Decode : return "decode";
case Escape : return "escape";

View File

@ -193,6 +193,7 @@ public class FHIRPathEngine {
/**
* A constant reference - e.g. a reference to a name that must be resolved in context.
* The % will be removed from the constant name before this is invoked.
* Variables created with defineVariable will not be processed by resolveConstant (or resolveConstantType)
*
* This will also be called if the host invokes the FluentPath engine with a context of null
*
@ -515,10 +516,14 @@ public class FHIRPathEngine {
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT, context);
}
ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null) {
List<ElementDefinitionMatch> edl = getElementDefinition(sd, context, true, expr);
if (edl.size() == 0) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
}
if (edl.size() > 1) {
throw new Error("Not handled here yet");
}
ElementDefinitionMatch ed = edl.get(0);
if (ed.fixedType != null) {
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
} else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType())) {
@ -577,10 +582,14 @@ public class FHIRPathEngine {
}
String tn = checkTypeName ? sd.getSnapshot().getElementFirstRep().getPath() : t;
ElementDefinitionMatch ed = getElementDefinition(sd, tn, true, expr);
if (ed == null) {
List<ElementDefinitionMatch> edl = getElementDefinition(sd, tn, true, expr);
if (edl.size() == 0) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, t);
}
if (edl.size() > 1) {
throw new Error("not handled here either");
}
ElementDefinitionMatch ed = edl.get(0);
if (ed.fixedType != null) {
types.addType(ed.fixedType);
} else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType())) {
@ -660,10 +669,14 @@ public class FHIRPathEngine {
if (!context.contains(".")) {
types = new TypeDetails(CollectionStatus.SINGLETON, sd.getUrl());
} else {
ElementDefinitionMatch ed = getElementDefinition(sd, context, true, expr);
if (ed == null) {
List<ElementDefinitionMatch> edl = getElementDefinition(sd, context, true, expr);
if (edl.size() == 0) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONTEXT_ELEMENT, context);
}
if (edl.size() > 1) {
throw new Error("Unhandled case?");
}
ElementDefinitionMatch ed = edl.get(0);
if (ed.fixedType != null) {
types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
} else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType())) {
@ -757,7 +770,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, null, base), list, ExpressionNode, true);
return execute(new ExecutionContext(null, base != null && base.isResource() ? base : null, base != null && base.isResource() ? base : null, base, base), list, ExpressionNode, true);
}
/**
@ -776,7 +789,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, null, base), list, exp, true);
return execute(new ExecutionContext(null, base.isResource() ? base : null, base.isResource() ? base : null, base, base), list, exp, true);
}
/**
@ -794,7 +807,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list, ExpressionNode, true);
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list, ExpressionNode, true);
}
/**
@ -812,7 +825,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list, expressionNode, true);
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list, expressionNode, true);
}
/**
@ -831,7 +844,7 @@ public class FHIRPathEngine {
list.add(base);
}
log = new StringBuilder();
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, null, base), list, exp, true);
return execute(new ExecutionContext(appContext, focusResource, rootResource, base, base), list, exp, true);
}
/**
@ -996,15 +1009,14 @@ public class FHIRPathEngine {
private Base context;
private Base thisItem;
private List<Base> total;
private Map<String, Base> aliases;
private int index;
private Map<String, List<Base>> definedVariables;
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Map<String, Base> aliases, Base thisItem) {
public ExecutionContext(Object appInfo, Base resource, Base rootResource, Base context, Base thisItem) {
this.appInfo = appInfo;
this.context = context;
this.focusResource = resource;
this.rootResource = rootResource;
this.aliases = aliases;
this.thisItem = thisItem;
this.index = 0;
}
@ -1028,24 +1040,34 @@ public class FHIRPathEngine {
return new IntegerType(index);
}
public void addAlias(String name, List<Base> focus) throws FHIRException {
if (aliases == null) {
aliases = new HashMap<String, Base>();
} else {
aliases = new HashMap<String, Base>(aliases); // clone it, since it's going to change
}
if (focus.size() > 1) {
throw makeException(null, I18nConstants.FHIRPATH_ALIAS_COLLECTION);
}
aliases.put(name, focus.size() == 0 ? null : focus.get(0));
}
public Base getAlias(String name) {
return aliases == null ? null : aliases.get(name);
}
public ExecutionContext setIndex(int i) {
index = i;
return this;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public List<Base> getDefinedVariable(String name) {
return definedVariables == null ? makeNull() : definedVariables.get(name);
}
public void setDefinedVariable(String name, List<Base> value) {
if (isSystemVariable(name))
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, List<Base>>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException(worker.formatMessage(I18nConstants.FHIRPATH_REDEFINE_VARIABLE, name), I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private static class ExecutionTypeContext {
@ -1054,7 +1076,7 @@ public class FHIRPathEngine {
private TypeDetails context;
private TypeDetails thisItem;
private TypeDetails total;
private Map<String, TypeDetails> definedVariables;
public ExecutionTypeContext(Object appInfo, String resource, TypeDetails context, TypeDetails thisItem) {
super();
@ -1071,7 +1093,29 @@ public class FHIRPathEngine {
return thisItem;
}
public boolean hasDefinedVariable(String name) {
return definedVariables != null && definedVariables.containsKey(name);
}
public TypeDetails getDefinedVariable(String name) {
return definedVariables == null ? null : definedVariables.get(name);
}
public void setDefinedVariable(String name, TypeDetails value) {
if (isSystemVariable(name))
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
if (definedVariables == null) {
definedVariables = new HashMap<String, TypeDetails>();
} else {
if (definedVariables.containsKey(name)) {
// Can't do this, so throw an error
throw new PathEngineException("Redefine of variable "+name, I18nConstants.FHIRPATH_REDEFINE_VARIABLE);
}
}
definedVariables.put(name, value);
}
}
private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
@ -1411,6 +1455,7 @@ public class FHIRPathEngine {
case Descendants: return checkParamCount(lexer, location, exp, 0);
case MemberOf: return checkParamCount(lexer, location, exp, 1);
case Trace: return checkParamCount(lexer, location, exp, 1, 2);
case DefineVariable: return checkParamCount(lexer, location, exp, 1, 2);
case Check: return checkParamCount(lexer, location, exp, 2);
case Today: return checkParamCount(lexer, location, exp, 0);
case Now: return checkParamCount(lexer, location, exp, 0);
@ -1421,8 +1466,6 @@ public class FHIRPathEngine {
case AllTrue: return checkParamCount(lexer, location, exp, 0);
case AnyTrue: return checkParamCount(lexer, location, exp, 0);
case HasValue: return checkParamCount(lexer, location, exp, 0);
case Alias: return checkParamCount(lexer, location, exp, 1);
case AliasAs: return checkParamCount(lexer, location, exp, 1);
case Encode: return checkParamCount(lexer, location, exp, 1);
case Decode: return checkParamCount(lexer, location, exp, 1);
case Escape: return checkParamCount(lexer, location, exp, 1);
@ -1468,8 +1511,9 @@ public class FHIRPathEngine {
return false;
}
private List<Base> execute(ExecutionContext context, List<Base> focus, ExpressionNode exp, boolean atEntry) throws FHIRException {
private List<Base> execute(ExecutionContext inContext, List<Base> focus, ExpressionNode exp, boolean atEntry) throws FHIRException {
// System.out.println("Evaluate {'"+exp.toString()+"'} on "+focus.toString());
ExecutionContext context = contextForParameter(inContext);
List<Base> work = new ArrayList<Base>();
switch (exp.getKind()) {
case Unary:
@ -1513,6 +1557,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
List<Base> work2 = preOperate(work, last.getOperation(), exp);
if (work2 != null) {
work = work2;
@ -1576,8 +1621,8 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, exp.getName());
}
private TypeDetails executeType(ExecutionTypeContext context, TypeDetails focus, ExpressionNode exp, Set<ElementDefinition> elementDependencies, boolean atEntry, boolean canBeNone, ExpressionNode container) throws PathEngineException, DefinitionException {
private TypeDetails executeType(ExecutionTypeContext inContext, TypeDetails focus, ExpressionNode exp, Set<ElementDefinition> elementDependencies, boolean atEntry, boolean canBeNone, ExpressionNode container) throws PathEngineException, DefinitionException {
ExecutionTypeContext context = contextForParameter(inContext);
TypeDetails result = new TypeDetails(null);
switch (exp.getKind()) {
case Name:
@ -1627,6 +1672,7 @@ public class FHIRPathEngine {
ExpressionNode next = exp.getOpNext();
ExpressionNode last = exp;
while (next != null) {
context = contextForParameter(inContext);
TypeDetails work;
if (last.getOperation() == Operation.Is || last.getOperation() == Operation.As) {
work = executeTypeName(context, focus, next, atEntry);
@ -1664,6 +1710,10 @@ public class FHIRPathEngine {
}
FHIRConstant c = (FHIRConstant) constant;
if (c.getValue().startsWith("%")) {
String varName = c.getValue().substring(1);
if (context.hasDefinedVariable(varName)) {
return context.getDefinedVariable(varName);
}
return resolveConstant(context, c.getValue(), beforeContext, expr, true);
} else if (c.getValue().startsWith("@")) {
return new ArrayList<Base>(Arrays.asList(processDateConstant(context.appInfo, c.getValue().substring(1), expr)));
@ -1734,6 +1784,21 @@ public class FHIRPathEngine {
}
}
static boolean isSystemVariable(String name){
if (name.equals("sct"))
return true;
if (name.equals("loinc"))
return true;
if (name.equals("ucum"))
return true;
if (name.equals("resource"))
return true;
if (name.equals("rootResource"))
return true;
if (name.equals("context"))
return true;
return false;
}
private List<Base> resolveConstant(ExecutionContext context, String s, boolean beforeContext, ExpressionNode expr, boolean explicitConstant) throws PathEngineException {
if (s.equals("%sct")) {
@ -3137,8 +3202,14 @@ public class FHIRPathEngine {
} else if (s.startsWith("%`ext-")) {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
} else if (hostServices == null) {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
} else {
String varName = s.substring(1);
if (context.hasDefinedVariable(varName))
return context.getDefinedVariable(varName);
TypeDetails v = hostServices.resolveConstantType(this, context.appInfo, s, explicitConstant);
if (v == null) {
throw makeException(expr, I18nConstants.FHIRPATH_UNKNOWN_CONSTANT, s);
@ -3491,6 +3562,25 @@ public class FHIRPathEngine {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
}
case DefineVariable : {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.UNORDERED, TypeDetails.FP_String));
// set the type of the variable
// Actually evaluate the value of the first parameter (to get the name of the variable if possible)
// and if have that, set it into the context
ExpressionNode p = exp.getParameters().get(0);
if (p.getKind() == Kind.Constant && p.getConstant() != null) {
String varName = exp.getParameters().get(0).getConstant().primitiveValue();
if (varName != null) {
if (paramTypes.size() > 1)
context.setDefinedVariable(varName, paramTypes.get(1));
else
context.setDefinedVariable(varName, focus);
}
} else {
// this variable is not a constant, so we can't analyze what name it could have
}
return focus;
}
case Check : {
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
@ -3533,12 +3623,6 @@ public class FHIRPathEngine {
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Comparable :
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_Boolean);
case Alias :
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return anything(CollectionStatus.SINGLETON);
case AliasAs :
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return focus;
case Encode:
checkParamTypes(exp, exp.getFunction().toCode(), paramTypes, new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String));
return new TypeDetails(CollectionStatus.SINGLETON, TypeDetails.FP_String);
@ -3722,7 +3806,7 @@ public class FHIRPathEngine {
case 0:
return exp.getFunction() == Function.Where || exp.getFunction() == Function.Exists || exp.getFunction() == Function.All || exp.getFunction() == Function.Select || exp.getFunction() == Function.Repeat || exp.getFunction() == Function.Aggregate;
case 1:
return exp.getFunction() == Function.Trace;
return exp.getFunction() == Function.Trace || exp.getFunction() == Function.DefineVariable;
default:
return false;
}
@ -3875,6 +3959,7 @@ public class FHIRPathEngine {
case Descendants : return funcDescendants(context, focus, exp);
case MemberOf : return funcMemberOf(context, focus, exp);
case Trace : return funcTrace(context, focus, exp);
case DefineVariable : return funcDefineVariable(context, focus, exp);
case Check : return funcCheck(context, focus, exp);
case Today : return funcToday(context, focus, exp);
case Now : return funcNow(context, focus, exp);
@ -3885,7 +3970,6 @@ public class FHIRPathEngine {
case AnyTrue: return funcAnyTrue(context, focus, exp);
case AllTrue: return funcAllTrue(context, focus, exp);
case HasValue : return funcHasValue(context, focus, exp);
case AliasAs : return funcAliasAs(context, focus, exp);
case Encode : return funcEncode(context, focus, exp);
case Decode : return funcDecode(context, focus, exp);
case Escape : return funcEscape(context, focus, exp);
@ -3893,7 +3977,6 @@ public class FHIRPathEngine {
case Trim : return funcTrim(context, focus, exp);
case Split : return funcSplit(context, focus, exp);
case Join : return funcJoin(context, focus, exp);
case Alias : return funcAlias(context, focus, exp);
case HtmlChecks1 : return funcHtmlChecks1(context, focus, exp);
case HtmlChecks2 : return funcHtmlChecks2(context, focus, exp);
case Comparable : return funcComparable(context, focus, exp);
@ -4464,24 +4547,6 @@ public class FHIRPathEngine {
return result;
}
private List<Base> funcAliasAs(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
context.addAlias(name, focus);
return focus;
}
private List<Base> funcAlias(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> res = new ArrayList<Base>();
Base b = context.getAlias(name);
if (b != null) {
res.add(b);
}
return res;
}
private List<Base> funcHtmlChecks1(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
// todo: actually check the HTML
if (focus.size() != 1) {
@ -4640,13 +4705,50 @@ public class FHIRPathEngine {
private ExecutionContext changeThis(ExecutionContext context, Base newThis) {
return new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.aliases, newThis);
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionContext contextForParameter(ExecutionContext context) {
ExecutionContext newContext = new ExecutionContext(context.appInfo, context.focusResource, context.rootResource, context.context, context.thisItem);
newContext.total = context.total;
newContext.index = context.index;
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext changeThis(ExecutionTypeContext context, TypeDetails newThis) {
return new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, newThis);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private ExecutionTypeContext contextForParameter(ExecutionTypeContext context) {
ExecutionTypeContext newContext = new ExecutionTypeContext(context.appInfo, context.resource, context.context, context.thisItem);
// append all of the defined variables from the context into the new context
if (context.definedVariables != null) {
for (String s : context.definedVariables.keySet()) {
newContext.setDefinedVariable(s, context.definedVariables.get(s));
}
}
return newContext;
}
private List<Base> funcNow(ExecutionContext context, List<Base> focus, ExpressionNode exp) {
List<Base> result = new ArrayList<Base>();
@ -5484,6 +5586,20 @@ public class FHIRPathEngine {
return focus;
}
private List<Base> funcDefineVariable(ExecutionContext context, List<Base> focus, ExpressionNode exp) throws FHIRException {
List<Base> nl = execute(context, focus, exp.getParameters().get(0), true);
String name = nl.get(0).primitiveValue();
List<Base> value;
if (exp.getParameters().size() == 2) {
value = execute(context, focus, exp.getParameters().get(1), true);
} else {
value = focus;
}
// stash the variable into the context
context.setDefinedVariable(name, value);
return focus;
}
private List<Base> funcCheck(ExecutionContext context, List<Base> focus, ExpressionNode expr) throws FHIRException {
List<Base> n1 = execute(context, focus, expr.getParameters().get(0), true);
if (!convertToBoolean(n1)) {
@ -6073,8 +6189,10 @@ public class FHIRPathEngine {
}
List<StructureDefinition> sdl = new ArrayList<StructureDefinition>();
ElementDefinitionMatch m = null;
if (type.contains("#"))
m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr);
if (type.contains("#")) {
List<ElementDefinitionMatch> list = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr);
m = list.size() == 1 ? list.get(0) : null;
}
if (m != null && hasDataType(m.definition)) {
if (m.fixedType != null) {
StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, null), sd);
@ -6179,8 +6297,8 @@ public class FHIRPathEngine {
} else {
path = sdi.getSnapshot().getElement().get(0).getPath()+tail+"."+name;
ElementDefinitionMatch ed = getElementDefinition(sdi, path, isAllowPolymorphicNames(), expr);
if (ed != null) {
List<ElementDefinitionMatch> edl = getElementDefinition(sdi, path, isAllowPolymorphicNames(), expr);
for (ElementDefinitionMatch ed : edl) {
if (ed.getDefinition().isChoice()) {
result.setChoice(true);
}
@ -6277,8 +6395,7 @@ public class FHIRPathEngine {
}
public ElementDefinitionMatch getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName, ExpressionNode expr) throws PathEngineException {
public List<ElementDefinitionMatch> getElementDefinition(StructureDefinition sd, String path, boolean allowTypedName, ExpressionNode expr) throws PathEngineException {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.getPath().equals(path)) {
if (ed.hasContentReference()) {
@ -6288,26 +6405,36 @@ public class FHIRPathEngine {
} else {
res.sourceDefinition = ed;
}
return res;
return ml(res);
} else {
return new ElementDefinitionMatch(ed, null);
return ml(new ElementDefinitionMatch(ed, null));
}
}
if (ed.getPath().endsWith("[x]") && path.startsWith(ed.getPath().substring(0, ed.getPath().length()-3)) && path.length() == ed.getPath().length()-3) {
return new ElementDefinitionMatch(ed, null);
return ml(new ElementDefinitionMatch(ed, null));
}
if (allowTypedName && ed.getPath().endsWith("[x]") && path.startsWith(ed.getPath().substring(0, ed.getPath().length()-3)) && path.length() > ed.getPath().length()-3) {
String s = Utilities.uncapitalize(path.substring(ed.getPath().length()-3));
if (primitiveTypes.contains(s)) {
return new ElementDefinitionMatch(ed, s);
return ml(new ElementDefinitionMatch(ed, s));
} else {
return new ElementDefinitionMatch(ed, path.substring(ed.getPath().length()-3));
return ml(new ElementDefinitionMatch(ed, path.substring(ed.getPath().length()-3)));
}
}
if (ed.getPath().contains(".") && path.startsWith(ed.getPath()+".") && (ed.getType().size() > 0) && !isAbstractType(ed.getType())) {
// now we walk into the type.
if (ed.getType().size() > 1) { // if there's more than one type, the test above would fail this
throw new Error("Internal typing issue....");
if (ed.getType().size() > 1) { // if there's more than one type, the test above would fail this, but we can get here with CDA
List<ElementDefinitionMatch> list = new ArrayList<>();
// for each type, does it have the next node in the path?
for (TypeRefComponent tr : ed.getType()) {
StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(tr.getCode(), null), sd);
if (nsd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition");
}
List<ElementDefinitionMatch> edl = getElementDefinition(nsd, nsd.getId()+path.substring(ed.getPath().length()), allowTypedName, expr);
list.addAll(edl);
}
return list;
}
StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), null), sd);
if (nsd == null) {
@ -6317,16 +6444,26 @@ public class FHIRPathEngine {
}
if (ed.hasContentReference() && path.startsWith(ed.getPath()+".")) {
ElementDefinitionMatch m = getElementDefinitionById(sd, ed.getContentReference());
ElementDefinitionMatch res = getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
if (res == null) {
List<ElementDefinitionMatch> res = getElementDefinition(sd, m.definition.getPath()+path.substring(ed.getPath().length()), allowTypedName, expr);
if (res.size() == 0) {
throw new Error("Unable to find "+ed.getContentReference());
} else {
res.sourceDefinition = ed;
for (ElementDefinitionMatch item : res) {
item.sourceDefinition = ed;
}
}
return res;
}
}
return null;
return ml(null);
}
private List<ElementDefinitionMatch> ml(ElementDefinitionMatch item) {
List<ElementDefinitionMatch> list = new ArrayList<>();
if (item != null) {
list.add(item);
}
return list;
}
private boolean isAbstractType(List<TypeRefComponent> list) {
@ -6418,7 +6555,7 @@ public class FHIRPathEngine {
sd = fetchStructureByType(element, expr);
if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_DISCRIMINATOR_THIS_CANNOT_FIND, element.getElement().getType().get(0).getProfile(), element.getElement().getId());
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getElement().getType().get(0).getProfile(), element.getElement().getId());
}
childDefinitions = profileUtilities.getChildMap(sd, sd.getSnapshot().getElementFirstRep());
}

View File

@ -286,9 +286,15 @@ public abstract class Base implements Serializable, IBase, IElement {
public boolean hasType(String... name) {
String t = fhirType();
for (String n : name)
for (String n : name) {
if (n.equalsIgnoreCase(t))
return true;
if (n.contains(".")) {
String[] p = n.split("\\.");
if (p.length == 2 && Utilities.existsInList(p[0], "FHIR", "CDA") && p[1].equalsIgnoreCase(t))
return true;
}
}
return false;
}

View File

@ -42,6 +42,7 @@ import javax.annotation.Nullable;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap;
@ -50,7 +51,7 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
public abstract class BaseDateTimeType extends PrimitiveType<Date> {
static final long NANOS_PER_MILLIS = 1000000L;
static final long NANOS_PER_MILLIS = 1000000L;
static final long NANOS_PER_SECOND = 1000000000L;
private static final Map<String, TimeZone> timezoneCache = new ConcurrentHashMap<>();
@ -816,9 +817,14 @@ public abstract class BaseDateTimeType extends PrimitiveType<Date> {
* {@link #toHumanDisplayLocalTimezone()} instead.
* </p>
*/
public String toHumanDisplay() {
return DateTimeUtil.toHumanDisplay(getTimeZone(), getPrecision(), getValue(), getValueAsString());
}
public String toHumanDisplay() {
return DateTimeUtil.toHumanDisplay(getTimeZone(), getPrecision(), getValue(), getValueAsString());
}
public String toHumanDisplay(Locale locale) {
return DateTimeUtil.toHumanDisplay(locale, getTimeZone(), getPrecision(), getValue());
}
/**
* Returns a human readable version of this date/time using the system local format, converted to the local timezone

View File

@ -0,0 +1,228 @@
package org.hl7.fhir.r5.model;
import org.hl7.fhir.r5.fhirpath.TypeDetails;
import org.hl7.fhir.utilities.SourceLocation;
import java.util.List;
/**
@deprecated This interface only exists to provide backward compatibility for the following two projects:
<a href="https://github.com/cqframework/clinical-reasoning">clinical-reasoning</a>
<a href="https://github.com/cqframework/clinical_quality_language/">clinical_quality-language</a>
Due to a circular dependency, they cannot be updated without a release of HAPI, which requires backwards
compatibility with core version 6.1.2.2
**/
public class ExpressionNode extends org.hl7.fhir.r5.fhirpath.ExpressionNode{
private final org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode;
public ExpressionNode(int uniqueId) {
super(0);
wrappedExpressionNode = new org.hl7.fhir.r5.fhirpath.ExpressionNode(uniqueId);
}
public ExpressionNode(org.hl7.fhir.r5.fhirpath.ExpressionNode wrappedExpressionNode) {
super(0);
this.wrappedExpressionNode = wrappedExpressionNode;
}
@Override
public String toString() {
return wrappedExpressionNode.toString();
}
@Override
public String getName() {
return wrappedExpressionNode.getName();
}
@Override
public void setName(String name) {
wrappedExpressionNode.setName(name);
}
@Override
public Base getConstant() {
return wrappedExpressionNode.getConstant();
}
@Override
public void setConstant(Base constant) {
wrappedExpressionNode.setConstant(constant);
}
@Override
public Function getFunction() {
return wrappedExpressionNode.getFunction();
}
@Override
public void setFunction(Function function) {
wrappedExpressionNode.setFunction(function);
}
@Override
public boolean isProximal() {
return wrappedExpressionNode.isProximal();
}
@Override
public void setProximal(boolean proximal) {
wrappedExpressionNode.setProximal(proximal);
}
@Override
public Operation getOperation() {
return wrappedExpressionNode.getOperation();
}
@Override
public void setOperation(Operation operation) {
wrappedExpressionNode.setOperation(operation);
}
@Override
public org.hl7.fhir.r5.fhirpath.ExpressionNode getInner() {
return wrappedExpressionNode.getInner();
}
@Override
public void setInner(org.hl7.fhir.r5.fhirpath.ExpressionNode value) {
wrappedExpressionNode.setInner(value);
}
@Override
public org.hl7.fhir.r5.fhirpath.ExpressionNode getOpNext() {
return wrappedExpressionNode.getOpNext();
}
@Override
public void setOpNext(org.hl7.fhir.r5.fhirpath.ExpressionNode value) {
wrappedExpressionNode.setOpNext(value);
}
@Override
public List<org.hl7.fhir.r5.fhirpath.ExpressionNode> getParameters() {
return wrappedExpressionNode.getParameters();
}
@Override
public boolean checkName() {
return wrappedExpressionNode.checkName();
}
@Override
public Kind getKind() {
return wrappedExpressionNode.getKind();
}
@Override
public void setKind(Kind kind) {
wrappedExpressionNode.setKind(kind);
}
@Override
public org.hl7.fhir.r5.fhirpath.ExpressionNode getGroup() {
return wrappedExpressionNode.getGroup();
}
@Override
public void setGroup(org.hl7.fhir.r5.fhirpath.ExpressionNode group) {
wrappedExpressionNode.setGroup(group);
}
@Override
public SourceLocation getStart() {
return wrappedExpressionNode.getStart();
}
@Override
public void setStart(SourceLocation start) {
wrappedExpressionNode.setStart(start);
}
@Override
public SourceLocation getEnd() {
return wrappedExpressionNode.getEnd();
}
@Override
public void setEnd(SourceLocation end) {
wrappedExpressionNode.setEnd(end);
}
@Override
public SourceLocation getOpStart() {
return wrappedExpressionNode.getOpStart();
}
@Override
public void setOpStart(SourceLocation opStart) {
wrappedExpressionNode.setOpStart(opStart);
}
@Override
public SourceLocation getOpEnd() {
return wrappedExpressionNode.getOpEnd();
}
@Override
public void setOpEnd(SourceLocation opEnd) {
wrappedExpressionNode.setOpEnd(opEnd);
}
@Override
public String getUniqueId() {
return wrappedExpressionNode.getUniqueId();
}
@Override
public int parameterCount() {
return wrappedExpressionNode.parameterCount();
}
@Override
public String Canonical() {
return wrappedExpressionNode.Canonical();
}
@Override
public String summary() {
return wrappedExpressionNode.summary();
}
@Override
public String check() {
return wrappedExpressionNode.check();
}
@Override
public TypeDetails getTypes() {
return wrappedExpressionNode.getTypes();
}
@Override
public void setTypes(TypeDetails types) {
wrappedExpressionNode.setTypes(types);
}
@Override
public TypeDetails getOpTypes() {
return wrappedExpressionNode.getOpTypes();
}
@Override
public void setOpTypes(TypeDetails opTypes) {
wrappedExpressionNode.setOpTypes(opTypes);
}
@Override
public List<String> getDistalNames() {
return wrappedExpressionNode.getDistalNames();
}
@Override
public boolean isNullSet() {
return wrappedExpressionNode.isNullSet();
}
}

View File

@ -1518,6 +1518,25 @@ public String toString() {
return hasValue() && getValue() instanceof PrimitiveType<?>;
}
public ParametersParameterComponent getPart(String name) {
for (ParametersParameterComponent t : getPart()) {
if (name.equals(t.getName())) {
return t;
}
}
return null;
}
public boolean hasPart(String name) {
for (ParametersParameterComponent t : getPart()) {
if (name.equals(t.getName())) {
return true;
}
}
return false;
}
// end addition
}

View File

@ -33,13 +33,13 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
public boolean render(XhtmlNode x, ActorDefinition acd) throws FHIRFormatError, DefinitionException, IOException {
XhtmlNode tbl = x.table("grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(/*!#*/"Actor: "+acd.getName());
tr.td().b().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_ACT, acd.getName()) + " ");
tr.td().tx(acd.getTitle());
tr.td().tx(/*!#*/"Type: " + acd.getType().toCode());
tr.td().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_TYP, acd.getType().toCode()) + " ");
XhtmlNode td = tbl.tr().td().colspan("3");
addMarkdown(td, acd.getDocumentation());
if (acd.hasReference()) {
tbl.tr().td().tx(/*!#*/"References:");
tbl.tr().td().tx(context.formatPhrase(RenderingContext.GENERAL_REFS));
td = tr.td().colspan("2");
boolean first = true;
for (UrlType t : acd.getReference()) {
@ -48,7 +48,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
}
}
if (acd.hasCapabilities()) {
tbl.tr().td().tx(/*!#*/"Capabilities:");
tbl.tr().td().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_CAP));
td = tr.td().colspan("2");
CapabilityStatement cs = context.getWorker().fetchResource(CapabilityStatement.class, acd.getCapabilities(), acd);
if (cs != null) {
@ -58,7 +58,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
}
}
if (acd.hasDerivedFrom()) {
tbl.tr().td().tx(/*!#*/"Derived from:");
tbl.tr().td().tx(context.formatPhrase(RenderingContext.ACTOR_DEF_DER));
td = tr.td().colspan("2");
boolean first = true;
for (UrlType t : acd.getReference()) {

View File

@ -231,16 +231,16 @@ public class AdditionalBindingsRenderer {
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
children.add(tr);
tr.td().style("font-size: 11px").b().tx(/*!#*/"Additional Bindings");
tr.td().style("font-size: 11px").tx(/*!#*/"Purpose");
tr.td().style("font-size: 11px").b().tx(context.formatPhrase(RenderingContext.ADD_BIND_ADD_BIND));
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_PURPOSE));
if (usage) {
tr.td().style("font-size: 11px").tx(/*!#*/"Usage");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_USAGE));
}
if (any) {
tr.td().style("font-size: 11px").tx(/*!#*/"Any");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.ADD_BIND_ANY));
}
if (doco) {
tr.td().style("font-size: 11px").tx(/*!#*/"Documentation");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
}
for (AdditionalBindingDetail binding : bindings) {
tr = new XhtmlNode(NodeType.Element, "tr");
@ -296,8 +296,8 @@ public class AdditionalBindingsRenderer {
}
}
if (any) {
String newRepeat = binding.any ? /*!#*/"Any repeats" : /*!#*/"All repeats";
String oldRepeat = binding.compare!=null && binding.compare.any ? /*!#*/"Any repeats" : /*!#*/"All repeats";
String newRepeat = binding.any ? context.formatPhrase(RenderingContext.ADD_BIND_ANY_REP) : context.formatPhrase(RenderingContext.ADD_BIND_ALL_REP);
String oldRepeat = binding.compare!=null && binding.compare.any ? context.formatPhrase(RenderingContext.ADD_BIND_ANY_REP) : context.formatPhrase(RenderingContext.ADD_BIND_ALL_REP);
compareString(tr.td().style("font-size: 11px"), newRepeat, oldRepeat);
}
if (doco) {
@ -338,54 +338,54 @@ public class AdditionalBindingsRenderer {
boolean r5 = context == null || context.getWorker() == null ? false : VersionUtilities.isR5Plus(context.getWorker().getVersion());
switch (purpose) {
case "maximum":
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-maximum" : corePath+"extension-elementdefinition-maxvalueset.html", /*!#*/"A required binding, for use when the binding strength is 'extensible' or 'preferred'").tx(/*!#*/"Max Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-maximum" : corePath+"extension-elementdefinition-maxvalueset.html", context.formatPhrase(RenderingContext.ADD_BIND_EXT_PREF)).tx(context.formatPhrase(RenderingContext.ADD_BIND_MAX));
break;
case "minimum":
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-minimum" : corePath+"extension-elementdefinition-minvalueset.html", /*!#*/"The minimum allowable value set - any conformant system SHALL support all these codes").tx(/*!#*/"Min Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-minimum" : corePath+"extension-elementdefinition-minvalueset.html", context.formatPhrase(RenderingContext.GENERAL_BIND_MIN_ALLOW)).tx(context.formatPhrase(RenderingContext.ADD_BIND_MIN));
break;
case "required" :
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-required" : corePath+"terminologies.html#strength", /*!#*/"Validators will check this binding (strength = required)").tx(/*!#*/"Required Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-required" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_VALID_REQ)).tx(context.formatPhrase(RenderingContext.ADD_BIND_REQ_BIND));
break;
case "extensible" :
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-extensible" : corePath+"terminologies.html#strength", /*!#*/"Validators will check this binding (strength = extensible)").tx(/*!#*/"Extensible Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-extensible" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_VALID_EXT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_EX_BIND));
break;
case "current" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-current" : corePath+"terminologies.html#strength", /*!#*/"New records are required to use this value set, but legacy records may use other codes").tx(/*!#*/"Current Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-current" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_NEW_REC)).tx(context.formatPhrase(RenderingContext.ADD_BIND_CURR_BIND));
} else {
td.span(null, /*!#*/"New records are required to use this value set, but legacy records may use other codes").tx(/*!#*/"Current");
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_NEW_REC)).tx(context.formatPhrase(RenderingContext.GENERAL_REQUIRED));
}
break;
case "preferred" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-preferred" : corePath+"terminologies.html#strength", /*!#*/"This is the value set that is recommended (documentation should explain why)").tx(/*!#*/"Preferred Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-preferred" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_RECOM_VALUE_SET)).tx(context.formatPhrase(RenderingContext.ADD_BIND_PREF_BIND));
} else {
td.span(null, /*!#*/"This is the value set that is recommended (documentation should explain why)").tx(/*!#*/"Recommended");
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_RECOM_VALUE_SET)).tx(context.formatPhrase(RenderingContext.GENERAL_PREFERRED));
}
break;
case "ui" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-ui" : corePath+"terminologies.html#strength", /*!#*/"This value set is provided to user look up in a given context").tx(/*!#*/"UI Binding");
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-ui" : corePath+"terminologies.html#strength", context.formatPhrase(RenderingContext.ADD_BIND_GIVEN_CONT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_UI_BIND));
} else {
td.span(null, /*!#*/"This value set is provided to user look up in a given context").tx(/*!#*/"UI");
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_GIVEN_CONT)).tx(context.formatPhrase(RenderingContext.ADD_BIND_UI));
}
break;
case "starter" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-starter" : corePath+"terminologies.html#strength", "This value set is a good set of codes to start with when designing your system").tx("Starter Set");
} else {
td.span(null, /*!#*/"This value set is a good set of codes to start with when designing your system").tx(/*!#*/"Starter");
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_DESIG_SYS)).tx(context.formatPhrase(RenderingContext.GENERAL_STARTER));
}
break;
case "component" :
if (r5) {
td.ah(r5 ? corePath+"valueset-additional-binding-purpose.html#additional-binding-purpose-component" : corePath+"terminologies.html#strength", "This value set is a component of the base value set").tx("Component");
} else {
td.span(null, /*!#*/"This value set is a component of the base value set").tx(/*!#*/"Component");
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_VALUE_COMP)).tx(context.formatPhrase(RenderingContext.GENERAL_COMPONENT));
}
break;
default:
td.span(null, /*!#*/"Unknown code for purpose").tx(purpose);
td.span(null, context.formatPhrase(RenderingContext.ADD_BIND_UNKNOWN_PUR)).tx(purpose);
}
}
@ -430,7 +430,7 @@ public class AdditionalBindingsRenderer {
children.tx(" (");
boolean ffirst = !b.getAny();
if (b.getAny()) {
children.tx(/*!#*/"any repeat");
children.tx(context.formatPhrase(RenderingContext.ADD_BIND_ANY_REP));
}
for (UsageContext uc : b.getUsage()) {
if (ffirst) ffirst = false; else children.tx(",");

View File

@ -3,8 +3,10 @@ package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.model.Binary;
import org.hl7.fhir.utilities.TextFile;
import org.hl7.fhir.utilities.Utilities;
@ -30,9 +32,9 @@ public class BinaryRenderer {
return filenames;
}
public static String getBinContentAsString(Binary bin) {
public static String getBinContentAsString(byte[] bin) {
// for now, assume UTF8. To do: extract character encoding from mime type if possible (charset)
return new String(bin.getContent(), StandardCharsets.UTF_8);
return new String(bin, StandardCharsets.UTF_8);
}
public String display(Binary bin) throws IOException {
@ -40,47 +42,71 @@ public class BinaryRenderer {
render(div, bin);
return new XhtmlComposer(false, true).compose(div);
}
public String display(Element bin) throws IOException {
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
render(div, bin);
return new XhtmlComposer(false, true).compose(div);
}
public String display(String id, String ct, byte[] cnt) throws IOException {
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
render(div, id, ct, cnt);
return new XhtmlComposer(false, true).compose(div);
}
public void render(XhtmlNode x, Binary bin) throws IOException {
String ct = bin.getContentType();
byte[] cnt = bin.getContent();
render(x, bin.getId(), ct, cnt);
}
public void render(XhtmlNode x, Element bin) throws IOException {
String ct = bin.getNamedChildValue("contentType");
String id = bin.getNamedChildValue("id");
byte[] cnt = Base64.getMimeDecoder().decode(bin.getNamedChildValue("data"));
render(x, id, ct, cnt);
}
public void render(XhtmlNode x, String id, String ct, byte[] cnt) throws IOException {
filenames.clear();
if (!bin.hasContentType()) {
error(x, /*!#*/"No Content Type");
} else if (bin.getContentType().startsWith("image/")) {
image(x, bin);
} else if (isXml(bin.getContentType())) {
xml(x, bin);
} else if (isJson(bin.getContentType())) {
json(x, bin);
} else if (isTtl(bin.getContentType())) {
ttl(x, bin);
} else if (isText(bin.getContentType())) {
text(x, bin);
if (ct == null) {
error(x,"No Content Type");
} else if (ct.startsWith("image/")) {
image(x, id, ct, cnt);
} else if (isXml(ct)) {
xml(x, cnt);
} else if (isJson(ct)) {
json(x, cnt);
} else if (isTtl(ct)) {
ttl(x, cnt);
} else if (isText(ct)) {
text(x, cnt);
} else {
error(x, "The Content Type '"+bin.getContentType()+"' is not rendered in this context");
error(x, "The Content Type '"+ct+"' is not rendered in this context");
}
}
private void image(XhtmlNode x, Binary bin) throws IOException {
private void image(XhtmlNode x, String id, String ct, byte[] cnt) throws IOException {
String ext = null;
if (bin.getContentType().startsWith("image/png")) {
if (ct.startsWith("image/png")) {
ext = ".png";
} else if (bin.getContentType().startsWith("image/jpeg")) {
} else if (ct.startsWith("image/jpeg")) {
ext = ".jpg";
} else if (bin.getContentType().startsWith("image/gif")) {
} else if (ct.startsWith("image/gif")) {
ext = ".gif";
} else if (bin.getContentType().startsWith("image/svg")) {
} else if (ct.startsWith("image/svg")) {
ext = ".svg";
}
if (ext == null) {
error(x, /*!#*/"The Image Type '"+bin.getContentType()+"' is not rendered in this context");
error(x, "The Image Type '"+ct+"' is not rendered in this context");
} else {
String fn = "Binary-Native-"+bin.getId()+ext;
TextFile.bytesToFile(bin.getContent(), Utilities.path(folder, fn));
String fn = "Binary-Native-"+id+ext;
TextFile.bytesToFile(cnt, Utilities.path(folder, fn));
filenames.add(fn);
x.img("Binary-Native-"+bin.getId()+ext, "binary");
x.img("Binary-Native-"+id+ext, "binary");
}
}
@ -92,8 +118,8 @@ public class BinaryRenderer {
return ct.startsWith("text/xml") || ct.startsWith("application/xml") || ct.contains("+xml");
}
private void xml(XhtmlNode x, Binary bin) {
String content = "\r\n"+getBinContentAsString(bin);
private void xml(XhtmlNode x, byte[] cnt) {
String content = "\r\n"+getBinContentAsString(cnt);
XhtmlNode pre = x.pre("xml");
pre.code(content);
}
@ -102,8 +128,8 @@ public class BinaryRenderer {
return ct.startsWith("text/json") || ct.startsWith("application/json") || ct.contains("+json");
}
private void json(XhtmlNode x, Binary bin) {
String content = "\r\n"+getBinContentAsString(bin);
private void json(XhtmlNode x, byte[] cnt) {
String content = "\r\n"+getBinContentAsString(cnt);
XhtmlNode pre = x.pre("json");
pre.code(content);
}
@ -112,8 +138,8 @@ public class BinaryRenderer {
return ct.startsWith("text/rdf") || ct.contains("+turtle");
}
private void ttl(XhtmlNode x, Binary bin) {
String content = "\r\n"+getBinContentAsString(bin);
private void ttl(XhtmlNode x, byte[] cnt) {
String content = "\r\n"+getBinContentAsString(cnt);
XhtmlNode pre = x.pre("rdf language-turtle");
pre.code(content);
}
@ -123,8 +149,8 @@ public class BinaryRenderer {
return ct.startsWith("text/");
}
private void text(XhtmlNode x, Binary bin) {
String content = "\r\n"+getBinContentAsString(bin);
private void text(XhtmlNode x, byte[] cnt) {
String content = "\r\n"+getBinContentAsString(cnt);
XhtmlNode pre = x.pre();
pre.code(content);
}

View File

@ -68,13 +68,13 @@ public class BundleRenderer extends ResourceRenderer {
List<BaseWrapper> entries = b.children("entry");
if ("document".equals(b.get("type").primitiveValue())) {
if (entries.isEmpty() || (entries.get(0).has("resource") && !"Composition".equals(entries.get(0).get("resource").fhirType())))
throw new FHIRException(/*!#*/"Invalid document '"+b.getId()+"' - first entry is not a Composition ('"+entries.get(0).get("resource").fhirType()+"')");
throw new FHIRException(context.formatPhrase(RenderingContext.BUND_REND_INVALID_DOC, b.getId(), entries.get(0).get("resource").fhirType()+"')"));
return renderDocument(x, b, entries);
} else if ("collection".equals(b.get("type").primitiveValue()) && allEntriesAreHistoryProvenance(entries)) {
// nothing
} else {
XhtmlNode root = new XhtmlNode(NodeType.Element, "div");
root.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.get("type").primitiveValue()));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.get("type").primitiveValue()));
int i = 0;
for (BaseWrapper be : entries) {
i++;
@ -93,9 +93,9 @@ public class BundleRenderer extends ResourceRenderer {
}
root.hr();
if (be.has("fullUrl")) {
root.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.get("fullUrl").primitiveValue()));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.get("fullUrl").primitiveValue()));
} else {
root.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i)));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i)));
}
// if (be.hasRequest())
// renderRequest(root, be.getRequest());
@ -104,7 +104,7 @@ public class BundleRenderer extends ResourceRenderer {
// if (be.hasResponse())
// renderResponse(root, be.getResponse());
if (be.has("resource")) {
root.para().addText(formatMessage(RenderingContext.BUNDLE_RESOURCE, be.get("resource").fhirType()));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_RESOURCE, be.get("resource").fhirType()));
ResourceWrapper rw = be.getChildByName("resource").getAsResource();
XhtmlNode xn = rw.getNarrative();
if (xn == null || xn.isEmpty()) {
@ -114,7 +114,7 @@ public class BundleRenderer extends ResourceRenderer {
xn = rr.render(rw);
} catch (Exception e) {
xn = new XhtmlNode();
xn.para().b().tx(/*!#*/"Exception generating narrative: "+e.getMessage());
xn.para().b().tx(context.formatPhrase(RenderingContext.BUNDLE_REV_EXCP, e.getMessage()) + " ");
}
}
root.blockquote().para().addChildren(xn);
@ -288,15 +288,15 @@ public class BundleRenderer extends ResourceRenderer {
XhtmlNode x = new XhtmlNode(NodeType.Element, "div");
if (b.getType() == BundleType.DOCUMENT) {
if (!b.hasEntry() || !(b.getEntryFirstRep().hasResource() && b.getEntryFirstRep().getResource() instanceof Composition)) {
throw new FHIRException(/*!#*/"Invalid document - first entry is not a Composition");
throw new FHIRException(context.formatPhrase(RenderingContext.BUNDLE_REV_INV_DOC));
}
renderDocument(x, b);
start = 1;
docMode = true;
x.hr();
x.h2().addText(formatMessage(RenderingContext.BUNDLE_DOCUMENT_CONTENT, b.getId(), b.getType().toCode()));
x.h2().addText(formatPhrase(RenderingContext.BUNDLE_DOCUMENT_CONTENT, b.getId(), b.getType().toCode()));
} else {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.getType().toCode()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ROOT, b.getId(), b.getType().toCode()));
}
int i = 0;
for (BundleEntryComponent be : b.getEntry()) {
@ -317,17 +317,17 @@ public class BundleRenderer extends ResourceRenderer {
x.hr();
if (docMode) {
if (be.hasFullUrl() && be.hasResource()) {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_URD, Integer.toString(i), be.getFullUrl(), be.getResource().fhirType(), be.getResource().getIdBase()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_URD, Integer.toString(i), be.getFullUrl(), be.getResource().fhirType(), be.getResource().getIdBase()));
} else if (be.hasFullUrl()) {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_U, Integer.toString(i), be.getFullUrl()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_U, Integer.toString(i), be.getFullUrl()));
} else if (be.hasResource()) {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_RD, Integer.toString(i), be.getResource().fhirType(), be.getResource().getIdBase()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_DOC_ENTRY_RD, Integer.toString(i), be.getResource().fhirType(), be.getResource().getIdBase()));
}
} else {
if (be.hasFullUrl()) {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.getFullUrl()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY_URL, Integer.toString(i), be.getFullUrl()));
} else {
x.para().addText(formatMessage(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i)));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_HEADER_ENTRY, Integer.toString(i)));
}
if (be.hasRequest())
renderRequest(x, be.getRequest());
@ -338,7 +338,7 @@ public class BundleRenderer extends ResourceRenderer {
}
if (be.hasResource()) {
if (!docMode) {
x.para().addText(formatMessage(RenderingContext.BUNDLE_RESOURCE, be.getResource().fhirType()));
x.para().addText(formatPhrase(RenderingContext.BUNDLE_RESOURCE, be.getResource().fhirType()));
}
if (be.hasResource()) {
XhtmlNode xn = null;
@ -352,7 +352,7 @@ public class BundleRenderer extends ResourceRenderer {
rr.setRcontext(new ResourceContext(rcontext, be.getResource()));
xn = rr.build(be.getResource());
} catch (Exception e) {
xn = makeExceptionXhtml(e, /*!#*/"generating narrative");
xn = makeExceptionXhtml(e, context.formatPhrase(RenderingContext.BUND_REND_GEN_NARR));
}
}
x.blockquote().para().getChildNodes().addAll(checkInternalLinks(b, xn.getChildNodes()));
@ -411,42 +411,42 @@ public class BundleRenderer extends ResourceRenderer {
private void renderSearch(XhtmlNode root, BundleEntrySearchComponent search) {
StringBuilder b = new StringBuilder();
b.append(formatMessage(RenderingContext.BUNDLE_SEARCH));
b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH));
if (search.hasMode())
b.append(formatMessage(RenderingContext.BUNDLE_SEARCH_MODE, search.getMode().toCode()));
b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_MODE, search.getMode().toCode()));
if (search.hasScore()) {
if (search.hasMode())
b.append(",");
b.append(formatMessage(RenderingContext.BUNDLE_SEARCH_SCORE, search.getScore()));
b.append(formatPhrase(RenderingContext.BUNDLE_SEARCH_SCORE, search.getScore()));
}
root.para().addText(b.toString());
}
private void renderResponse(XhtmlNode root, BundleEntryResponseComponent response) {
root.para().addText(formatMessage(RenderingContext.BUNDLE_RESPONSE));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_RESPONSE));
StringBuilder b = new StringBuilder();
b.append(response.getStatus()+"\r\n");
if (response.hasLocation())
b.append(formatMessage(RenderingContext.BUNDLE_LOCATION, response.getLocation())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_LOCATION, response.getLocation())+"\r\n");
if (response.hasEtag())
b.append(formatMessage(RenderingContext.BUNDLE_ETAG, response.getEtag())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_ETAG, response.getEtag())+"\r\n");
if (response.hasLastModified())
b.append(formatMessage(RenderingContext.BUNDLE_LAST_MOD, response.getEtag())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_LAST_MOD, response.getEtag())+"\r\n");
root.pre().addText(b.toString());
}
private void renderRequest(XhtmlNode root, BundleEntryRequestComponent request) {
root.para().addText(formatMessage(RenderingContext.BUNDLE_REQUEST));
root.para().addText(formatPhrase(RenderingContext.BUNDLE_REQUEST));
StringBuilder b = new StringBuilder();
b.append(request.getMethod()+" "+request.getUrl()+"\r\n");
if (request.hasIfNoneMatch())
b.append(formatMessage(RenderingContext.BUNDLE_IF_NON_MATCH, request.getIfNoneMatch())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_IF_NON_MATCH, request.getIfNoneMatch())+"\r\n");
if (request.hasIfModifiedSince())
b.append(formatMessage(RenderingContext.BUNDLE_IF_MOD, request.getIfModifiedSince())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_IF_MOD, request.getIfModifiedSince())+"\r\n");
if (request.hasIfMatch())
b.append(formatMessage(RenderingContext.BUNDLE_IF_MATCH, request.getIfMatch())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_IF_MATCH, request.getIfMatch())+"\r\n");
if (request.hasIfNoneExist())
b.append(formatMessage(RenderingContext.BUNDLE_IF_NONE, request.getIfNoneExist())+"\r\n");
b.append(formatPhrase(RenderingContext.BUNDLE_IF_NONE, request.getIfNoneExist())+"\r\n");
root.pre().addText(b.toString());
}

View File

@ -12,6 +12,7 @@ import javax.annotation.Nullable;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CapabilityStatement;
@ -26,6 +27,7 @@ import org.hl7.fhir.r5.model.CapabilityStatement.SystemRestfulInteraction;
import org.hl7.fhir.r5.model.CapabilityStatement.TypeRestfulInteraction;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Element;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
import org.hl7.fhir.r5.model.Extension;
@ -43,6 +45,7 @@ import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.NodeType;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class CapabilityStatementRenderer extends ResourceRenderer {
private static final String EXPECTATION = "http://hl7.org/fhir/StructureDefinition/capabilitystatement-expectation";
@ -53,6 +56,8 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private String currentFhirBase = "";
private String collapseClass = "panel-collapse in";
private boolean multExpectationsPresent = false;
//Private classes for driving the rendering
@ -289,30 +294,30 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
x.h(2,"title").addText(conf.getTitle());
XhtmlNode uList = x.ul();
uList.li().addText(/*!#*/"Implementation Guide Version: " + igVersion);
uList.li().addText(/*!#*/"FHIR Version: " + currentVersion.toCode());
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_IMP_VER, igVersion) + " ");
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_FHIR_VER, currentVersion.toCode()) + " ");
addSupportedFormats(uList, conf);
uList.li().addText(/*!#*/"Published on: " + displayDateTime(conf.getDateElement()));
uList.li().addText(/*!#*/"Published by: " + conf.getPublisherElement().asStringValue());
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_PUB_ON, displayDateTime(conf.getDateElement()) + " "));
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_PUB_BY, conf.getPublisherElement().asStringValue()) + " ");
XhtmlNode block = x.addTag("blockquote").attribute("class","impl-note");
block.addTag("p").addTag("strong").addText(/*!#*/"Note to Implementers: FHIR Capabilities");
block.addTag("p").addText(/*!#*/"Any FHIR capability may be 'allowed' by the system unless explicitly marked as \"SHALL NOT\". A few items are marked as MAY in the Implementation Guide to highlight their potential relevance to the use case.");
block.addTag("p").addTag("strong").addText(context.formatPhrase(RenderingContext.CAPABILITY_NOTE_CAP));
block.addTag("p").addText(context.formatPhrase(RenderingContext.CAPABILTY_ALLOW_CAP));
addSupportedCSs(x, conf);
addSupportedIGs(x, conf);
int restNum = conf.getRest().size();
int nextLevel = 3;
if (restNum > 0) {
x.h(2,"rest").addText(/*!#*/"FHIR RESTful Capabilities");
x.h(2,"rest").addText((context.formatPhrase(RenderingContext.CAPABILITY_REST_CAPS)));
int count=1;
for (CapabilityStatementRestComponent rest : conf.getRest()) {
if (restNum > 1) {
x.h(3,"rest"+Integer.toString(count)).addText(/*!#*/"REST Configuration " + Integer.toString(count));
x.h(3,"rest"+Integer.toString(count)).addText(context.formatPhrase(RenderingContext.CAPABILITY_REST_CONFIG, Integer.toString(count)) + " ");
nextLevel = 4;
}
addRestConfigPanel(x, rest, nextLevel, count);
@ -330,8 +335,8 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
hasUpdates = hasUpdates || hasOp(r, TypeRestfulInteraction.HISTORYINSTANCE);
}
if (rest.getResource().size() >0) {
x.h(nextLevel,"resourcesCap" + Integer.toString(count)).addText(/*!#*/"Capabilities by Resource/Profile");
x.h(nextLevel+1,"resourcesSummary" + Integer.toString(count)).addText(/*!#*/"Summary");
x.h(nextLevel,"resourcesCap" + Integer.toString(count)).addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_PRO));
x.h(nextLevel+1,"resourcesSummary" + Integer.toString(count)).addText(context.formatPhrase(RenderingContext.GENERAL_SUMM));
addSummaryIntro(x);
addSummaryTable(x, rest, hasVRead, hasPatch, hasDelete, hasHistory, hasUpdates, count);
x.addTag("hr");
@ -346,6 +351,10 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
}
if (multExpectationsPresent) {
addWarningPanel(x,"⹋⹋ - this mark indicates that there are more than one expectation extensions present");
}
return true;
}
@ -415,6 +424,37 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
return null;
}
private void addSupportedCSs(XhtmlNode x, CapabilityStatement cap) {
if (cap.hasInstantiates()) {
XhtmlNode p = x.para();
p.tx(cap.getInstantiates().size() > 1 ? "This CapabilityStatement instantiates these CapabilityStatements" : "This CapabilityStatement instantiates the CapabilityStatement");
boolean first = true;
for (CanonicalType ct : cap.getInstantiates()) {
CapabilityStatement cs = context.getContext().fetchResource(CapabilityStatement.class, ct.getValue(), cap);
if (first) {first = false;} else {p.tx(", ");};
if (cs == null) {
p.code().tx(ct.getValue());
} else {
p.ah(cs.getWebPath()).tx(cs.present());
}
}
}
if (cap.hasImports()) {
XhtmlNode p = x.para();
p.tx(cap.getImports().size() > 1 ? "This CapabilityStatement imports these CapabilityStatements" : "This CapabilityStatement imports the CapabilityStatement");
boolean first = true;
for (CanonicalType ct : cap.getImports()) {
CapabilityStatement cs = context.getContext().fetchResource(CapabilityStatement.class, ct.getValue(), cap);
if (first) {first = false;} else {p.tx(", ");};
if (cs == null) {
p.code().tx(ct.getValue());
} else {
p.ah(cs.getWebPath()).tx(cs.present());
}
}
}
}
private void addSupportedIGs(XhtmlNode x, CapabilityStatement cap) {
String capExpectation=null;
if (cap.hasImplementationGuide()) {
@ -442,7 +482,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
XhtmlNode ul = null;
if (igShalls.size() > 0) {
x.h(3,"shallIGs").addText(/*!#*/"SHALL Support the Following Implementation Guides");
x.h(3,"shallIGs").addText(context.formatPhrase(RenderingContext.CAPABILTY_SHALL_SUPP));
ul = x.ul();
for (String url : igShalls) {
addResourceLink(ul.li(), url, url);
@ -450,7 +490,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
}
if (igShoulds.size() > 0) {
x.h(3,"shouldIGs").addText(/*!#*/"SHOULD Support the Following Implementation Guides");
x.h(3,"shouldIGs").addText(context.formatPhrase(RenderingContext.CAPABILITY_SHOULD_SUPP));
ul = x.ul();
for (String url : igShoulds) {
addResourceLink(ul.li(), url, url);
@ -458,7 +498,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
}
if (igMays.size() > 0) {
x.h(3,"shouldIGs").addText(/*!#*/"SHOULD Support the Following Implementation Guides");
x.h(3,"shouldIGs").addText(context.formatPhrase(RenderingContext.CAPABILITY_SHOULD_SUPP));
ul = x.ul();
for (String url : igMays) {
addResourceLink(ul.li(), url, url);
@ -471,7 +511,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private void addSupportedFormats(XhtmlNode uList, CapabilityStatement conf) {
XhtmlNode lItem = uList.li();
lItem.addText(/*!#*/"Supported Formats: ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_FORM) + " ");
Boolean first = true;
String capExpectation = null;
for (CodeType c : conf.getFormat()) {
@ -481,13 +521,13 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
capExpectation = getExtValueCode(c.getExtensionByUrl(EXPECTATION));
if (!Utilities.noString(capExpectation)) {
lItem.addTag("strong").addText(capExpectation);
lItem.addText(" "+/*!#*/"support ");
lItem.addText(" "+ (context.formatPhrase(RenderingContext.CAPABILITY_SUPP) + " "));
}
lItem.code().addText(c.getCode());
first = false;
}
lItem = uList.li();
lItem.addText(/*!#*/"Supported Patch Formats: ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_PATCH_FORM) + " ");
first=true;
for (CodeType c : conf.getPatchFormat()) {
if (!first) {
@ -496,7 +536,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
capExpectation = getExtValueCode(c.getExtensionByUrl(EXPECTATION));
if (!Utilities.noString(capExpectation)) {
lItem.addTag("strong").addText(capExpectation);
lItem.addText(/*!#*/" support ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP) + " ");
}
lItem.code().addText(c.getCode());
first = false;
@ -533,16 +573,16 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
addMarkdown(body.blockquote(),mdText);
}
}
body.div().attribute("class","lead").addTag("em").addText(/*!#*/"Summary of System-wide Interactions");
body.div().attribute("class","lead").addTag("em").addText(context.formatPhrase(RenderingContext.CAPABILITY_SUMM_SYS_INT));
addSystemInteractions(body, rest.getInteraction());
}
private String getCorsText(boolean on) {
if (on) {
return /*!#*/"Enable CORS: yes";
return context.formatPhrase(RenderingContext.CAPABILITY_CORS_YES);
}
return /*!#*/"Enable CORS: no";
return context.formatPhrase(RenderingContext.CAPABILITY_CORS_NO);
}
private List<String> getSecServices(List<CodeableConcept> services)
@ -613,20 +653,20 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
for (Map<String,String> interactionMap : interactions) {
item = uList.li();
if (Utilities.noString(verb)) {
item.addText(/*!#*/"Supports the ");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_THE) + " ");
}
else {
item.addTag("strong").addText(verb);
item.addText(/*!#*/" support the ");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_THE) + " ");
}
interaction = interactionMap.keySet().toArray()[0].toString();
item.code(interaction);
documentation = interactionMap.get(interaction);
if (Utilities.noString(documentation)) {
item.addText(/*!#*/" interaction.");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_INT));
}
else {
item.addText(/*!#*/" interaction described as follows:");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_INT_DESC));
try {
addMarkdown(item, documentation);
} catch (FHIRFormatError e) {
@ -647,11 +687,11 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
if (interactions.size() == 0) return;
XhtmlNode item = uList.li();
if (Utilities.noString(verb)) {
item.addText(/*!#*/"Supports ");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPPS) + " ");
}
else {
item.addTag("strong").addText(verb);
item.addText(/*!#*/" support ");
item.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP) + " ");
}
addSeparatedListOfCodes(item, interactions, ",");
item.addText(".");
@ -660,11 +700,11 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private void addSummaryIntro(XhtmlNode x) {
XhtmlNode uList = null;
XhtmlNode lItem = null;
x.para().addText(/*!#*/"The summary table lists the resources that are part of this configuration, and for each resource it lists:");
x.para().addText(context.formatPhrase(RenderingContext.CAPABILITY_SUMM_RES));
uList=x.ul();
uList.li().addText(/*!#*/"The relevant profiles (if any)");
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_REV_PROF));
lItem = uList.li();
lItem.addText(/*!#*/"The interactions supported by each resource (");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_INTER_SUPP));
lItem.b().addTag("span").attribute("class","bg-info").addText("R");
lItem.addText("ead, ");
lItem.b().addTag("span").attribute("class","bg-info").addText("S");
@ -686,40 +726,40 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
lItem.b().addTag("span").attribute("class","bg-info").addText("H");
lItem.addText("istory on ");
lItem.b().addTag("span").attribute("class","bg-info").addText("T");
lItem.addText(/*!#*/"ype are only present if at least one of the resources has support for them.");
uList.li().addTag("span").addText(/*!#*/"The required, recommended, and some optional search parameters (if any). ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_TYP_PRES));
uList.li().addTag("span").addText(context.formatPhrase(RenderingContext.CAPABILITY_SEARCH_PAR) + " ");
lItem = uList.li();
lItem.addText(/*!#*/"The linked resources enabled for ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_ENB) + " ");
lItem.code().addText("_include");
lItem = uList.li();
lItem.addText(/*!#*/"The other resources enabled for ");
lItem.addText(context.formatPhrase(RenderingContext.CAPABILITY_OTH_RES_ENB) + " ");
lItem.code().addText("_revinclude");
uList.li().addText(/*!#*/"The operations on the resource (if any)");
uList.li().addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_OPER));
}
private void addSummaryTable(XhtmlNode x, CapabilityStatement.CapabilityStatementRestComponent rest, boolean hasVRead, boolean hasPatch, boolean hasDelete, boolean hasHistory, boolean hasUpdates, int count) throws IOException {
XhtmlNode t = x.div().attribute("class","table-responsive").table("table table-condensed table-hover");
XhtmlNode tr = t.addTag("thead").tr();
tr.th().b().tx(/*!#*/"Resource Type");
tr.th().b().tx(/*!#*/"Profile");
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"GET a resource (read interaction)").tx("R");
tr.th().b().tx(context.formatPhrase(RenderingContext.CAPABILITY_RES_TYP));
tr.th().b().tx(context.formatPhrase(RenderingContext.GENERAL_PROF));
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_READ_INT)).tx("R");
if (hasVRead)
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"GET past versions of resources (vread interaction)").tx("V-R");
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"GET all set of resources of the type (search interaction)").tx("S");
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"PUT a new resource version (update interaction)").tx("U");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_VREAD_INT)).tx("V-R");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_SEARCH_INT)).tx("S");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_UPDATE_INT)).tx("U");
if (hasPatch)
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"PATCH a new resource version (patch interaction)").tx("P");
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"POST a new resource (create interaction)").tx("C");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_PATCH_INT)).tx("P");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_CREATE_INT)).tx("C");
if (hasDelete)
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"DELETE a resource (delete interaction)").tx("D");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_DELETE_INT)).tx("D");
if (hasUpdates)
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"GET changes to a resource (history interaction on instance)").tx("H-I");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_HISTORY_INT)).tx("H-I");
if (hasHistory)
tr.th().attribute("class", "text-center").b().attribute("title", /*!#*/"GET changes for all resources of the type (history interaction on type)").tx("H-T");
tr.th().b().attribute("title", /*!#*/"Required and recommended search parameters").tx(/*!#*/"Searches");
tr.th().attribute("class", "text-center").b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_HISTORY_TYPE)).tx("H-T");
tr.th().b().attribute("title", context.formatPhrase(RenderingContext.CAPABILITY_REQ_RECOM)).tx(context.formatPhrase(RenderingContext.CAPABILITY_SEARCHES));
tr.th().code().b().tx("_include");
tr.th().code().b().tx("_revinclude");
tr.th().b().tx(/*!#*/"Operations");
tr.th().b().tx(context.formatPhrase(RenderingContext.CAPABILITY_OP));
XhtmlNode tbody = t.addTag("tbody");
XhtmlNode profCell = null;
@ -744,12 +784,12 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
//profCell.ah(r.getProfile()).addText(r.getProfile());
if (hasSupProf) {
profCell.br();
profCell.addTag("em").addText(/*!#*/"Additional supported profiles:");
profCell.addTag("em").addText(context.formatPhrase(RenderingContext.CAPABILITY_ADD_SUPP_PROF));
renderSupportedProfiles(profCell, r);
}
}
else { //Case of only supported profiles
profCell.addText(/*!#*/"Supported profiles:");
profCell.addText(context.formatPhrase(RenderingContext.CAPABILITY_SUPP_PROFS));
renderSupportedProfiles(profCell, r);
}
//Show capabilities
@ -786,7 +826,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private List<String> getCombinedParams(List<String> paramNames, List<Extension> paramExtensions) {
for (Extension e : paramExtensions) {
String capExpectation = e.getExtensionString(EXPECTATION);
String capExpectation = expectationForDisplay(e,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
if (capExpectation.equals("SHALL") || capExpectation.equals("SHOULD") || capExpectation.equals("MAY")) {
paramNames.add(printCombinedParams(e));
@ -809,17 +849,17 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
if (r.hasExtension(ToolingExtensions.EXT_PROFILE_MAPPING)) {
profCell.br();
profCell.b().tx(/*!#*/"Profile Mapping");
profCell.b().tx(context.formatPhrase(RenderingContext.CAPABILITY_PROF_MAP));
XhtmlNode tbl = profCell.table("grid");
boolean doco = false;
for (Extension ext : r.getExtensionsByUrl(ToolingExtensions.EXT_PROFILE_MAPPING)) {
doco = doco || ext.hasExtension("documentation");
}
XhtmlNode tr = tbl.tr();
tr.th().tx(/*!#*/"Criteria");
tr.th().tx(/*!#*/"Profile");
tr.th().tx(context.formatPhrase(RenderingContext.GENERAL_CRIT));
tr.th().tx(context.formatPhrase(RenderingContext.GENERAL_PROF));
if (doco) {
tr.th().tx(/*!#*/"Criteria");
tr.th().tx(context.formatPhrase(RenderingContext.GENERAL_CRIT));
}
for (Extension ext : r.getExtensionsByUrl(ToolingExtensions.EXT_PROFILE_MAPPING)) {
tr = tbl.tr();
@ -859,7 +899,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private List<String> getParams(List<String> paramNames, List<CapabilityStatementRestResourceSearchParamComponent> params) {
for (CapabilityStatementRestResourceSearchParamComponent p : params) {
String capExpectation = p.getExtensionString(EXPECTATION);
String capExpectation = expectationForDisplay(p,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
if (capExpectation.equals("SHALL") || capExpectation.equals("SHOULD") || capExpectation.equals("MAY")) {
paramNames.add(p.getName());
@ -907,7 +947,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
private List<String> getStringListFromOperations(List<CapabilityStatementRestResourceOperationComponent> list) {
List<String> result = new ArrayList<String>();
for (CapabilityStatementRestResourceOperationComponent op : list) {
String capExpectation = op.getExtensionString(EXPECTATION);
String capExpectation = expectationForDisplay(op,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
if (capExpectation.equals("SHALL") || capExpectation.equals("SHOULD") || capExpectation.equals("MAY")) {
result.add("$"+op.getName());
@ -936,7 +976,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
else {
panelHead = panel.div().attribute("class", "panel-heading").h(nextLevel,r.getType() + countString).attribute("class", "panel-title");
panelHead.span("float: right;","").addText(/*!#*/"Resource Conformance: " + getResourceExpectation(r));
panelHead.span("float: right;","").addText(context.formatPhrase(RenderingContext.CAPABILITY_RES_CONF, getResourceExpectation(r)) + " ");
panelHead.addText(r.getType());
body = panel.div().attribute("class", "panel-body").div().attribute("class", "container");
}
@ -950,17 +990,17 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
String refPolicyWidth = "col-lg-3";
if (!Utilities.noString(text)) {
cell = row.div().attribute("class", "col-lg-6");
addLead(cell,/*!#*/"Base System Profile");
addLead(cell,context.formatPhrase(RenderingContext.CAPABILITY_BASE_SYS));
cell.br();
addResourceLink(cell, text, text);
cell=row.div().attribute("class", "col-lg-3");
addLead(cell, /*!#*/"Profile Conformance");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_PROF_CONF));
cell.br();
cell.b().addText(getProfileExpectation(r.getProfileElement()));
}
else { //No profile, use FHIR Core Resource
cell = row.div().attribute("class", "col-lg-4");
addLead(cell,/*!#*/"Core FHIR Resource");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_FHIR));
cell.br();
cell.ah(currentFhirBase + r.getType().toLowerCase() + ".html").addText(r.getType());
pullInteraction = true;
@ -968,7 +1008,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
cell = row.div().attribute("class", refPolicyWidth);
addLead(cell,/*!#*/"Reference Policy");
addLead(cell,context.formatPhrase(RenderingContext.CAPABILITY_REF_PROF));
cell.br();
addSeparatedListOfCodes(cell, getReferencePolicyStrings(r.getReferencePolicy()) , ",");
if (pullInteraction) {
@ -979,7 +1019,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
if (supportedProfiles.size() > 0) {
row = body.div().attribute("class", "row");
cell = row.div().attribute("class", "col-6");
addLead(cell,/*!#*/"Supported Profiles");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_SUPP_PROFS));
XhtmlNode para = cell.para();
boolean first = true;
for (CanonicalType c : supportedProfiles) {
@ -1004,7 +1044,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
if (!Utilities.noString(mdText)) {
row = body.div().attribute("class", "row");
cell = row.div().attribute("class", "col-12");
addLead(cell,/*!#*/"Documentation");
addLead(cell, context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
addMarkdown(cell.blockquote(), mdText);
}
@ -1028,12 +1068,12 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
XhtmlNode tr;
row = body.div().attribute("class", "row");
cell = row.div().attribute("class", "col-12");
addLead(cell,/*!#*/"Extended Operations");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_EXT_OP));
table = cell.table("table table-condensed table-hover");
tr = table.addTag("thead").tr();
tr.th().addText(/*!#*/"Conformance");
tr.th().addText(/*!#*/"Operation");
tr.th().addText(/*!#*/"Documentation");
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_CONFORMANCE));
tr.th().addText(context.formatPhrase(RenderingContext.CAPABILITY_OPER));
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
tbody = table.addTag("tbody");
addOps(tbody, map, "supported");
addOps(tbody, map, "SHALL");
@ -1051,7 +1091,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
ResourceOperations ops = new ResourceOperations();
for ( CapabilityStatementRestResourceOperationComponent op : opList) {
capExpectation = op.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(op,EXPECTATION);
if (Utilities.noString(capExpectation)) {
capExpectation = "supported";
}
@ -1071,7 +1111,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
List<String> supporteds = new ArrayList<String>();
for (ResourceInteractionComponent op : r.getInteraction()) {
capExpectation = op.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(op,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
switch(capExpectation) {
case "SHALL" : shalls.add(op.getCode().toCode());
@ -1089,7 +1129,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
}
XhtmlNode cell = row.div().attribute("class", widthString);
addLead(cell, /*!#*/"Interaction summary");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_INT_SUMM));
cell.br();
XhtmlNode ul = cell.ul();
addInteractionSummaryList(ul, "SHALL", shalls);
@ -1104,7 +1144,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
String capExpectation;
SingleParam param;
for ( CapabilityStatementRestResourceSearchParamComponent sp : r.getSearchParam()) {
capExpectation = sp.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(sp,EXPECTATION);
if (Utilities.noString(capExpectation)) {
capExpectation = "supported";
}
@ -1116,7 +1156,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
CombinedSearchParamSet combinedParams;
String paramName;
for (Extension e : r.getExtensionsByUrl(COMBINED)) {
capExpectation = e.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(e,EXPECTATION);
if (Utilities.noString(capExpectation)) {
capExpectation = "supported";
}
@ -1154,13 +1194,13 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
XhtmlNode tr;
row = body.div().attribute("class", "row");
cell = row.div().attribute("class", "col-lg-7");
addLead(cell,/*!#*/"Search Parameters");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_SEARCH_PARS));
table = cell.table("table table-condensed table-hover");
tr = table.addTag("thead").tr();
tr.th().addText(/*!#*/"Conformance");
tr.th().addText(/*!#*/"Parameter");
tr.th().addText(/*!#*/"Type");
tr.th().addText(/*!#*/"Documentation");
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_CONFORMANCE));
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_PAR));
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_TYPE));
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
tbody = table.addTag("tbody");
Map<String,List<SingleParam>> map = sParams.getIndbyExp();
addIndRows(tbody, map, "supported");
@ -1170,12 +1210,12 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
addIndRows(tbody, map, "SHOULD-NOT");
cell = row.div().attribute("class", "col-lg-5");
if (!isCombinedEmpty(comboMap)) {
addLead(cell,/*!#*/"Combined Search Parameters");
addLead(cell, context.formatPhrase(RenderingContext.CAPABILITY_COMB_SEARCH_PAR));
table = cell.table("table table-condensed table-hover");
tr = table.addTag("thead").tr();
tr.th().addText(/*!#*/"Conformance");
tr.th().addText(/*!#*/"Parameters");
tr.th().addText(/*!#*/"Types");
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_CONFORMANCE));
tr.th().addText(context.formatPhrase(RenderingContext.GENERAL_PARS));
tr.th().addText(context.formatPhrase(RenderingContext.CAPABILITY_TYPS));
tbody = table.addTag("tbody");
addComboRows(tbody, comboMap, "supported");
addComboRows(tbody, comboMap, "SHALL");
@ -1356,14 +1396,14 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
return stringList;
}
private String getResourceExpectation(CapabilityStatementRestResourceComponent r) {
String capExpectation = r.getExtensionString(EXPECTATION);
String capExpectation = expectationForDisplay(r,EXPECTATION);
if (!Utilities.noString(capExpectation)) return capExpectation;
boolean shalls = false;
boolean shoulds = false;
boolean mays = false;
boolean shouldnots = false;
for (ResourceInteractionComponent ric : r.getInteraction()) {
capExpectation = ric.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(ric,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
switch(capExpectation) {
case "SHALL" : shalls = true;
@ -1380,7 +1420,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
if (shalls) return "SHALL";
//Check search parameters requirements
for ( CapabilityStatementRestResourceSearchParamComponent sp : r.getSearchParam()) {
capExpectation = sp.getExtensionString(EXPECTATION);
capExpectation = expectationForDisplay(sp,EXPECTATION);
if (!Utilities.noString(capExpectation)) {
switch(capExpectation) {
case "SHALL" : shalls = true;
@ -1402,7 +1442,7 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
private String getProfileExpectation(CanonicalType r) {
String capExpectation = r.getExtensionString(EXPECTATION);
String capExpectation = expectationForDisplay(r,EXPECTATION);
if (!Utilities.noString(capExpectation)) return capExpectation;
return "SHALL";
}
@ -1463,4 +1503,27 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
}
}
}
private String expectationForDisplay(Element e, String url) {
String result;
try {
result = e.getExtensionString(url);
return result;
}
catch (FHIRException fex) {
List<Extension> ext = e.getExtensionsByUrl(url);
if (ext.isEmpty())
return null;
if (!ext.get(0).hasValue())
return null;
multExpectationsPresent = true;
return ext.get(0).getValue().primitiveValue() + "-⹋⹋";
}
}
private void addWarningPanel(XhtmlNode node, String text) {
XhtmlNode panel = node.addTag("div").attribute("class","panel panel-danger").addTag("div").attribute("class","panel-body");
panel.addTag("span").attribute("class","label label-danger").addText("Error detected");
panel.addText(" " + text);
}
}

View File

@ -23,9 +23,13 @@ import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.PrimitiveType;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.renderers.CodeSystemRenderer.Translateable;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.MultiLanguagePolicy;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
@ -38,6 +42,27 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class CodeSystemRenderer extends TerminologyRenderer {
public class Translateable {
private String lang;
private StringType value;
public Translateable(String lang, StringType value) {
this.lang = lang;
this.value = value;
}
public String getLang() {
return lang;
}
public StringType getValue() {
return value;
}
}
private Boolean doMarkdown = null;
public CodeSystemRenderer(RenderingContext context) {
@ -82,13 +107,13 @@ public class CodeSystemRenderer extends TerminologyRenderer {
private void generateFilters(XhtmlNode x, CodeSystem cs) {
if (cs.hasFilter()) {
x.para().b().tx(formatMessage(RenderingContext.CODESYSTEM_FILTERS));
x.para().b().tx(formatPhrase(RenderingContext.CODESYSTEM_FILTERS));
XhtmlNode tbl = x.table("grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_FILTER_CODE));
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_FILTER_DESC));
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_FILTER_OP));
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_FILTER_VALUE));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_CODE));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_DESC));
tr.td().b().tx(formatPhrase(RenderingContext.CODESYSTEM_FILTER_OP));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_VALUE));
for (CodeSystemFilterComponent f : cs.getFilter()) {
tr = tbl.tr();
renderStatus(f, tr.td()).tx(f.getCode());
@ -107,30 +132,30 @@ public class CodeSystemRenderer extends TerminologyRenderer {
boolean hasURI = false;
boolean hasDescription = false;
for (PropertyComponent p : cs.getProperty()) {
hasRendered = hasRendered || !p.getCode().equals(ToolingExtensions.getPresentation(p, p.getCodeElement()));
hasRendered = hasRendered || getDisplayForProperty(p) != null;
hasURI = hasURI || p.hasUri();
hasDescription = hasDescription || p.hasDescription();
}
x.para().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROPS));
x.para().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROPS_DESC));
x.para().b().tx(formatPhrase(RenderingContext.GENERAL_PROPS));
x.para().b().tx(formatPhrase(RenderingContext.CODESYSTEM_PROPS_DESC));
XhtmlNode tbl = x.table("grid");
XhtmlNode tr = tbl.tr();
if (hasRendered) {
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROP_NAME));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_NAME));
}
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROP_CODE));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_CODE));
if (hasURI) {
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROP_URI));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_URI));
}
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROP_TYPE));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_TYPE));
if (hasDescription) {
tr.td().b().tx(formatMessage(RenderingContext.CODESYSTEM_PROP_DESC));
tr.td().b().tx(formatPhrase(RenderingContext.GENERAL_DESC));
}
for (PropertyComponent p : cs.getProperty()) {
tr = tbl.tr();
if (hasRendered) {
tr.td().tx(ToolingExtensions.getPresentation(p, p.getCodeElement()));
tr.td().tx(getDisplayForProperty(p));
}
renderStatus(p, tr.td()).tx(p.getCode());
if (hasURI) {
@ -148,33 +173,36 @@ public class CodeSystemRenderer extends TerminologyRenderer {
}
private String sentenceForContent(CodeSystemContentMode mode, CodeSystem cs) {
if (mode == null) {
return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_NOTPRESENT);
}
switch (mode) {
case COMPLETE: return formatMessage(RenderingContext.CODESYSTEM_CONTENT_COMPLETE);
case EXAMPLE: return formatMessage(RenderingContext.CODESYSTEM_CONTENT_EXAMPLE);
case FRAGMENT: return formatMessage(RenderingContext.CODESYSTEM_CONTENT_FRAGMENT);
case NOTPRESENT: return formatMessage(RenderingContext.CODESYSTEM_CONTENT_NOTPRESENT);
case COMPLETE: return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_COMPLETE);
case EXAMPLE: return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_EXAMPLE);
case FRAGMENT: return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_FRAGMENT);
case NOTPRESENT: return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_NOTPRESENT);
case SUPPLEMENT:
boolean properties = CodeSystemUtilities.hasProperties(cs);
boolean designations = CodeSystemUtilities.hasDesignations(cs);
String features;
if (properties && designations) {
features = /*!#*/"displays and properties";
features = (context.formatPhrase(RenderingContext.CODE_SYS_DISP_PROP));
} else if (properties) {
features = /*!#*/"properties";
features = (context.formatPhrase(RenderingContext.CODE_SYS_PROP));
} else if (designations) {
features = /*!#*/"displays";
features = (context.formatPhrase(RenderingContext.CODE_SYS_DISP));
} else {
features = /*!#*/"features"; // ?
features = (context.formatPhrase(RenderingContext.CODE_SYS_FEAT)); // ?
}
return formatMessage(RenderingContext.CODESYSTEM_CONTENT_SUPPLEMENT, features);
return formatPhrase(RenderingContext.CODESYSTEM_CONTENT_SUPPLEMENT, features);
default:
throw new FHIRException(/*!#*/"Unknown CodeSystemContentMode mode");
throw new FHIRException(context.formatPhrase(RenderingContext.CODE_SYS_UNKN_MODE));
}
}
private boolean generateCodeSystemContent(XhtmlNode x, CodeSystem cs, boolean hasExtensions, List<UsedConceptMap> maps, boolean props) throws FHIRFormatError, DefinitionException, IOException {
if (props) {
x.para().b().tx(formatMessage(RenderingContext.CODESYSTEM_CONCEPTS));
x.para().b().tx(formatPhrase(RenderingContext.CODESYSTEM_CONCEPTS));
}
XhtmlNode p = x.para();
renderStatus(cs.getUrlElement(), p.param("cs")).code().tx(cs.getUrl());
@ -234,10 +262,10 @@ public class CodeSystemRenderer extends TerminologyRenderer {
}
if (langs.size() >= 2) {
Collections.sort(langs);
x.para().b().tx(/*!#*/"Additional Language Displays");
x.para().b().tx(context.formatPhrase(RenderingContext.GENERAL_ADD_LANG));
t = x.table("codes");
XhtmlNode tr = t.tr();
tr.td().b().tx(/*!#*/"Code");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE));
for (String lang : langs)
tr.td().b().addText(describeLang(lang));
for (ConceptDefinitionComponent c : cs.getConcept()) {
@ -250,11 +278,11 @@ public class CodeSystemRenderer extends TerminologyRenderer {
private void makeHierarchyParam(XhtmlNode x, CodeSystem cs, Enumeration<CodeSystemHierarchyMeaning> hm) {
if (hm.hasValue()) {
String s = hm.getValue().getDisplay();
renderStatus(hm, x).tx(" "+/*!#*/"in a "+s+" heirarchy");
renderStatus(hm, x).tx(" "+context.formatPhrase(RenderingContext.CODE_SYS_IN_A_HIERARCHY, s));
} else if (VersionComparisonAnnotation.hasDeleted(cs, "hierarchyMeaning")) {
makeHierarchyParam(x, null, (Enumeration<CodeSystemHierarchyMeaning>) VersionComparisonAnnotation.getDeleted(cs, "hierarchyMeaning").get(0));
} else if (CodeSystemUtilities.hasHierarchy(cs)) {
x.tx(" "+/*!#*/"in an undefined heirarchy");
x.tx(" "+ (context.formatPhrase(RenderingContext.CODE_SYS_UNDEF_HIER)));
} else {
x.tx("");
}
@ -285,7 +313,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
private void addCopyColumn(XhtmlNode tr) {
if (context.isCopyButton()) {
tr.td().b().tx(/*!#*/"Copy");
tr.td().b().tx(context.formatPhrase(RenderingContext.CODE_SYS_COPY));
}
}
@ -421,39 +449,53 @@ public class CodeSystemRenderer extends TerminologyRenderer {
if (hasDisplay) {
td = tr.td();
renderDisplayName(c, cs, td);
hasExtensions = renderDisplayName(c, cs, td, langs) || hasExtensions;
}
if (hasDefinitions) {
td = tr.td();
if (c != null &&c.hasDefinitionElement()) {
if (getContext().getLang() == null) {
if (hasMarkdownInDefinitions(cs)) {
addMarkdown(renderStatusDiv(c.getDefinitionElement(), td), c.getDefinition());
} else {
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
// translations of the definition might come from either the translation extension, or from the designations
StringType defn = context.getTranslatedElement(c.getDefinitionElement());
boolean sl = false;
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) {
sl = true;
}
} else if (getContext().getLang().equals("*")) {
boolean sl = false;
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue()))
sl = true;
td.addText((sl ? cs.getLanguage("en")+": " : ""));
if (hasMarkdownInDefinitions(cs))
addMarkdown(renderStatusDiv(c.getDefinitionElement(), td), c.getDefinition());
else
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
}
if (getContext().getMultiLanguagePolicy() == MultiLanguagePolicy.NONE || !(sl || ToolingExtensions.hasLanguageTranslations(defn))) {
if (hasMarkdownInDefinitions(cs)) {
addMarkdown(renderStatusDiv(defn, td), defn.asStringValue());
} else {
renderStatus(defn, td).addText(defn.asStringValue());
}
} else {
List<Translateable> list = new ArrayList<>();
list.add(new Translateable(cs.getLanguage(), defn));
for (Extension ext : defn.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATION)) {
hasExtensions = true;
list.add(new Translateable(ext.getExtensionString("lang"), ext.getExtensionByUrl("content").getValueStringType()));
}
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && !c.getDefinition().equalsIgnoreCase(cd.getValue())) {
td.br();
td.addText(cd.getLanguage()+": "+cd.getValue());
list.add(new Translateable(cd.getLanguage(), cd.getValueElement()));
}
}
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
renderStatus(c.getDefinitionElement(), td).addText(c.getDefinition());
} else {
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "definition") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) {
td.addText(cd.getValue());
boolean first = true;
for (Translateable ti : list) {
if (first) {
first = false;
} else {
td.br();
}
if (ti.lang != null) {
td.addText(ti.lang + ": ");
}
if (hasMarkdownInDefinitions(cs)) {
addMarkdown(renderStatusDiv(ti.getValue(), td), ti.getValue().asStringValue());
} else {
renderStatus(ti.getValue(), td).addText(ti.getValue().asStringValue());
}
}
}
@ -463,11 +505,11 @@ public class CodeSystemRenderer extends TerminologyRenderer {
td = tr.td();
Boolean b = CodeSystemUtilities.isDeprecated(cs, c, false);
if (b != null && b) {
smartAddText(td, formatMessage(RenderingContext.CODESYSTEM_DEPRECATED));
smartAddText(td, formatPhrase(RenderingContext.CODESYSTEM_DEPRECATED));
hasExtensions = true;
if (ToolingExtensions.hasExtension(c, ToolingExtensions.EXT_REPLACED_BY)) {
Coding cc = (Coding) ToolingExtensions.getExtension(c, ToolingExtensions.EXT_REPLACED_BY).getValue();
td.tx(" "+/*!#*/"(replaced by ");
td.tx(" "+ context.formatPhrase(RenderingContext.CODE_SYS_REPLACED_BY) + " ");
String url = getCodingReference(cc, system);
if (url != null) {
td.ah(url).addText(cc.getCode());
@ -488,39 +530,30 @@ public class CodeSystemRenderer extends TerminologyRenderer {
if (comment) {
td = tr.td();
Extension ext = c.getExtensionByUrl(ToolingExtensions.EXT_CS_COMMENT);
if (ext != null) {
if (ext != null && ext.hasValue() && ext.getValue().primitiveValue() != null) {
hasExtensions = true;
String bc = ext.hasValue() ? ext.getValue().primitiveValue() : null;
Map<String, String> translations = ToolingExtensions.getLanguageTranslations(ext.getValue());
if (getContext().getLang() == null) {
if (bc != null)
td.addText(bc);
} else if (getContext().getLang().equals("*")) {
boolean sl = false;
for (String l : translations.keySet())
if (bc == null || !bc.equalsIgnoreCase(translations.get(l)))
sl = true;
if (bc != null) {
td.addText((sl ? cs.getLanguage("en")+": " : "")+bc);
}
for (String l : translations.keySet()) {
if (bc == null || !bc.equalsIgnoreCase(translations.get(l))) {
if (!td.getChildNodes().isEmpty())
td.br();
td.addText(l+": "+translations.get(l));
}
}
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
if (bc != null)
td.addText(bc);
StringType defn = context.getTranslatedElement((PrimitiveType<?>) ext.getValue());
if (getContext().getMultiLanguagePolicy() == MultiLanguagePolicy.NONE ||!(ToolingExtensions.hasLanguageTranslations(ext.getValue()))) {
td.addText(defn.asStringValue());
} else {
if (bc != null)
translations.put(cs.getLanguage("en"), bc);
for (String l : translations.keySet()) {
if (l.equals(getContext().getLang())) {
td.addText(translations.get(l));
List<Translateable> list = new ArrayList<>();
list.add(new Translateable(cs.getLanguage(), defn));
for (Extension ex : defn.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATION)) {
hasExtensions = true;
list.add(new Translateable(ex.getExtensionString("lang"), ex.getExtensionByUrl("content").getValueStringType()));
}
boolean first = true;
for (Translateable ti : list) {
if (first) {
first = false;
} else {
td.br();
}
if (ti.lang != null) {
td.addText(ti.lang + ": ");
}
renderStatus(ti.getValue(), td).addText(ti.getValue().asStringValue());
}
}
}
@ -596,7 +629,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
a.addText(cc.getCode());
if (hasDisplay) {
td = tr.td();
renderDisplayName(cc, cs, td);
hasExtensions = renderDisplayName(cc, cs, td, langs) || hasExtensions;
}
int w = 1 + (deprecated ? 1 : 0) + (comment ? 1 : 0) + (version ? 1 : 0) + maps.size();
if (properties != null) {
@ -606,9 +639,9 @@ public class CodeSystemRenderer extends TerminologyRenderer {
}
if (context.isCopyButton()) {
td = tr.td();
clipboard(td, "icon_clipboard_x.png", /*!#*/"XML", "<system value=\""+Utilities.escapeXml(cs.getUrl())+"\">\n"+(cs.getVersionNeeded() ? "<version value=\""+Utilities.escapeXml(cs.getVersion())+"\">\n" : "")+"<code value=\""+Utilities.escapeXml(c.getCode())+"\">\n<display value=\""+Utilities.escapeXml(c.getDisplay())+"\">\n");
clipboard(td, "icon_clipboard_x.png", "XML", "<system value=\""+Utilities.escapeXml(cs.getUrl())+"\">\n"+(cs.getVersionNeeded() ? "<version value=\""+Utilities.escapeXml(cs.getVersion())+"\">\n" : "")+"<code value=\""+Utilities.escapeXml(c.getCode())+"\">\n<display value=\""+Utilities.escapeXml(c.getDisplay())+"\">\n");
td.nbsp();
clipboard(td, "icon_clipboard_j.png", /*!#*/"JSON", "\"system\" : \""+Utilities.escapeXml(cs.getUrl())+"\",\n"+(cs.getVersionNeeded() ? "\"version\" : \""+Utilities.escapeXml(cs.getVersion())+"\",\n" : "")+"\"code\" : \""+Utilities.escapeXml(c.getCode())+"\",\n\"display\" : \""+Utilities.escapeXml(c.getDisplay())+"\"\n");
clipboard(td, "icon_clipboard_j.png", "JSON", "\"system\" : \""+Utilities.escapeXml(cs.getUrl())+"\",\n"+(cs.getVersionNeeded() ? "\"version\" : \""+Utilities.escapeXml(cs.getVersion())+"\",\n" : "")+"\"code\" : \""+Utilities.escapeXml(c.getCode())+"\",\n\"display\" : \""+Utilities.escapeXml(c.getDisplay())+"\"\n");
}
return hasExtensions;
}
@ -639,32 +672,44 @@ public class CodeSystemRenderer extends TerminologyRenderer {
}
public void renderDisplayName(ConceptDefinitionComponent c, CodeSystem cs, XhtmlNode td) {
public boolean renderDisplayName(ConceptDefinitionComponent c, CodeSystem cs, XhtmlNode td, List<String> langs) {
boolean hasExtensions = false;
if (c.hasDisplayElement()) {
if (getContext().getLang() == null) {
renderStatus(c.getDisplayElement(), td).addText(c.getDisplay());
} else if (getContext().getLang().equals("*")) {
boolean sl = false;
for (ConceptDefinitionDesignationComponent cd : c.getDesignation())
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue()))
sl = true;
td.addText((sl ? cs.getLanguage("en")+": " : "")+c.getDisplay());
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && !c.getDisplay().equalsIgnoreCase(cd.getValue())) {
td.br();
td.addText(cd.getLanguage()+": "+cd.getValue());
}
StringType disp = c.getDisplayElement();
List<Translateable> list = new ArrayList<>();
list.add(new Translateable(cs.getLanguage(), disp));
for (Extension ext : disp.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATION)) {
if (!langs.contains(ext.getExtensionString("lang"))) {
hasExtensions = true;
list.add(new Translateable(ext.getExtensionString("lang"), ext.getExtensionByUrl("content").getValueStringType()));
}
} else if (getContext().getLang().equals(cs.getLanguage()) || (getContext().getLang().equals("en") && !cs.hasLanguage())) {
renderStatus(c.getDisplayElement(), td).addText(c.getDisplay());
} else {
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.getUse().is("http://terminology.hl7.org/CodeSystem/designation-usage", "display") && cd.hasLanguage() && cd.getLanguage().equals(getContext().getLang())) {
td.addText(cd.getValue());
}
}
}
}
for (ConceptDefinitionDesignationComponent cd : c.getDesignation()) {
if (cd.hasLanguage() && (langs == null || !langs.contains(cd.getLanguage())) && (c.getDefinition() == null || !c.getDefinition().equalsIgnoreCase(cd.getValue()))) {
list.add(new Translateable(cd.getLanguage(), cd.getValueElement()));
}
}
if (getContext().getMultiLanguagePolicy() == MultiLanguagePolicy.NONE || list.size() <= 1) {
renderStatus(disp, td).addText(disp.asStringValue());
} else {
boolean first = true;
for (Translateable ti : list) {
if (first) {
first = false;
} else {
td.br();
}
if (ti.lang != null) {
td.addText(ti.lang + ": ");
}
renderStatus(ti.getValue(), td).addText(ti.getValue().asStringValue());
}
}
}
return hasExtensions;
}
private String getCodingReference(Coding cc, String system) {

View File

@ -314,23 +314,23 @@ public class ConceptMapRenderer extends TerminologyRenderer {
}
XhtmlNode p = x.para();
p.tx(/*!#*/"Mapping from ");
p.tx(context.formatPhrase(RenderingContext.CONC_MAP_FROM) + " ");
if (cm.hasSourceScope())
AddVsRef(cm.getSourceScope().primitiveValue(), p, cm);
else
p.tx(/*!#*/"(not specified)");
p.tx(" "+/*!#*/"to ");
p.tx(context.formatPhrase(RenderingContext.CONC_MAP_NOT_SPEC));
p.tx(" "+ (context.formatPhrase(RenderingContext.CONC_MAP_TO) + " "));
if (cm.hasTargetScope())
AddVsRef(cm.getTargetScope().primitiveValue(), p, cm);
else
p.tx(/*!#*/"(not specified)");
p.tx(context.formatPhrase(RenderingContext.CONC_MAP_NOT_SPEC));
p = x.para();
if (cm.getExperimental())
p.addText(Utilities.capitalize(cm.getStatus().toString())+" "+/*!#*/"(not intended for production usage). ");
p.addText(Utilities.capitalize(cm.getStatus().toString())+" "+ (context.formatPhrase(RenderingContext.CONC_MAP_NO_PROD_USE) + " "));
else
p.addText(Utilities.capitalize(cm.getStatus().toString())+". ");
p.tx(/*!#*/"Published on "+(cm.hasDate() ? display(cm.getDateElement()) : "?ngen-10?")+" by "+cm.getPublisher());
p.tx(context.formatPhrase(RenderingContext.CONC_MAP_PUB_ON, (cm.hasDate() ? display(cm.getDateElement()) : "?ngen-10?")+" by "+cm.getPublisher()) + " ");
if (!cm.getContact().isEmpty()) {
p.tx(" (");
boolean firsti = true;
@ -400,18 +400,18 @@ public class ConceptMapRenderer extends TerminologyRenderer {
x.hr();
}
XhtmlNode pp = x.para();
pp.b().tx(/*!#*/"Group "+gc);
pp.tx(" "+/*!#*/"Mapping from ");
pp.b().tx(context.formatPhrase(RenderingContext.CONC_MAP_GRP, gc) + " ");
pp.tx(context.formatPhrase(RenderingContext.CONC_MAP_FROM) + " ");
if (grp.hasSource()) {
renderCanonical(cm, pp, grp.getSource());
} else {
pp.code(/*!#*/"unspecified code system");
pp.code(context.formatPhrase(RenderingContext.CONC_MAP_CODE_SYS_UNSPEC));
}
pp.tx(" to ");
if (grp.hasTarget()) {
renderCanonical(cm, pp, grp.getTarget());
} else {
pp.code(/*!#*/"unspecified code system");
pp.code(context.formatPhrase(RenderingContext.CONC_MAP_CODE_SYS_UNSPEC));
}
String display;
@ -419,11 +419,11 @@ public class ConceptMapRenderer extends TerminologyRenderer {
// simple
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(/*!#*/"Source Code");
tr.td().b().tx(/*!#*/"Relationship");
tr.td().b().tx(/*!#*/"Target Code");
tr.td().b().tx(context.formatPhrase(RenderingContext.CONC_MAP_SOURCE));
tr.td().b().tx(context.formatPhrase(RenderingContext.CONC_MAP_REL));
tr.td().b().tx(context.formatPhrase(RenderingContext.CONC_MAP_TRGT));
if (comment)
tr.td().b().tx(/*!#*/"Comment");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_COMMENT));
for (SourceElementComponent ccl : grp.getElement()) {
tr = tbl.tr();
XhtmlNode td = tr.td();
@ -470,21 +470,21 @@ public class ConceptMapRenderer extends TerminologyRenderer {
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
XhtmlNode td;
tr.td().colspan(Integer.toString(1+sources.size())).b().tx(/*!#*/"Source Concept Details");
tr.td().colspan(Integer.toString(1+sources.size())).b().tx(context.formatPhrase(RenderingContext.CONC_MAP_SRC_DET));
if (hasRelationships) {
tr.td().b().tx(/*!#*/"Relationship");
tr.td().b().tx(context.formatPhrase(RenderingContext.CONC_MAP_REL));
}
tr.td().colspan(Integer.toString(1+targets.size())).b().tx(/*!#*/"Target Concept Details");
tr.td().colspan(Integer.toString(1+targets.size())).b().tx(context.formatPhrase(RenderingContext.CONC_MAP_TRGT_DET));
if (comment) {
tr.td().b().tx(/*!#*/"Comment");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_COMMENT));
}
tr.td().colspan(Integer.toString(1+targets.size())).b().tx(/*!#*/"Properties");
tr.td().colspan(Integer.toString(1+targets.size())).b().tx(context.formatPhrase(RenderingContext.GENERAL_PROPS));
tr = tbl.tr();
if (sources.get("code").size() == 1) {
String url = sources.get("code").iterator().next();
renderCSDetailsLink(tr, url, true);
} else
tr.td().b().tx(/*!#*/"Code");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE));
for (String s : sources.keySet()) {
if (s != null && !s.equals("code")) {
if (sources.get(s).size() == 1) {
@ -501,7 +501,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
String url = targets.get("code").iterator().next();
renderCSDetailsLink(tr, url, true);
} else
tr.td().b().tx(/*!#*/"Code");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE));
for (String s : targets.keySet()) {
if (s != null && !s.equals("code")) {
if (targets.get(s).size() == 1) {
@ -698,8 +698,8 @@ public class ConceptMapRenderer extends TerminologyRenderer {
if (span2) {
td.colspan("2");
}
td.b().tx(/*!#*/"Codes");
td.tx(" "+/*!#*/"from ");
td.b().tx(context.formatPhrase(RenderingContext.CONC_MAP_CODES));
td.tx(" " + (context.formatPhrase(RenderingContext.CONC_MAP_FRM) + " "));
if (cs == null)
td.tx(url);
else
@ -783,7 +783,7 @@ public class ConceptMapRenderer extends TerminologyRenderer {
private static void renderLinks(XhtmlNode td, List<CollateralDefinition> collateral) {
if (collateral.size() > 0) {
td.tx(/*!#*/"Links:");
td.tx( "Links:");
td.tx(" ");
boolean first = true;
for (CollateralDefinition c : collateral) {

View File

@ -1,488 +1,488 @@
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DiagnosticReport;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.DirectWrappers;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class DiagnosticReportRenderer extends ResourceRenderer {
public class ObservationNode {
private String ref;
private ResourceWithReference obs;
private List<ObservationNode> contained;
}
public DiagnosticReportRenderer(RenderingContext context) {
super(context);
}
public DiagnosticReportRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
return render(x, (DiagnosticReport) dr);
}
public boolean render(XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome {
XhtmlNode h2 = x.h2();
render(h2, getProperty(dr, "code").value());
h2.tx(" ");
PropertyWrapper pw = getProperty(dr, "category");
if (valued(pw)) {
h2.tx("(");
boolean first = true;
for (BaseWrapper b : pw.getValues()) {
if (first) first = false; else h2.tx(", ");
render(h2, b);
}
h2.tx(") ");
}
XhtmlNode tbl = x.table("grid");
XhtmlNode tr;
if (dr.has("subject")) {
tr = tbl.tr();
tr.td().tx(/*!#*/"Subject");
populateSubjectSummary(tr.td(), getProperty(dr, "subject").value());
}
DataType eff = null;
DataType iss = null;
if (dr.has("effective[x]")) {
tr = tbl.tr();
tr.td().tx(/*!#*/"When For");
eff = (DataType) getProperty(dr, "effective[x]").value().getBase();
render(tr.td(), eff);
}
if (dr.has("issued")) {
tr = tbl.tr();
tr.td().tx(/*!#*/"Reported");
eff = (DataType) getProperty(dr, "issued").value().getBase();
render(tr.td(), getProperty(dr, "issued").value());
}
pw = getProperty(dr, "perfomer");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize(/*!#*/"Performer", pw.getValues().size()));
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
}
pw = getProperty(dr, "identifier");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize(/*!#*/"Identifier", pw.getValues().size())+":");
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
}
pw = getProperty(dr, "request");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize(/*!#*/"Request", pw.getValues().size())+":");
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
tdr.br();
}
x.para().b().tx(/*!#*/"Report Details");
pw = getProperty(dr, "result");
if (valued(pw)) {
List<ObservationNode> observations = fetchObservations(pw.getValues(), dr);
buildObservationsTable(x, observations, eff, iss);
}
pw = getProperty(dr, "conclusion");
if (valued(pw)) {
if (pw.fhirType().equals("markdown")) {
render(x, pw.value());
} else {
render(x.para(), pw.value());
}
}
pw = getProperty(dr, "conclusionCode");
if (!valued(pw)) {
pw = getProperty(dr, "codedDiagnosis");
}
if (valued(pw)) {
XhtmlNode p = x.para();
p.b().tx(/*!#*/"Coded Conclusions :");
XhtmlNode ul = x.ul();
for (BaseWrapper v : pw.getValues()) {
render(ul.li(), v);
}
}
return false;
}
public boolean render(XhtmlNode x, DiagnosticReport dr) throws IOException, FHIRException, EOperationOutcome {
render(x, new DirectWrappers.ResourceWrapperDirect(this.context, dr));
return true;
}
public void describe(XhtmlNode x, DiagnosticReport dr) {
x.tx(display(dr));
}
public String display(DiagnosticReport dr) {
return display(dr.getCode());
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return display((DiagnosticReport) r);
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return "Not done yet";
}
private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome {
ResourceWrapper r = fetchResource(subject);
if (r == null)
container.tx(/*!#*/"Unable to get Patient Details");
else if (r.getName().equals("Patient"))
generatePatientSummary(container, r);
else
container.tx(/*!#*/"Not done yet");
}
private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
new PatientRenderer(context).describe(c, r);
}
private List<ObservationNode> fetchObservations(List<BaseWrapper> list, ResourceWrapper rw) throws UnsupportedEncodingException, FHIRException, IOException {
List<ObservationNode> res = new ArrayList<ObservationNode>();
for (BaseWrapper b : list) {
if (b.has("reference")) {
ObservationNode obs = new ObservationNode();
obs.ref = b.get("reference").primitiveValue();
obs.obs = resolveReference(rw, obs.ref);
if (obs.obs != null && obs.obs.getResource() != null) {
PropertyWrapper t = getProperty(obs.obs.getResource(), "contained");
if (t != null && t.hasValues()) {
obs.contained = fetchObservations(t.getValues(), rw);
}
}
res.add(obs);
}
}
return res;
}
private void buildObservationsTable(XhtmlNode root, List<ObservationNode> observations, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tbl = root.table("grid");
boolean refRange = scanObsForRefRange(observations);
boolean flags = scanObsForFlags(observations);
boolean note = scanObsForNote(observations);
boolean effectiveTime = scanObsForEffective(observations, eff);
boolean issued = scanObsForIssued(observations, iss);
int cs = 2;
if (refRange) cs++;
if (flags) cs++;
if (note) cs++;
if (issued) cs++;
if (effectiveTime) cs++;
XhtmlNode tr = tbl.tr();
tr.td().b().tx(/*!#*/"Code");
tr.td().b().tx(/*!#*/"Value");
if (refRange) {
tr.td().b().tx(/*!#*/"Reference Range");
}
if (flags) {
tr.td().b().tx(/*!#*/"Flags");
}
if (note) {
tr.td().b().tx(/*!#*/"Note");
}
if (effectiveTime) {
tr.td().b().tx(/*!#*/"When For");
}
if (issued) {
tr.td().b().tx(/*!#*/"Reported");
}
for (ObservationNode o : observations) {
addObservationToTable(tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss);
}
}
private boolean scanObsForRefRange(List<ObservationNode> observations) {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "referenceRange");
if (valued(pw)) {
return true;
}
}
if (o.contained != null) {
if (scanObsForRefRange(o.contained)) {
return true;
}
}
}
return false;
}
private boolean scanObsForNote(List<ObservationNode> observations) {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "note");
if (valued(pw)) {
return true;
}
}
if (o.contained != null) {
if (scanObsForNote(o.contained)) {
return true;
}
}
}
return false;
}
private boolean scanObsForIssued(List<ObservationNode> observations, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "issued");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), iss, true)) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForIssued(o.contained, iss)) {
return true;
}
}
}
return false;
}
private boolean scanObsForEffective(List<ObservationNode> observations, DataType eff) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "effective[x]");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForEffective(o.contained, eff)) {
return true;
}
}
}
return false;
}
private boolean scanObsForFlags(List<ObservationNode> observations) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "interpretation");
if (valued(pw)) {
return true;
}
pw = getProperty(o.obs.getResource(), "status");
if (valued(pw)) {
if (!pw.value().getBase().primitiveValue().equals("final")) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForFlags(o.contained)) {
return true;
}
}
}
return false;
}
private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tr = tbl.tr();
if (o.obs != null && o.obs.getReference() == null) {
XhtmlNode td = tr.td().colspan(cs);
td.i().tx(/*!#*/"This Observation could not be resolved");
} else {
if (o.obs != null && o.obs.getResource() != null) {
addObservationToTable(tr, o.obs.getResource(), i, o.obs.getReference(), refRange, flags, note, effectiveTime, issued, eff, iss);
} else {
XhtmlNode td = tr.td().colspan(cs);
td.i().tx(/*!#*/"Observation");
}
if (o.contained != null) {
for (ObservationNode c : o.contained) {
addObservationToTable(tbl, c, i+1, cs, refRange, flags, note, effectiveTime, issued, eff, iss);
}
}
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.DataType;
import org.hl7.fhir.r5.model.DiagnosticReport;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.PropertyWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.DirectWrappers;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class DiagnosticReportRenderer extends ResourceRenderer {
public class ObservationNode {
private String ref;
private ResourceWithReference obs;
private List<ObservationNode> contained;
}
public DiagnosticReportRenderer(RenderingContext context) {
super(context);
}
public DiagnosticReportRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
return render(x, (DiagnosticReport) dr);
}
public boolean render(XhtmlNode x, ResourceWrapper dr) throws IOException, FHIRException, EOperationOutcome {
XhtmlNode h2 = x.h2();
render(h2, getProperty(dr, "code").value());
h2.tx(" ");
PropertyWrapper pw = getProperty(dr, "category");
if (valued(pw)) {
h2.tx("(");
boolean first = true;
for (BaseWrapper b : pw.getValues()) {
if (first) first = false; else h2.tx(", ");
render(h2, b);
}
h2.tx(") ");
}
}
private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
// code (+bodysite)
XhtmlNode td = tr.td();
PropertyWrapper pw = getProperty(obs, "code");
if (valued(pw)) {
render(td.ah(ref), pw.value());
}
pw = getProperty(obs, "bodySite");
if (valued(pw)) {
td.tx(" (");
render(td, pw.value());
td.tx(")");
}
// value / dataAbsentReason (in red)
td = tr.td();
pw = getProperty(obs, "value[x]");
if (valued(pw)) {
render(td, pw.value());
} else {
pw = getProperty(obs, "dataAbsentReason");
if (valued(pw)) {
XhtmlNode span = td.span("color: maroon", "Error");
span.tx(/*!#*/"Error: ");
render(span.b(), pw.value());
}
}
if (refRange) {
// reference range
td = tr.td();
pw = getProperty(obs, "referenceRange");
if (valued(pw)) {
boolean first = true;
for (BaseWrapper v : pw.getValues()) {
if (first) first = false; else td.br();
PropertyWrapper pwr = getProperty(v, "type");
if (valued(pwr)) {
render(td, pwr.value());
td.tx(": ");
}
PropertyWrapper pwt = getProperty(v, "text");
if (valued(pwt)) {
render(td, pwt.value());
} else {
PropertyWrapper pwl = getProperty(v, "low");
PropertyWrapper pwh = getProperty(v, "high");
if (valued(pwl) && valued(pwh)) {
render(td, pwl.value());
td.tx(" - ");
render(td, pwh.value());
} else if (valued(pwl)) {
td.tx(">");
render(td, pwl.value());
} else if (valued(pwh)) {
td.tx("<");
render(td, pwh.value());
} else {
td.tx("??");
}
}
pwr = getProperty(v, "appliesTo");
PropertyWrapper pwrA = getProperty(v, "age");
if (valued(pwr) || valued(pwrA)) {
boolean firstA = true;
td.tx(" "+/*!#*/"for ");
if (valued(pwr)) {
for (BaseWrapper va : pwr.getValues()) {
if (firstA) firstA = false; else td.tx(", ");
render(td, va);
}
}
if (valued(pwrA)) {
if (firstA) firstA = false; else td.tx(", ");
td.tx(/*!#*/"Age ");
render(td, pwrA.value());
}
}
}
}
}
if (flags) {
// flags (status other than F, interpretation, )
td = tr.td();
boolean first = true;
pw = getProperty(obs, "status");
if (valued(pw)) {
if (!pw.value().getBase().primitiveValue().equals("final")) {
if (first) first = false; else td.br();
render(td, pw.value());
}
}
pw = getProperty(obs, "interpretation");
if (valued(pw)) {
for (BaseWrapper v : pw.getValues()) {
if (first) first = false; else td.br();
render(td, v);
}
}
}
if (note) {
td = tr.td();
pw = getProperty(obs, "note");
if (valued(pw)) {
render(td, pw.value());
}
}
if (effectiveTime) {
// effective if different to DR
td = tr.td();
pw = getProperty(obs, "effective[x]");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
render(td, pw.value());
}
}
}
if (issued) {
// issued if different to DR
td = tr.td();
pw = getProperty(obs, "issued");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
render(td, pw.value());
}
}
}
}
}
XhtmlNode tbl = x.table("grid");
XhtmlNode tr;
if (dr.has("subject")) {
tr = tbl.tr();
tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_SUBJ));
populateSubjectSummary(tr.td(), getProperty(dr, "subject").value());
}
DataType eff = null;
DataType iss = null;
if (dr.has("effective[x]")) {
tr = tbl.tr();
tr.td().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_WHEN));
eff = (DataType) getProperty(dr, "effective[x]").value().getBase();
render(tr.td(), eff);
}
if (dr.has("issued")) {
tr = tbl.tr();
tr.td().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REP));
eff = (DataType) getProperty(dr, "issued").value().getBase();
render(tr.td(), getProperty(dr, "issued").value());
}
pw = getProperty(dr, "perfomer");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.DIAG_REP_REND_PER)), pw.getValues().size()));
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
}
pw = getProperty(dr, "identifier");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.DIAG_REP_REND_IDENTIFIER)), pw.getValues().size())+":");
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
}
pw = getProperty(dr, "request");
if (valued(pw)) {
tr = tbl.tr();
tr.td().tx(Utilities.pluralize((context.formatPhrase(RenderingContext.GENERAL_REQUEST)), pw.getValues().size())+":");
XhtmlNode tdr = tr.td();
for (BaseWrapper v : pw.getValues()) {
tdr.tx(" ");
render(tdr, v);
}
tdr.br();
}
x.para().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REPDET));
pw = getProperty(dr, "result");
if (valued(pw)) {
List<ObservationNode> observations = fetchObservations(pw.getValues(), dr);
buildObservationsTable(x, observations, eff, iss);
}
pw = getProperty(dr, "conclusion");
if (valued(pw)) {
if (pw.fhirType().equals("markdown")) {
render(x, pw.value());
} else {
render(x.para(), pw.value());
}
}
pw = getProperty(dr, "conclusionCode");
if (!valued(pw)) {
pw = getProperty(dr, "codedDiagnosis");
}
if (valued(pw)) {
XhtmlNode p = x.para();
p.b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_CODECON));
XhtmlNode ul = x.ul();
for (BaseWrapper v : pw.getValues()) {
render(ul.li(), v);
}
}
return false;
}
public boolean render(XhtmlNode x, DiagnosticReport dr) throws IOException, FHIRException, EOperationOutcome {
render(x, new DirectWrappers.ResourceWrapperDirect(this.context, dr));
return true;
}
public void describe(XhtmlNode x, DiagnosticReport dr) {
x.tx(display(dr));
}
public String display(DiagnosticReport dr) {
return display(dr.getCode());
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return display((DiagnosticReport) r);
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return "Not done yet";
}
private void populateSubjectSummary(XhtmlNode container, BaseWrapper subject) throws UnsupportedEncodingException, FHIRException, IOException, EOperationOutcome {
ResourceWrapper r = fetchResource(subject);
if (r == null)
container.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_UNABLE));
else if (r.getName().equals("Patient"))
generatePatientSummary(container, r);
else
container.tx(context.formatPhrase(RenderingContext.GENERAL_TODO));
}
private void generatePatientSummary(XhtmlNode c, ResourceWrapper r) throws FHIRFormatError, DefinitionException, FHIRException, IOException, EOperationOutcome {
new PatientRenderer(context).describe(c, r);
}
private List<ObservationNode> fetchObservations(List<BaseWrapper> list, ResourceWrapper rw) throws UnsupportedEncodingException, FHIRException, IOException {
List<ObservationNode> res = new ArrayList<ObservationNode>();
for (BaseWrapper b : list) {
if (b.has("reference")) {
ObservationNode obs = new ObservationNode();
obs.ref = b.get("reference").primitiveValue();
obs.obs = resolveReference(rw, obs.ref);
if (obs.obs != null && obs.obs.getResource() != null) {
PropertyWrapper t = getProperty(obs.obs.getResource(), "contained");
if (t != null && t.hasValues()) {
obs.contained = fetchObservations(t.getValues(), rw);
}
}
res.add(obs);
}
}
return res;
}
private void buildObservationsTable(XhtmlNode root, List<ObservationNode> observations, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tbl = root.table("grid");
boolean refRange = scanObsForRefRange(observations);
boolean flags = scanObsForFlags(observations);
boolean note = scanObsForNote(observations);
boolean effectiveTime = scanObsForEffective(observations, eff);
boolean issued = scanObsForIssued(observations, iss);
int cs = 2;
if (refRange) cs++;
if (flags) cs++;
if (note) cs++;
if (issued) cs++;
if (effectiveTime) cs++;
XhtmlNode tr = tbl.tr();
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_VALUE));
if (refRange) {
tr.td().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REFRAN));
}
if (flags) {
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_FLAGS));
}
if (note) {
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_NOTE));
}
if (effectiveTime) {
tr.td().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_WHEN));
}
if (issued) {
tr.td().b().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_REP));
}
for (ObservationNode o : observations) {
addObservationToTable(tbl, o, 0, Integer.toString(cs), refRange, flags, note, effectiveTime, issued, eff, iss);
}
}
private boolean scanObsForRefRange(List<ObservationNode> observations) {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "referenceRange");
if (valued(pw)) {
return true;
}
}
if (o.contained != null) {
if (scanObsForRefRange(o.contained)) {
return true;
}
}
}
return false;
}
private boolean scanObsForNote(List<ObservationNode> observations) {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "note");
if (valued(pw)) {
return true;
}
}
if (o.contained != null) {
if (scanObsForNote(o.contained)) {
return true;
}
}
}
return false;
}
private boolean scanObsForIssued(List<ObservationNode> observations, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "issued");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), iss, true)) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForIssued(o.contained, iss)) {
return true;
}
}
}
return false;
}
private boolean scanObsForEffective(List<ObservationNode> observations, DataType eff) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "effective[x]");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForEffective(o.contained, eff)) {
return true;
}
}
}
return false;
}
private boolean scanObsForFlags(List<ObservationNode> observations) throws UnsupportedEncodingException, FHIRException, IOException {
for (ObservationNode o : observations) {
if (o.obs != null && o.obs.getResource() != null) {
PropertyWrapper pw = getProperty(o.obs.getResource(), "interpretation");
if (valued(pw)) {
return true;
}
pw = getProperty(o.obs.getResource(), "status");
if (valued(pw)) {
if (!pw.value().getBase().primitiveValue().equals("final")) {
return true;
}
}
}
if (o.contained != null) {
if (scanObsForFlags(o.contained)) {
return true;
}
}
}
return false;
}
private void addObservationToTable(XhtmlNode tbl, ObservationNode o, int i, String cs, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
XhtmlNode tr = tbl.tr();
if (o.obs != null && o.obs.getReference() == null) {
XhtmlNode td = tr.td().colspan(cs);
td.i().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_NOTRES));
} else {
if (o.obs != null && o.obs.getResource() != null) {
addObservationToTable(tr, o.obs.getResource(), i, o.obs.getReference(), refRange, flags, note, effectiveTime, issued, eff, iss);
} else {
XhtmlNode td = tr.td().colspan(cs);
td.i().tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_OBS));
}
if (o.contained != null) {
for (ObservationNode c : o.contained) {
addObservationToTable(tbl, c, i+1, cs, refRange, flags, note, effectiveTime, issued, eff, iss);
}
}
}
}
private void addObservationToTable(XhtmlNode tr, ResourceWrapper obs, int i, String ref, boolean refRange, boolean flags, boolean note, boolean effectiveTime, boolean issued, DataType eff, DataType iss) throws UnsupportedEncodingException, FHIRException, IOException {
// code (+bodysite)
XhtmlNode td = tr.td();
PropertyWrapper pw = getProperty(obs, "code");
if (valued(pw)) {
render(td.ah(ref), pw.value());
}
pw = getProperty(obs, "bodySite");
if (valued(pw)) {
td.tx(" (");
render(td, pw.value());
td.tx(")");
}
// value / dataAbsentReason (in red)
td = tr.td();
pw = getProperty(obs, "value[x]");
if (valued(pw)) {
render(td, pw.value());
} else {
pw = getProperty(obs, "dataAbsentReason");
if (valued(pw)) {
XhtmlNode span = td.span("color: maroon", "Error");
span.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_ERR) + " ");
render(span.b(), pw.value());
}
}
if (refRange) {
// reference range
td = tr.td();
pw = getProperty(obs, "referenceRange");
if (valued(pw)) {
boolean first = true;
for (BaseWrapper v : pw.getValues()) {
if (first) first = false; else td.br();
PropertyWrapper pwr = getProperty(v, "type");
if (valued(pwr)) {
render(td, pwr.value());
td.tx(": ");
}
PropertyWrapper pwt = getProperty(v, "text");
if (valued(pwt)) {
render(td, pwt.value());
} else {
PropertyWrapper pwl = getProperty(v, "low");
PropertyWrapper pwh = getProperty(v, "high");
if (valued(pwl) && valued(pwh)) {
render(td, pwl.value());
td.tx(" - ");
render(td, pwh.value());
} else if (valued(pwl)) {
td.tx(">");
render(td, pwl.value());
} else if (valued(pwh)) {
td.tx("<");
render(td, pwh.value());
} else {
td.tx("??");
}
}
pwr = getProperty(v, "appliesTo");
PropertyWrapper pwrA = getProperty(v, "age");
if (valued(pwr) || valued(pwrA)) {
boolean firstA = true;
td.tx(" "+ (context.formatPhrase(RenderingContext.DIAG_REP_REND_FOR)) + " ");
if (valued(pwr)) {
for (BaseWrapper va : pwr.getValues()) {
if (firstA) firstA = false; else td.tx(", ");
render(td, va);
}
}
if (valued(pwrA)) {
if (firstA) firstA = false; else td.tx(", ");
td.tx(context.formatPhrase(RenderingContext.DIAG_REP_REND_AGE) + " ");
render(td, pwrA.value());
}
}
}
}
}
if (flags) {
// flags (status other than F, interpretation, )
td = tr.td();
boolean first = true;
pw = getProperty(obs, "status");
if (valued(pw)) {
if (!pw.value().getBase().primitiveValue().equals("final")) {
if (first) first = false; else td.br();
render(td, pw.value());
}
}
pw = getProperty(obs, "interpretation");
if (valued(pw)) {
for (BaseWrapper v : pw.getValues()) {
if (first) first = false; else td.br();
render(td, v);
}
}
}
if (note) {
td = tr.td();
pw = getProperty(obs, "note");
if (valued(pw)) {
render(td, pw.value());
}
}
if (effectiveTime) {
// effective if different to DR
td = tr.td();
pw = getProperty(obs, "effective[x]");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
render(td, pw.value());
}
}
}
if (issued) {
// issued if different to DR
td = tr.td();
pw = getProperty(obs, "issued");
if (valued(pw)) {
if (!Base.compareDeep(pw.value().getBase(), eff, true)) {
render(td, pw.value());
}
}
}
}
}

View File

@ -43,11 +43,11 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
case PROCESSES:
return renderProcesses(x, scen);
default:
throw new FHIRException(/*!#*/"Unknown ExampleScenario Renderer Mode " + context.getScenarioMode());
throw new FHIRException(context.formatPhrase(RenderingContext.EX_SCEN_UN, context.getScenarioMode()) + " ");
}
}
} catch (Exception e) {
throw new FHIRException(/*!#*/"Error rendering ExampleScenario " + scen.getUrl(), e);
throw new FHIRException(context.formatPhrase(RenderingContext.EX_SCEN_ERR_REN, scen.getUrl(), e) + " ");
}
}
@ -105,7 +105,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
for (ExampleScenarioProcessStepComponent step: process.getStep()) {
plantUml += toPlantUml(step, stepPrefix(prefix, step, stepCount), scen, actorsActive, actorKeys);
if (step.getPause())
plantUml += /*!#*/"... time passes ...\n";
plantUml += context.formatPhrase(RenderingContext.EX_SCEN_TIME)+"\n";
stepCount++;
}
@ -119,7 +119,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
XhtmlNode n = new XhtmlDocument();
renderCanonical(scen, n, step.getWorkflow());
XhtmlNode ref = n.getChildNodes().get(0);
plantUml += noteOver(scen.getActor(), /*!#*/"Step " + trimPrefix(prefix) + " - See scenario\n" + creolLink(ref.getContent(), ref.getAttribute("href")));
plantUml += noteOver(scen.getActor(), context.formatPhrase(RenderingContext.EXAMPLE_SCEN_STEP_SCEN, trimPrefix(prefix), creolLink((ref.getContent()), ref.getAttribute("href"))));
} else if (step.hasProcess())
plantUml += toPlantUml(step.getProcess(), prefix, scen, actorKeys);
else {
@ -211,9 +211,9 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
public boolean renderActors(XhtmlNode x, ExampleScenario scen) throws IOException {
XhtmlNode tbl = x.table("table-striped table-bordered");
XhtmlNode thead = tbl.tr();
thead.th().addText(/*!#*/"Name");
thead.th().addText(/*!#*/"Type");
thead.th().addText(/*!#*/"Description");
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_NAME));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_TYPE));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_DESC));
for (ExampleScenarioActorComponent actor : scen.getActor()) {
XhtmlNode tr = tbl.tr();
XhtmlNode nameCell = tr.td();
@ -228,10 +228,10 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
public boolean renderInstances(XhtmlNode x, ExampleScenario scen) throws IOException {
XhtmlNode tbl = x.table("table-striped table-bordered");
XhtmlNode thead = tbl.tr();
thead.th().addText(/*!#*/"Name");
thead.th().addText(/*!#*/"Type");
thead.th().addText(/*!#*/"Content");
thead.th().addText(/*!#*/"Description");
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_NAME));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_TYPE));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_CONTENT));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_DESC));
Map<String, String> instanceNames = new HashMap<String, String>();
for (ExampleScenarioInstanceComponent instance : scen.getInstance()) {
@ -254,7 +254,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
if (!instance.hasStructureVersion() || instance.getStructureType().getSystem().equals("")) {
if (instance.hasStructureVersion())
typeCell.tx(/*!#*/"FHIR version " + instance.getStructureVersion() + " ");
typeCell.tx((context.formatPhrase(RenderingContext.EX_SCEN_FVER, instance.getStructureVersion()) + " ") + " ");
if (instance.hasStructureProfile()) {
renderCanonical(scen, typeCell, instance.getStructureProfile().toString());
} else {
@ -262,7 +262,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
}
} else {
render(typeCell, instance.getStructureVersionElement());
typeCell.tx(" "+/*!#*/"version " + instance.getStructureVersion());
typeCell.tx(" "+(context.formatPhrase(RenderingContext.GENERAL_VER_LOW, instance.getStructureVersion())+" "));
if (instance.hasStructureProfile()) {
typeCell.tx(" ");
renderCanonical(scen, typeCell, instance.getStructureProfile().toString());
@ -280,7 +280,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
XhtmlNode descCell = row.td();
addMarkdown(descCell, instance.getDescription());
if (instance.hasContainedInstance()) {
descCell.b().tx(/*!#*/"Contains: ");
descCell.b().tx(context.formatPhrase(RenderingContext.EX_SCEN_CONTA) + " ");
int containedCount = 1;
for (ExampleScenarioInstanceContainedInstanceComponent contained: instance.getContainedInstance()) {
String key = "i_" + contained.getInstanceReference();
@ -341,26 +341,26 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
public void renderProcess(XhtmlNode x, ExampleScenarioProcessComponent process, String prefix, Map<String, ExampleScenarioActorComponent> actors, Map<String, ExampleScenarioInstanceComponent> instances) throws IOException {
XhtmlNode div = x.div();
div.an("p_" + prefix);
div.b().tx(/*!#*/"Process: " + process.getTitle());
div.b().tx(context.formatPhrase(RenderingContext.EX_SCEN_PROC, process.getTitle())+" ");
if (process.hasDescription())
addMarkdown(div, process.getDescription());
if (process.hasPreConditions()) {
div.para().b().i().tx(/*!#*/"Pre-conditions:");
div.para().b().i().tx(context.formatPhrase(RenderingContext.EX_SCEN_PRECON));
addMarkdown(div, process.getPreConditions());
}
if (process.hasPostConditions()) {
div.para().b().i().tx(/*!#*/"Post-conditions:");
div.para().b().i().tx(context.formatPhrase(RenderingContext.EX_SCEN_POSTCON));
addMarkdown(div, process.getPostConditions());
}
XhtmlNode tbl = div.table("table-striped table-bordered").style("width:100%");
XhtmlNode thead = tbl.tr();
thead.th().addText(/*!#*/"Step");
thead.th().addText(/*!#*/"Name");
thead.th().addText(/*!#*/"Description");
thead.th().addText(/*!#*/"Initator");
thead.th().addText(/*!#*/"Receiver");
thead.th().addText(/*!#*/"Request");
thead.th().addText(/*!#*/"Response");
thead.th().addText(context.formatPhrase(RenderingContext.EX_SCEN_STEP));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_NAME));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_DESC));
thead.th().addText(context.formatPhrase(RenderingContext.EX_SCEN_IN));
thead.th().addText(context.formatPhrase(RenderingContext.EX_SCEN_REC));
thead.th().addText(context.formatPhrase(RenderingContext.GENERAL_REQUEST));
thead.th().addText(context.formatPhrase(RenderingContext.EX_SCEN_RES));
int stepCount = 1;
for (ExampleScenarioProcessStepComponent step: process.getStep()) {
renderStep(tbl, step, stepPrefix(prefix, step, stepCount), actors, instances);
@ -407,13 +407,13 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
prefixCell.tx(stepLabel.substring(stepLabel.indexOf(".") + 1));
if (step.hasProcess()) {
XhtmlNode n = row.td().colspan(6);
n.tx(/*!#*/"See subprocess" );
n.tx(context.formatPhrase(RenderingContext.EX_SCEN_SEE));
n.ah("#p_" + stepLabel, step.getProcess().getTitle());
n.tx(" "+/*!#*/"below");
n.tx(" "+ context.formatPhrase(RenderingContext.EX_SCEN_BEL));
} else if (step.hasWorkflow()) {
XhtmlNode n = row.td().colspan(6);
n.tx(/*!#*/"See other scenario ");
n.tx(context.formatPhrase(RenderingContext.EX_SCEN_OTH));
String link = new ContextUtilities(context.getWorker()).getLinkForUrl(context.getLink(KnownLinkType.SPEC), step.getWorkflow());
n.ah(link, step.getProcess().getTitle());
@ -438,7 +438,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
int altNum = 1;
for (ExampleScenarioProcessStepAlternativeComponent alt : step.getAlternative()) {
XhtmlNode altHeading = tbl.tr().colspan(7).td();
altHeading.para().i().tx(/*!#*/"Alternative " + alt.getTitle());
altHeading.para().i().tx(context.formatPhrase(RenderingContext.EX_SCEN_ALT, alt.getTitle())+" ");
if (alt.hasDescription())
addMarkdown(altHeading, alt.getDescription());
int stepCount = 1;
@ -458,7 +458,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
return;
ExampleScenarioActorComponent actor = actors.get(actorId);
if (actor==null)
throw new FHIRException(/*!#*/"Unable to find referenced actor " + actorId);
throw new FHIRException(context.formatPhrase(RenderingContext.EX_SCEN_UN_ACT, actorId)+" ");
actorCell.ah("#a_" + actor.getKey(), actor.getDescription()).tx(actor.getTitle());
}
@ -468,7 +468,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
return;
ExampleScenarioInstanceComponent instance = instances.get(instanceRef.getInstanceReference());
if (instance==null)
throw new FHIRException(/*!#*/"Unable to find referenced instance " + instanceRef.getInstanceReference());
throw new FHIRException(context.formatPhrase(RenderingContext.EX_SCEN_UN_INST, instanceRef.getInstanceReference())+" ");
if (instanceRef.hasVersionReference()) {
ExampleScenarioInstanceVersionComponent theVersion = null;
for (ExampleScenarioInstanceVersionComponent version: instance.getVersion()) {
@ -478,7 +478,7 @@ public class ExampleScenarioRenderer extends TerminologyRenderer {
}
}
if (theVersion==null)
throw new FHIRException(/*!#*/"Unable to find referenced version " + instanceRef.getVersionReference() + " within instance " + instanceRef.getInstanceReference());
throw new FHIRException("Unable to find referenced version " + instanceRef.getVersionReference() + " within instance " + instanceRef.getInstanceReference());
instanceCell.ah("#i_" + instance.getKey() + "v_"+ theVersion.getKey() , theVersion.getDescription()).tx(theVersion.getTitle());
} else

View File

@ -28,7 +28,7 @@ public class ImplementationGuideRenderer extends ResourceRenderer {
public boolean render(XhtmlNode x, ImplementationGuide ig) throws FHIRFormatError, DefinitionException, IOException {
x.h2().addText(ig.getName());
x.para().tx(/*!#*/"The official URL for this implementation guide is: ");
x.para().tx(context.formatPhrase(RenderingContext.IMP_GUIDE_URL)+" ");
x.pre().tx(ig.getUrl());
addMarkdown(x, ig.getDescription());
return true;

View File

@ -9,6 +9,7 @@ import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Attachment;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.ContactDetail;
import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.DataRequirement;
@ -49,32 +50,32 @@ public class LibraryRenderer extends ResourceRenderer {
boolean email = hasCT(authors, "email") || hasCT(editors, "email") || hasCT(reviewers, "email") || hasCT(endorsers, "email");
boolean phone = hasCT(authors, "phone") || hasCT(editors, "phone") || hasCT(reviewers, "phone") || hasCT(endorsers, "phone");
boolean url = hasCT(authors, "url") || hasCT(editors, "url") || hasCT(reviewers, "url") || hasCT(endorsers, "url");
x.h2().tx(/*!#*/"Participants");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_PAR));
XhtmlNode t = x.table("grid");
if (authors != null) {
for (BaseWrapper cd : authors.getValues()) {
participantRow(t, /*!#*/"Author", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_AUT)), cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : editors.getValues()) {
participantRow(t, /*!#*/"Editor", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_ED)), cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : reviewers.getValues()) {
participantRow(t, /*!#*/"Reviewer", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_REV)), cd, email, phone, url);
}
}
if (authors != null) {
for (BaseWrapper cd : endorsers.getValues()) {
participantRow(t, /*!#*/"Endorser", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_END)), cd, email, phone, url);
}
}
}
PropertyWrapper artifacts = lib.getChildByName("relatedArtifact");
if (artifacts != null && artifacts.hasValues()) {
x.h2().tx(/*!#*/"Related Artifacts");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_ART));
XhtmlNode t = x.table("grid");
boolean label = false;
boolean display = false;
@ -90,7 +91,7 @@ public class LibraryRenderer extends ResourceRenderer {
}
PropertyWrapper parameters = lib.getChildByName("parameter");
if (parameters != null && parameters.hasValues()) {
x.h2().tx(/*!#*/"Parameters");
x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode t = x.table("grid");
boolean doco = false;
for (BaseWrapper p : parameters.getValues()) {
@ -102,14 +103,14 @@ public class LibraryRenderer extends ResourceRenderer {
}
PropertyWrapper dataRequirements = lib.getChildByName("dataRequirement");
if (dataRequirements != null && dataRequirements.hasValues()) {
x.h2().tx(/*!#*/"Data Requirements");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_REQ));
for (BaseWrapper p : dataRequirements.getValues()) {
renderDataRequirement(x, (DataRequirement) p.getBase());
}
}
PropertyWrapper contents = lib.getChildByName("content");
if (contents != null) {
x.h2().tx(/*!#*/"Contents");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_CONT));
boolean isCql = false;
int counter = 0;
for (BaseWrapper p : contents.getValues()) {
@ -151,23 +152,23 @@ public class LibraryRenderer extends ResourceRenderer {
boolean email = hasCT(lib.getAuthor(), "email") || hasCT(lib.getEditor(), "email") || hasCT(lib.getReviewer(), "email") || hasCT(lib.getEndorser(), "email");
boolean phone = hasCT(lib.getAuthor(), "phone") || hasCT(lib.getEditor(), "phone") || hasCT(lib.getReviewer(), "phone") || hasCT(lib.getEndorser(), "phone");
boolean url = hasCT(lib.getAuthor(), "url") || hasCT(lib.getEditor(), "url") || hasCT(lib.getReviewer(), "url") || hasCT(lib.getEndorser(), "url");
x.h2().tx(/*!#*/"Participants");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_PAR));
XhtmlNode t = x.table("grid");
for (ContactDetail cd : lib.getAuthor()) {
participantRow(t, /*!#*/"Author", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_AUT)), cd, email, phone, url);
}
for (ContactDetail cd : lib.getEditor()) {
participantRow(t, /*!#*/"Editor", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_ED)), cd, email, phone, url);
}
for (ContactDetail cd : lib.getReviewer()) {
participantRow(t, /*!#*/"Reviewer", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_REV)), cd, email, phone, url);
}
for (ContactDetail cd : lib.getEndorser()) {
participantRow(t, /*!#*/"Endorser", cd, email, phone, url);
participantRow(t, (context.formatPhrase(RenderingContext.LIB_REND_END)), cd, email, phone, url);
}
}
if (lib.hasRelatedArtifact()) {
x.h2().tx(/*!#*/"Related Artifacts");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_ART));
XhtmlNode t = x.table("grid");
boolean label = false;
boolean display = false;
@ -182,7 +183,7 @@ public class LibraryRenderer extends ResourceRenderer {
}
}
if (lib.hasParameter()) {
x.h2().tx(/*!#*/"Parameters");
x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode t = x.table("grid");
boolean doco = false;
for (ParameterDefinition p : lib.getParameter()) {
@ -193,13 +194,13 @@ public class LibraryRenderer extends ResourceRenderer {
}
}
if (lib.hasDataRequirement()) {
x.h2().tx(/*!#*/"Data Requirements");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_REQ));
for (DataRequirement p : lib.getDataRequirement()) {
renderDataRequirement(x, p);
}
}
if (lib.hasContent()) {
x.h2().tx(/*!#*/"Contents");
x.h2().tx(context.formatPhrase(RenderingContext.LIB_REND_CONT));
boolean isCql = false;
int counter = 0;
for (Attachment att : lib.getContent()) {
@ -345,7 +346,14 @@ public class LibraryRenderer extends ResourceRenderer {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().ah(att.getUrl()).tx(att.getUrl());
Resource res = context.getContext().fetchResource(Resource.class, att.getUrl());
if (res == null || !res.hasWebPath()) {
p.code().ah(att.getUrl()).tx(att.getUrl());
} else if (res instanceof CanonicalResource) {
p.code().ah(res.getWebPath()).tx(((CanonicalResource) res).present());
} else {
p.code().ah(res.getWebPath()).tx(att.getUrl());
}
p.tx(" (");
p.code().tx(att.getContentType());
p.tx(lang(att));
@ -356,7 +364,7 @@ public class LibraryRenderer extends ResourceRenderer {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().tx(/*!#*/"No Content");
p.code().tx(context.formatPhrase(RenderingContext.LIB_REND_NOCONT));
p.tx(" (");
p.code().tx(att.getContentType());
p.tx(lang(att));
@ -405,10 +413,10 @@ public class LibraryRenderer extends ResourceRenderer {
p.tx(att.getTitle());
p.tx(": ");
}
p.code().tx(/*!#*/"Content not shown - (");
p.code().tx(context.formatPhrase(RenderingContext.LIB_REND_SHOW));
p.code().tx(att.getContentType());
p.tx(lang(att));
p.tx(/*!#*/", size = "+Utilities.describeSize(att.getData().length)+")");
p.tx((context.formatPhrase(RenderingContext.LIB_REND_SIZE, Utilities.describeSize(att.getData().length))+" ")+")");
}
}
}

View File

@ -144,8 +144,13 @@ public class LiquidRenderer extends ResourceRenderer implements ILiquidRendering
} else {
x.tx(base.toString());
}
String res = new XhtmlComposer(true).compose(x).substring(5);
return res.substring(0, res.length()-6);
String res = new XhtmlComposer(true).compose(x);
res = res.substring(5);
if (res.length() < 6) {
return "";
} else {
return res.substring(0, res.length()-6);
}
} catch (FHIRFormatError e) {
throw new FHIRException(e);
} catch (IOException e) {

View File

@ -1,253 +1,253 @@
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Annotation;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ListResource;
import org.hl7.fhir.r5.model.ListResource.ListResourceEntryComponent;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class ListRenderer extends ResourceRenderer {
public ListRenderer(RenderingContext context) {
super(context);
}
public ListRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (ListResource) dr);
}
public boolean render(XhtmlNode x, ResourceWrapper list) throws FHIRFormatError, DefinitionException, IOException {
if (list.has("title")) {
x.h2().tx(list.get("title").primitiveValue());
}
XhtmlNode t = x.table("clstu");
XhtmlNode tr = t.tr();
XhtmlNode td = tr.td();
if (list.has("date")) {
td.tx(/*!#*/"Date: "+displayDateTime(list.get("date").dateTimeValue()));
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Annotation;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ListResource;
import org.hl7.fhir.r5.model.ListResource.ListResourceEntryComponent;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.BaseWrapper;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceWithReference;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class ListRenderer extends ResourceRenderer {
public ListRenderer(RenderingContext context) {
super(context);
}
public ListRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (ListResource) dr);
}
public boolean render(XhtmlNode x, ResourceWrapper list) throws FHIRFormatError, DefinitionException, IOException {
if (list.has("title")) {
x.h2().tx(list.get("title").primitiveValue());
}
if (list.has("mode")) {
td.tx(/*!#*/"Mode: "+list.get("mode").primitiveValue());
}
if (list.has("status")) {
td.tx(/*!#*/"Status: "+list.get("status").primitiveValue());
}
if (list.has("code")) {
td.tx(/*!#*/"Code: "+displayBase(list.get("code")));
}
tr = t.tr();
td = tr.td();
if (list.has("subject")) {
td.tx(/*!#*/"Subject: ");
shortForRef(td, list.get("subject"));
}
if (list.has("encounter")) {
td.tx(/*!#*/"Encounter: ");
shortForRef(td, list.get("encounter"));
}
if (list.has("source")) {
td.tx(/*!#*/"Source: ");
shortForRef(td, list.get("encounter"));
}
if (list.has("orderedBy")) {
td.tx(/*!#*/"Order: "+displayBase(list.get("orderedBy")));
}
// for (Annotation a : list.getNote()) {
// renderAnnotation(a, x);
// }
boolean flag = false;
boolean deleted = false;
boolean date = false;
for (BaseWrapper e : list.children("entry")) {
flag = flag || e.has("flag");
deleted = deleted || e.has("deleted");
date = date || e.has("date");
}
t = x.table("grid");
tr = t.tr().style("backgound-color: #eeeeee");
tr.td().b().tx(/*!#*/"Items");
if (date) {
tr.td().tx(/*!#*/"Date");
}
if (flag) {
tr.td().tx(/*!#*/"Flag");
}
if (deleted) {
tr.td().tx(/*!#*/"Deleted");
}
for (BaseWrapper e : list.children("entry")) {
tr = t.tr();
shortForRef(tr.td(), e.get("item"));
if (date) {
tr.td().tx(e.has("date") ? e.get("date").dateTimeValue().toHumanDisplay() : "");
}
if (flag) {
tr.td().tx(e.has("flag") ? displayBase(e.get("flag")) : "");
}
if (deleted) {
tr.td().tx(e.has("deleted") ? e.get("deleted").primitiveValue() : "");
}
}
return false;
}
public boolean render(XhtmlNode x, ListResource list) throws FHIRFormatError, DefinitionException, IOException {
if (list.hasTitle()) {
x.h2().tx(list.getTitle());
}
XhtmlNode t = x.table("clstu");
XhtmlNode tr = t.tr();
if (list.hasDate()) {
tr.td().tx(/*!#*/"Date: "+displayDateTime(list.getDateElement()));
}
if (list.hasMode()) {
tr.td().tx(/*!#*/"Mode: "+list.getMode().getDisplay());
}
if (list.hasStatus()) {
tr.td().tx(/*!#*/"Status: "+list.getStatus().getDisplay());
}
if (list.hasCode()) {
tr.td().tx(/*!#*/"Code: "+display(list.getCode()));
}
tr = t.tr();
if (list.hasSubject()) {
if (list.getSubject().size() == 1) {
shortForRef(tr.td().txN("Subject: "), list.getSubjectFirstRep());
} else {
XhtmlNode td = tr.td();
td.txN(/*!#*/"Subject: ");
int i = 0;
for (Reference subj : list.getSubject()) {
if (i == list.getSubject().size() - 1) {
td.tx(" and ");
} else if (i > 0) {
td.tx(", ");
}
shortForRef(td, subj);
}
}
}
if (list.hasEncounter()) {
shortForRef(tr.td().txN(/*!#*/"Encounter: "), list.getEncounter());
}
if (list.hasSource()) {
shortForRef(tr.td().txN(/*!#*/"Source: "), list.getEncounter());
}
if (list.hasOrderedBy()) {
tr.td().tx(/*!#*/"Order: "+display(list.getOrderedBy()));
}
for (Annotation a : list.getNote()) {
renderAnnotation(x, a);
}
boolean flag = false;
boolean deleted = false;
boolean date = false;
for (ListResourceEntryComponent e : list.getEntry()) {
flag = flag || e.hasFlag();
deleted = deleted || e.hasDeleted();
date = date || e.hasDate();
}
t = x.table("grid");
tr = t.tr().style("backgound-color: #eeeeee");
tr.td().b().tx(/*!#*/"Items");
if (date) {
tr.td().tx(/*!#*/"Date");
}
if (flag) {
tr.td().tx(/*!#*/"Flag");
}
if (deleted) {
tr.td().tx(/*!#*/"Deleted");
}
for (ListResourceEntryComponent e : list.getEntry()) {
tr = t.tr();
shortForRef(tr.td(), e.getItem());
if (date) {
tr.td().tx(e.hasDate() ? e.getDate().toLocaleString() : "");
}
if (flag) {
tr.td().tx(e.hasFlag() ? display(e.getFlag()) : "");
}
if (deleted) {
tr.td().tx(e.hasDeleted() ? Boolean.toString(e.getDeleted()) : "");
}
}
return false;
}
public void describe(XhtmlNode x, ListResource list) {
x.tx(display(list));
}
public String display(ListResource list) {
return list.getTitle();
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return ((ListResource) r).getTitle();
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
if (r.has("title")) {
return r.children("title").get(0).getBase().primitiveValue();
}
return "??";
}
private void shortForRef(XhtmlNode x, Reference ref) throws UnsupportedEncodingException, IOException {
ResourceWithReference r = context.getResolver() == null ? null : context.getResolver().resolve(context, ref.getReference());
if (r == null) {
x.tx(display(ref));
} else {
RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, ref);
}
}
private XhtmlNode shortForRef(XhtmlNode x, Base ref) throws UnsupportedEncodingException, IOException {
if (ref == null) {
x.tx("(null)");
} else {
String disp = ref.getChildByName("display") != null && ref.getChildByName("display").hasValues() ? ref.getChildByName("display").getValues().get(0).primitiveValue() : null;
if (ref.getChildByName("reference").hasValues()) {
String url = ref.getChildByName("reference").getValues().get(0).primitiveValue();
if (url.startsWith("#")) {
x.tx("?ngen-16a?");
} else {
ResourceWithReference r = context.getResolver().resolve(context, url);
if (r == null) {
if (disp == null) {
disp = url;
}
x.tx(disp);
} else if (r.getResource() != null) {
RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, (Reference) ref);
} else {
x.ah(r.getReference()).tx(url);
}
}
} else if (disp != null) {
x.tx(disp);
} else {
x.tx("?ngen-16?");
}
}
return x;
}
}
XhtmlNode t = x.table("clstu");
XhtmlNode tr = t.tr();
XhtmlNode td = tr.td();
if (list.has("date")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_DATE, displayDateTime(list.get("date").dateTimeValue()))+" ");
}
if (list.has("mode")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_MODE, list.get("mode").primitiveValue())+" ");
}
if (list.has("status")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_STAT, list.get("status").primitiveValue())+" ");
}
if (list.has("code")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_CODE, displayBase(list.get("code")))+" ");
}
tr = t.tr();
td = tr.td();
if (list.has("subject")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_SUB)+" ");
shortForRef(td, list.get("subject"));
}
if (list.has("encounter")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_ENC)+" ");
shortForRef(td, list.get("encounter"));
}
if (list.has("source")) {
td.tx(context.formatPhrase(RenderingContext.GENERAL_SRC)+" ");
shortForRef(td, list.get("encounter"));
}
if (list.has("orderedBy")) {
td.tx(context.formatPhrase(RenderingContext.LIST_REND_ORD, displayBase(list.get("orderedBy")))+" ");
}
// for (Annotation a : list.getNote()) {
// renderAnnotation(a, x);
// }
boolean flag = false;
boolean deleted = false;
boolean date = false;
for (BaseWrapper e : list.children("entry")) {
flag = flag || e.has("flag");
deleted = deleted || e.has("deleted");
date = date || e.has("date");
}
t = x.table("grid");
tr = t.tr().style("backgound-color: #eeeeee");
tr.td().b().tx(context.formatPhrase(RenderingContext.LIST_REND_ITEM));
if (date) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DAT));
}
if (flag) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_FLAG));
}
if (deleted) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DEL));
}
for (BaseWrapper e : list.children("entry")) {
tr = t.tr();
shortForRef(tr.td(), e.get("item"));
if (date) {
tr.td().tx(e.has("date") ? e.get("date").dateTimeValue().toHumanDisplay() : "");
}
if (flag) {
tr.td().tx(e.has("flag") ? displayBase(e.get("flag")) : "");
}
if (deleted) {
tr.td().tx(e.has("deleted") ? e.get("deleted").primitiveValue() : "");
}
}
return false;
}
public boolean render(XhtmlNode x, ListResource list) throws FHIRFormatError, DefinitionException, IOException {
if (list.hasTitle()) {
x.h2().tx(list.getTitle());
}
XhtmlNode t = x.table("clstu");
XhtmlNode tr = t.tr();
if (list.hasDate()) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DATE, displayDateTime(list.getDateElement()))+" ");
}
if (list.hasMode()) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_MODE, list.getMode().getDisplay())+" ");
}
if (list.hasStatus()) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_STAT, list.getStatus().getDisplay())+" ");
}
if (list.hasCode()) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_CODE, display(list.getCode()))+" ");
}
tr = t.tr();
if (list.hasSubject()) {
if (list.getSubject().size() == 1) {
shortForRef(tr.td().txN("Subject: "), list.getSubjectFirstRep());
} else {
XhtmlNode td = tr.td();
td.txN(context.formatPhrase(RenderingContext.LIST_REND_SUB)+" ");
int i = 0;
for (Reference subj : list.getSubject()) {
if (i == list.getSubject().size() - 1) {
td.tx(" and ");
} else if (i > 0) {
td.tx(", ");
}
shortForRef(td, subj);
}
}
}
if (list.hasEncounter()) {
shortForRef(tr.td().txN(context.formatPhrase(RenderingContext.LIST_REND_ENC)+" "), list.getEncounter());
}
if (list.hasSource()) {
shortForRef(tr.td().txN(context.formatPhrase(RenderingContext.GENERAL_SRC)+" "), list.getEncounter());
}
if (list.hasOrderedBy()) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_ORD, display(list.getOrderedBy()))+" ");
}
for (Annotation a : list.getNote()) {
renderAnnotation(x, a);
}
boolean flag = false;
boolean deleted = false;
boolean date = false;
for (ListResourceEntryComponent e : list.getEntry()) {
flag = flag || e.hasFlag();
deleted = deleted || e.hasDeleted();
date = date || e.hasDate();
}
t = x.table("grid");
tr = t.tr().style("backgound-color: #eeeeee");
tr.td().b().tx(context.formatPhrase(RenderingContext.LIST_REND_ITEM));
if (date) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DAT));
}
if (flag) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_FLAG));
}
if (deleted) {
tr.td().tx(context.formatPhrase(RenderingContext.LIST_REND_DEL));
}
for (ListResourceEntryComponent e : list.getEntry()) {
tr = t.tr();
shortForRef(tr.td(), e.getItem());
if (date) {
tr.td().tx(e.hasDate() ? e.getDate().toLocaleString() : "");
}
if (flag) {
tr.td().tx(e.hasFlag() ? display(e.getFlag()) : "");
}
if (deleted) {
tr.td().tx(e.hasDeleted() ? Boolean.toString(e.getDeleted()) : "");
}
}
return false;
}
public void describe(XhtmlNode x, ListResource list) {
x.tx(display(list));
}
public String display(ListResource list) {
return list.getTitle();
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return ((ListResource) r).getTitle();
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
if (r.has("title")) {
return r.children("title").get(0).getBase().primitiveValue();
}
return "??";
}
private void shortForRef(XhtmlNode x, Reference ref) throws UnsupportedEncodingException, IOException {
ResourceWithReference r = context.getResolver() == null ? null : context.getResolver().resolve(context, ref.getReference());
if (r == null) {
x.tx(display(ref));
} else {
RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, ref);
}
}
private XhtmlNode shortForRef(XhtmlNode x, Base ref) throws UnsupportedEncodingException, IOException {
if (ref == null) {
x.tx("(null)");
} else {
String disp = ref.getChildByName("display") != null && ref.getChildByName("display").hasValues() ? ref.getChildByName("display").getValues().get(0).primitiveValue() : null;
if (ref.getChildByName("reference").hasValues()) {
String url = ref.getChildByName("reference").getValues().get(0).primitiveValue();
if (url.startsWith("#")) {
x.tx("?ngen-16a?");
} else {
ResourceWithReference r = context.getResolver().resolve(context, url);
if (r == null) {
if (disp == null) {
disp = url;
}
x.tx(disp);
} else if (r.getResource() != null) {
RendererFactory.factory(r.getResource().getName(), context).renderReference(r.getResource(), x, (Reference) ref);
} else {
x.ah(r.getReference()).tx(url);
}
}
} else if (disp != null) {
x.tx(disp);
} else {
x.tx("?ngen-16?");
}
}
return x;
}
}

View File

@ -30,33 +30,33 @@ public class NamingSystemRenderer extends ResourceRenderer {
}
public boolean render(XhtmlNode x, NamingSystem ns) throws FHIRFormatError, DefinitionException, IOException {
x.h3().tx(/*!#*/"Summary");
x.h3().tx(context.formatPhrase(RenderingContext.GENERAL_SUMM));
XhtmlNode tbl = x.table("grid");
row(tbl, /*!#*/"Defining URL", ns.getUrl());
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_DEFINING_URL)), ns.getUrl());
if (ns.hasVersion()) {
row(tbl, /*!#*/"Version", ns.getVersion());
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_VER)), ns.getVersion());
}
if (ns.hasName()) {
row(tbl, /*!#*/"Name", gt(ns.getNameElement()));
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_NAME)), gt(ns.getNameElement()));
}
if (ns.hasTitle()) {
row(tbl, /*!#*/"Title", gt(ns.getTitleElement()));
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_TITLE)), gt(ns.getTitleElement()));
}
row(tbl, /*!#*/"Status", ns.getStatus().toCode());
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_STATUS)), ns.getStatus().toCode());
if (ns.hasDescription()) {
addMarkdown(row(tbl, /*!#*/"Definition"), ns.getDescription());
addMarkdown(row(tbl, (context.formatPhrase(RenderingContext.GENERAL_DEFINITION))), ns.getDescription());
}
if (ns.hasPublisher()) {
row(tbl, /*!#*/"Publisher", gt(ns.getPublisherElement()));
row(tbl, (context.formatPhrase(RenderingContext.CANON_REND_PUBLISHER)), gt(ns.getPublisherElement()));
}
if (ns.hasExtension(ToolingExtensions.EXT_WORKGROUP)) {
renderCommitteeLink(row(tbl, "Committee"), ns);
}
if (CodeSystemUtilities.hasOID(ns)) {
row(tbl, /*!#*/"OID", CodeSystemUtilities.getOID(ns)).tx("("+(/*!#*/"for OID based terminology systems")+")");
row(tbl, (context.formatPhrase(RenderingContext.GENERAL_OID)), CodeSystemUtilities.getOID(ns)).tx("("+(context.formatPhrase(RenderingContext.CODE_SYS_FOR_OID))+")");
}
if (ns.hasCopyright()) {
addMarkdown(row(tbl, /*!#*/"Copyright"), ns.getCopyright());
addMarkdown(row(tbl, (context.formatPhrase(RenderingContext.GENERAL_COPYRIGHT))), ns.getCopyright());
}
boolean hasPreferred = false;
boolean hasPeriod = false;
@ -66,19 +66,19 @@ public class NamingSystemRenderer extends ResourceRenderer {
hasPeriod = hasPeriod || id.hasPeriod();
hasComment = hasComment || id.hasComment();
}
x.h3().tx(/*!#*/"Identifiers");
x.h3().tx(context.formatPhrase(RenderingContext.NAME_SYS_IDEN));
tbl = x.table("grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx((/*!#*/"Type"));
tr.td().b().tx((/*!#*/"Value"));
tr.td().b().tx((context.formatPhrase(RenderingContext.GENERAL_TYPE)));
tr.td().b().tx((context.formatPhrase(RenderingContext.GENERAL_VALUE)));
if (hasPreferred) {
tr.td().b().tx((/*!#*/"Preferred"));
tr.td().b().tx((context.formatPhrase(RenderingContext.GENERAL_PREFERRED)));
}
if (hasPeriod) {
tr.td().b().tx((/*!#*/"Period"));
tr.td().b().tx((context.formatPhrase(RenderingContext.NAME_SYS_PER)));
}
if (hasComment) {
tr.td().b().tx((/*!#*/"Comment"));
tr.td().b().tx((context.formatPhrase(RenderingContext.GENERAL_COMMENT)));
}
for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) {
tr = tbl.tr();

View File

@ -353,21 +353,21 @@ public class ObligationsRenderer {
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
children.add(tr);
tr.td().style("font-size: 11px").b().tx(/*!#*/"Obligations");
tr.td().style("font-size: 11px").b().tx(context.formatPhrase(RenderingContext.GENERAL_OBLIG));
if (actor) {
tr.td().style("font-size: 11px").tx(/*!#*/"Actor");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.OBLIG_ACT));
}
if (elementId) {
tr.td().style("font-size: 11px").tx(/*!#*/"Elements");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.OBLIG_ELE));
}
if (usage) {
tr.td().style("font-size: 11px").tx(/*!#*/"Usage");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_USAGE));
}
if (doco) {
tr.td().style("font-size: 11px").tx(/*!#*/"Documentation");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
}
if (filter) {
tr.td().style("font-size: 11px").tx(/*!#*/"Filter");
tr.td().style("font-size: 11px").tx(context.formatPhrase(RenderingContext.GENERAL_FILTER));
}
for (ObligationDetail ob : obligations) {
tr = new XhtmlNode(NodeType.Element, "tr");

View File

@ -1,189 +1,189 @@
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.Enumerations.FHIRTypes;
import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.OperationDefinition;
import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
import org.hl7.fhir.r5.model.OperationDefinition.OperationParameterScope;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class OperationDefinitionRenderer extends TerminologyRenderer {
public OperationDefinitionRenderer(RenderingContext context) {
super(context);
}
public OperationDefinitionRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
return render(x, (OperationDefinition) dr);
}
public boolean render(XhtmlNode x, OperationDefinition opd) throws IOException, FHIRException, EOperationOutcome {
if (context.isHeader()) {
x.h2().addText(opd.getName());
x.para().addText(Utilities.capitalize(opd.getKind().toString())+": "+opd.getName());
x.para().tx(/*!#*/"The official URL for this operation definition is: ");
x.pre().tx(opd.getUrl());
addMarkdown(x, opd.getDescription());}
if (opd.getSystem())
x.para().tx(/*!#*/"URL: [base]/$"+opd.getCode());
for (Enumeration<VersionIndependentResourceTypesAll> c : opd.getResource()) {
if (opd.getType())
x.para().tx(/*!#*/"URL: [base]/"+c.getCode()+"/$"+opd.getCode());
if (opd.getInstance())
x.para().tx(/*!#*/"URL: [base]/"+c.getCode()+"/[id]/$"+opd.getCode());
}
if (opd.hasInputProfile()) {
XhtmlNode p = x.para();
p.tx(/*!#*/"Input parameters Profile: ");
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile(), opd);
if (sd == null) {
p.pre().tx(opd.getInputProfile());
} else {
p.ah(sd.getWebPath()).tx(sd.present());
}
}
if (opd.hasOutputProfile()) {
XhtmlNode p = x.para();
p.tx(/*!#*/"Output parameters Profile: ");
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile(), opd);
if (sd == null) {
p.pre().tx(opd.getOutputProfile());
} else {
p.ah(sd.getWebPath()).tx(sd.present());
}
}
x.para().tx(/*!#*/"Parameters");
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(/*!#*/"Use");
tr.td().b().tx(/*!#*/"Name");
tr.td().b().tx(/*!#*/"Scope");
tr.td().b().tx(/*!#*/"Cardinality");
tr.td().b().tx(/*!#*/"Type");
tr.td().b().tx(/*!#*/"Binding");
tr.td().b().tx(/*!#*/"Documentation");
for (OperationDefinitionParameterComponent p : opd.getParameter()) {
genOpParam(tbl, "", p, opd);
}
addMarkdown(x, opd.getComment());
return true;
}
public void describe(XhtmlNode x, OperationDefinition opd) {
x.tx(display(opd));
}
public String display(OperationDefinition opd) {
return opd.present();
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return ((OperationDefinition) r).present();
}
private void genOpParam(XhtmlNode tbl, String path, OperationDefinitionParameterComponent p, Resource opd) throws EOperationOutcome, FHIRException, IOException {
XhtmlNode tr;
tr = tbl.tr();
tr.td().addText(p.getUse().toString());
XhtmlNode td = tr.td();
td.addText(path+p.getName());
StandardsStatus ss = ToolingExtensions.getStandardsStatus(p);
genStandardsStatus(td, ss);
td = tr.td();
if (p.hasScope()) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (Enumeration<OperationParameterScope> s : p.getScope()) {
b.append(s.getCode());
}
td.tx(b.toString());
}
tr.td().addText(Integer.toString(p.getMin())+".."+p.getMax());
td = tr.td();
String actualType = translateTypeToVersion(p.getTypeElement());
StructureDefinition sd = actualType != null ? context.getWorker().fetchTypeDefinition(actualType) : null;
if (sd == null)
td.tx(p.hasType() ? actualType : "");
else if (sd.getAbstract() && p.hasExtension(ToolingExtensions.EXT_ALLOWED_TYPE)) {
boolean first = true;
for (Extension ex : p.getExtensionsByUrl(ToolingExtensions.EXT_ALLOWED_TYPE)) {
if (first) first = false; else td.tx(" | ");
String s = ex.getValue().primitiveValue();
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(s);
if (sdt == null)
td.tx(p.hasType() ? actualType : "");
else
td.ah(sdt.getWebPath()).tx(s);
}
} else
td.ah(sd.getWebPath()).tx(actualType);
if (p.hasTargetProfile()) {
td.tx(" (");
boolean first = true;
for (CanonicalType tp : p.getTargetProfile()) {
if (first) { first = false;} else {td.tx(", ");};
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(tp.asStringValue());
if (sdt == null || !sdt.hasWebPath()) {
td.code().tx(tp.asStringValue());
} else {
td.ah(sdt.getWebPath(), tp.asStringValue()).tx(sdt.present());
}
}
td.tx(")");
}
if (p.hasSearchType()) {
td.br();
td.tx("(");
td.ah( context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode());
td.tx(")");
}
td = tr.td();
if (p.hasBinding() && p.getBinding().hasValueSet()) {
AddVsRef(p.getBinding().getValueSet(), td, opd);
td.tx(" ("+p.getBinding().getStrength().getDisplay()+")");
}
addMarkdown(tr.td(), p.getDocumentation());
if (!p.hasType()) {
for (OperationDefinitionParameterComponent pp : p.getPart()) {
genOpParam(tbl, path+p.getName()+".", pp, opd);
}
}
}
public static final String EXT_OPDEF_ORIGINAL_TYPE = "http://hl7.org/fhir/4.0/StructureDefinition/extension-OperationDefinition.parameter.type";
private String translateTypeToVersion(Enumeration<FHIRTypes> src) {
if (src.hasExtension(EXT_OPDEF_ORIGINAL_TYPE)) {
return src.getExtensionString(EXT_OPDEF_ORIGINAL_TYPE);
} else {
return src.asStringValue();
}
}
}
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeType;
import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.Enumerations.FHIRTypes;
import org.hl7.fhir.r5.model.Enumerations.VersionIndependentResourceTypesAll;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.OperationDefinition;
import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
import org.hl7.fhir.r5.model.OperationDefinition.OperationParameterScope;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.utils.EOperationOutcome;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.StandardsStatus;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class OperationDefinitionRenderer extends TerminologyRenderer {
public OperationDefinitionRenderer(RenderingContext context) {
super(context);
}
public OperationDefinitionRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws IOException, FHIRException, EOperationOutcome {
return render(x, (OperationDefinition) dr);
}
public boolean render(XhtmlNode x, OperationDefinition opd) throws IOException, FHIRException, EOperationOutcome {
if (context.isHeader()) {
x.h2().addText(opd.getName());
x.para().addText(Utilities.capitalize(opd.getKind().toString())+": "+opd.getName());
x.para().tx(context.formatPhrase(RenderingContext.OP_DEF_OFFIC)+" ");
x.pre().tx(opd.getUrl());
addMarkdown(x, opd.getDescription());}
if (opd.getSystem())
x.para().tx(context.formatPhrase(RenderingContext.OP_DEF_URLS, opd.getCode()));
for (Enumeration<VersionIndependentResourceTypesAll> c : opd.getResource()) {
if (opd.getType())
x.para().tx(context.formatPhrase(RenderingContext.OP_DEF_URL, c.getCode()+"/$"+opd.getCode()));
if (opd.getInstance())
x.para().tx(context.formatPhrase(RenderingContext.OP_DEF_URL, c.getCode()+"/[id]/$"+opd.getCode()));
}
if (opd.hasInputProfile()) {
XhtmlNode p = x.para();
p.tx(context.formatPhrase(RenderingContext.OP_DEF_INPAR));
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile(), opd);
if (sd == null) {
p.pre().tx(opd.getInputProfile());
} else {
p.ah(sd.getWebPath()).tx(sd.present());
}
}
if (opd.hasOutputProfile()) {
XhtmlNode p = x.para();
p.tx(context.formatPhrase(RenderingContext.OP_DEF_OUTPAR));
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile(), opd);
if (sd == null) {
p.pre().tx(opd.getOutputProfile());
} else {
p.ah(sd.getWebPath()).tx(sd.present());
}
}
x.para().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode tbl = x.table( "grid");
XhtmlNode tr = tbl.tr();
tr.td().b().tx(context.formatPhrase(RenderingContext.OP_DEF_USE));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_NAME));
tr.td().b().tx(context.formatPhrase(RenderingContext.OP_DEF_SCO));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CARDINALITY));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_BINDING));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_DOCUMENTATION));
for (OperationDefinitionParameterComponent p : opd.getParameter()) {
genOpParam(tbl, "", p, opd);
}
addMarkdown(x, opd.getComment());
return true;
}
public void describe(XhtmlNode x, OperationDefinition opd) {
x.tx(display(opd));
}
public String display(OperationDefinition opd) {
return opd.present();
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return ((OperationDefinition) r).present();
}
private void genOpParam(XhtmlNode tbl, String path, OperationDefinitionParameterComponent p, Resource opd) throws EOperationOutcome, FHIRException, IOException {
XhtmlNode tr;
tr = tbl.tr();
tr.td().addText(p.getUse().toString());
XhtmlNode td = tr.td();
td.addText(path+p.getName());
StandardsStatus ss = ToolingExtensions.getStandardsStatus(p);
genStandardsStatus(td, ss);
td = tr.td();
if (p.hasScope()) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (Enumeration<OperationParameterScope> s : p.getScope()) {
b.append(s.getCode());
}
td.tx(b.toString());
}
tr.td().addText(Integer.toString(p.getMin())+".."+p.getMax());
td = tr.td();
String actualType = translateTypeToVersion(p.getTypeElement());
StructureDefinition sd = actualType != null ? context.getWorker().fetchTypeDefinition(actualType) : null;
if (sd == null)
td.tx(p.hasType() ? actualType : "");
else if (sd.getAbstract() && p.hasExtension(ToolingExtensions.EXT_ALLOWED_TYPE)) {
boolean first = true;
for (Extension ex : p.getExtensionsByUrl(ToolingExtensions.EXT_ALLOWED_TYPE)) {
if (first) first = false; else td.tx(" | ");
String s = ex.getValue().primitiveValue();
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(s);
if (sdt == null)
td.tx(p.hasType() ? actualType : "");
else
td.ah(sdt.getWebPath()).tx(s);
}
} else
td.ah(sd.getWebPath()).tx(actualType);
if (p.hasTargetProfile()) {
td.tx(" (");
boolean first = true;
for (CanonicalType tp : p.getTargetProfile()) {
if (first) { first = false;} else {td.tx(", ");};
StructureDefinition sdt = context.getWorker().fetchTypeDefinition(tp.asStringValue());
if (sdt == null || !sdt.hasWebPath()) {
td.code().tx(tp.asStringValue());
} else {
td.ah(sdt.getWebPath(), tp.asStringValue()).tx(sdt.present());
}
}
td.tx(")");
}
if (p.hasSearchType()) {
td.br();
td.tx("(");
td.ah( context.getLink(KnownLinkType.SPEC) == null ? "search.html#"+p.getSearchType().toCode() : Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "search.html#"+p.getSearchType().toCode())).tx(p.getSearchType().toCode());
td.tx(")");
}
td = tr.td();
if (p.hasBinding() && p.getBinding().hasValueSet()) {
AddVsRef(p.getBinding().getValueSet(), td, opd);
td.tx(" ("+p.getBinding().getStrength().getDisplay()+")");
}
addMarkdown(tr.td(), p.getDocumentation());
if (!p.hasType()) {
for (OperationDefinitionParameterComponent pp : p.getPart()) {
genOpParam(tbl, path+p.getName()+".", pp, opd);
}
}
}
public static final String EXT_OPDEF_ORIGINAL_TYPE = "http://hl7.org/fhir/4.0/StructureDefinition/extension-OperationDefinition.parameter.type";
private String translateTypeToVersion(Enumeration<FHIRTypes> src) {
if (src.hasExtension(EXT_OPDEF_ORIGINAL_TYPE)) {
return src.getExtensionString(EXT_OPDEF_ORIGINAL_TYPE);
} else {
return src.asStringValue();
}
}
}

View File

@ -1,105 +1,105 @@
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.ExtensionHelper;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class OperationOutcomeRenderer extends ResourceRenderer {
public OperationOutcomeRenderer(RenderingContext context) {
super(context);
}
public OperationOutcomeRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (OperationOutcome) dr);
}
public boolean render(XhtmlNode x, OperationOutcome op) throws FHIRFormatError, DefinitionException, IOException {
boolean hasSource = false;
boolean success = true;
for (OperationOutcomeIssueComponent i : op.getIssue()) {
success = success && i.getSeverity() == IssueSeverity.INFORMATION;
hasSource = hasSource || ExtensionHelper.hasExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE);
}
if (success)
x.para().tx(/*!#*/"All OK");
if (op.getIssue().size() > 0) {
XhtmlNode tbl = x.table("grid"); // on the basis that we'll most likely be rendered using the standard fhir css, but it doesn't really matter
XhtmlNode tr = tbl.tr();
tr.td().b().tx(/*!#*/"Severity");
tr.td().b().tx(/*!#*/"Location");
tr.td().b().tx(/*!#*/"Code");
tr.td().b().tx(/*!#*/"Details");
tr.td().b().tx(/*!#*/"Diagnostics");
if (hasSource)
tr.td().b().tx(/*!#*/"Source");
for (OperationOutcomeIssueComponent i : op.getIssue()) {
tr = tbl.tr();
tr.td().addText(i.getSeverity().toString());
XhtmlNode td = tr.td();
boolean d = false;
for (StringType s : i.hasExpression() ? i.getExpression() : i.getLocation()) {
if (d)
td.tx(", ");
else
d = true;
td.addText(s.getValue());
}
tr.td().addText(i.getCode().getDisplay());
tr.td().addText(display(i.getDetails()));
smartAddText(tr.td(), i.getDiagnostics());
if (hasSource) {
Extension ext = ExtensionHelper.getExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE);
tr.td().addText(ext == null ? "" : display(ext));
}
}
}
return true;
}
public void describe(XhtmlNode x, OperationOutcome oo) {
x.tx(display(oo));
}
public String display(OperationOutcome oo) {
return /*!#*/"todo";
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return /*!#*/"Not done yet";
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return display((OperationOutcome) r);
}
public static String toString(OperationOutcome oo) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (OperationOutcomeIssueComponent issue : oo.getIssue()) {
b.append(issue.getSeverity().toCode()+": "+issue.getDetails().getText());
}
return b.toString();
}
}
package org.hl7.fhir.r5.renderers;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.ExtensionHelper;
import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.utilities.CommaSeparatedStringBuilder;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class OperationOutcomeRenderer extends ResourceRenderer {
public OperationOutcomeRenderer(RenderingContext context) {
super(context);
}
public OperationOutcomeRenderer(RenderingContext context, ResourceContext rcontext) {
super(context, rcontext);
}
public boolean render(XhtmlNode x, Resource dr) throws FHIRFormatError, DefinitionException, IOException {
return render(x, (OperationOutcome) dr);
}
public boolean render(XhtmlNode x, OperationOutcome op) throws FHIRFormatError, DefinitionException, IOException {
boolean hasSource = false;
boolean success = true;
for (OperationOutcomeIssueComponent i : op.getIssue()) {
success = success && i.getSeverity() == IssueSeverity.INFORMATION;
hasSource = hasSource || ExtensionHelper.hasExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE);
}
if (success)
x.para().tx(context.formatPhrase(RenderingContext.OP_OUT_OK));
if (op.getIssue().size() > 0) {
XhtmlNode tbl = x.table("grid"); // on the basis that we'll most likely be rendered using the standard fhir css, but it doesn't really matter
XhtmlNode tr = tbl.tr();
tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SEV));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_LOCATION));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_CODE));
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_DETAILS));
tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_DIAG));
if (hasSource)
tr.td().b().tx(context.formatPhrase(RenderingContext.OP_OUT_SRC));
for (OperationOutcomeIssueComponent i : op.getIssue()) {
tr = tbl.tr();
tr.td().addText(i.getSeverity().toString());
XhtmlNode td = tr.td();
boolean d = false;
for (StringType s : i.hasExpression() ? i.getExpression() : i.getLocation()) {
if (d)
td.tx(", ");
else
d = true;
td.addText(s.getValue());
}
tr.td().addText(i.getCode().getDisplay());
tr.td().addText(display(i.getDetails()));
smartAddText(tr.td(), i.getDiagnostics());
if (hasSource) {
Extension ext = ExtensionHelper.getExtension(i, ToolingExtensions.EXT_ISSUE_SOURCE);
tr.td().addText(ext == null ? "" : display(ext));
}
}
}
return true;
}
public void describe(XhtmlNode x, OperationOutcome oo) {
x.tx(display(oo));
}
public String display(OperationOutcome oo) {
return (context.formatPhrase(RenderingContext.GENERAL_TODO));
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return (context.formatPhrase(RenderingContext.GENERAL_TODO));
}
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return display((OperationOutcome) r);
}
public static String toString(OperationOutcome oo) {
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
for (OperationOutcomeIssueComponent issue : oo.getIssue()) {
b.append(issue.getSeverity().toCode()+": "+issue.getDetails().getText());
}
return b.toString();
}
}

View File

@ -37,7 +37,7 @@ public class ParametersRenderer extends ResourceRenderer {
@Override
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
x.h2().tx(/*!#*/"Parameters");
x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode tbl = x.table("grid");
params(tbl, ((Parameters) r).getParameter(), 0);
return false;
@ -55,7 +55,7 @@ public class ParametersRenderer extends ResourceRenderer {
@Override
public boolean render(XhtmlNode x, ResourceWrapper params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
x.h2().tx(/*!#*/"Parameters");
x.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode tbl = x.table("grid");
PropertyWrapper pw = getProperty(params, "parameter");
if (valued(pw)) {
@ -84,6 +84,7 @@ public class ParametersRenderer extends ResourceRenderer {
XhtmlNode para = td.para();
para.tx(rw.fhirType()+"/"+rw.getId());
para.an(rw.fhirType()+"_"+rw.getId()).tx(" ");
para.an("hc"+rw.fhirType()+"_"+rw.getId()).tx(" ");
XhtmlNode x = rw.getNarrative();
if (x != null) {
td.addChildren(x);
@ -101,7 +102,7 @@ public class ParametersRenderer extends ResourceRenderer {
public XhtmlNode render(Parameters params) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
XhtmlNode div = new XhtmlNode(NodeType.Element, "div");
div.h2().tx(/*!#*/"Parameters");
div.h2().tx(context.formatPhrase(RenderingContext.GENERAL_PARS));
XhtmlNode tbl = div.table("grid");
params(tbl, params.getParameter(), 0);
return div;
@ -123,6 +124,7 @@ public class ParametersRenderer extends ResourceRenderer {
XhtmlNode para = td.para();
para.tx(r.fhirType()+"/"+r.getId());
para.an(r.fhirType()+"_"+r.getId()).tx(" ");
para.an("hc"+r.fhirType()+"_"+r.getId()).tx(" ");
ResourceRenderer rr = RendererFactory.factory(r, context);
rr.render(td, r);
} else if (p.hasPart()) {

View File

@ -228,19 +228,19 @@ public class PatientRenderer extends ResourceRenderer {
if (name == null) {
b.append(display(name));
} else {
b.append(context.formatMessage(RenderingContext.PAT_NO_NAME));
b.append(context.formatPhrase(RenderingContext.PAT_NO_NAME));
}
b.append(" ");
if (dob == null) {
b.append(context.formatMessage(RenderingContext.PAT_NO_GENDER));
b.append(context.formatPhrase(RenderingContext.PAT_NO_GENDER));
} else {
b.append(gender);
}
b.append(", ");
if (dob == null) {
b.append(context.formatMessage(RenderingContext.PAT_NO_DOB));
b.append(context.formatPhrase(RenderingContext.PAT_NO_DOB));
} else {
b.append(context.formatMessage(RenderingContext.PAT_DOB, display(dob)));
b.append(context.formatPhrase(RenderingContext.PAT_DOB, display(dob)));
}
if (id != null) {
b.append(" ( ");
@ -252,21 +252,21 @@ public class PatientRenderer extends ResourceRenderer {
public void describe(XhtmlNode x, HumanName name, String gender, DateType dob, Identifier id) throws UnsupportedEncodingException, IOException {
if (name == null) {
x.b().tx(context.formatMessage(RenderingContext.PAT_NO_NAME)); // todo: is this appropriate?
x.b().tx(context.formatPhrase(RenderingContext.PAT_NO_NAME)); // todo: is this appropriate?
} else {
render(x.b(), name);
}
x.tx(" ");
if (gender == null) {
x.tx(context.formatMessage(RenderingContext.PAT_NO_GENDER));
x.tx(context.formatPhrase(RenderingContext.PAT_NO_GENDER));
} else {
x.tx(gender);
}
x.tx(", ");
if (dob == null) {
x.tx(context.formatMessage(RenderingContext.PAT_NO_DOB));
x.tx(context.formatPhrase(RenderingContext.PAT_NO_DOB));
} else {
x.tx(context.formatMessage(RenderingContext.PAT_DOB, display(dob)));
x.tx(context.formatPhrase(RenderingContext.PAT_DOB, display(dob)));
}
if (id != null) {
x.tx(" ( ");
@ -338,7 +338,7 @@ public class PatientRenderer extends ResourceRenderer {
}
if (!anyComplex) {
XhtmlNode tr = tbl.tr();
nameCell(tr, sd.getTitle()+":", sd.getDescription(), sd.getWebPath());
nameCell(tr, getContext().getTranslated(sd.getTitleElement()), sd.getDescription(), sd.getWebPath());
XhtmlNode td = tr.td();
td.colspan("3");
if (list.size() == 1) {
@ -435,7 +435,7 @@ public class PatientRenderer extends ResourceRenderer {
if (langs.size() == 1) {
render(r, td, langs.get(0));
if (prefLang != null) {
td.tx(" "+context.formatMessage(RenderingContext.PAT_LANG_PREFERRED));
td.tx(" "+context.formatPhrase(RenderingContext.PAT_LANG_PREFERRED));
}
} else if (langs.size() > 1) {
XhtmlNode ul = td.ul();
@ -443,7 +443,7 @@ public class PatientRenderer extends ResourceRenderer {
XhtmlNode li = ul.li();
render(r, li, i);
if (i == prefLang) {
li.tx(" "+context.formatMessage(RenderingContext.PAT_LANG_PREFERRED));;
li.tx(" "+context.formatPhrase(RenderingContext.PAT_LANG_PREFERRED));;
}
}
}
@ -455,13 +455,13 @@ public class PatientRenderer extends ResourceRenderer {
PropertyWrapper pw = getProperty(r, "generalPractitioner");
if (pw != null) {
for (BaseWrapper t : pw.getValues()) {
refs.add(new NamedReferance(context.formatMessage(RenderingContext.PAT_GP), (Reference) t.getBase(), t));
refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_GP), (Reference) t.getBase(), t));
}
}
pw = getProperty(r, "managingOrganization");
if (pw != null) {
for (BaseWrapper t : pw.getValues()) {
refs.add(new NamedReferance(context.formatMessage(RenderingContext.PAT_MO), (Reference) t.getBase(), t));
refs.add(new NamedReferance(context.formatPhrase(RenderingContext.PAT_MO), (Reference) t.getBase(), t));
}
}
pw = getProperty(r, "link");
@ -485,7 +485,7 @@ public class PatientRenderer extends ResourceRenderer {
if (refs.size() > 0) {
XhtmlNode tr = tbl.tr();
nameCell(tr, context.formatMessage(RenderingContext.PAT_LINKS), context.formatMessage(RenderingContext.PAT_LINKS_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_LINKS), context.formatPhrase(RenderingContext.PAT_LINKS_HINT));
XhtmlNode td = tr.td();
td.colspan("3");
XhtmlNode ul = td.ul();
@ -500,10 +500,10 @@ public class PatientRenderer extends ResourceRenderer {
private String describeLinkedRecord(String type) {
switch (type) {
case "replaced-by" : return context.formatMessage(RenderingContext.PAT_LINK_REPLBY);
case "replaces": return context.formatMessage(RenderingContext.PAT_LINK_REPL);
case "refer": return context.formatMessage(RenderingContext.PAT_LINK_REFER);
case "seealso": return context.formatMessage(RenderingContext.PAT_LINK_SEE);
case "replaced-by" : return context.formatPhrase(RenderingContext.PAT_LINK_REPLBY);
case "replaces": return context.formatPhrase(RenderingContext.PAT_LINK_REPL);
case "refer": return context.formatPhrase(RenderingContext.PAT_LINK_REFER);
case "seealso": return context.formatPhrase(RenderingContext.PAT_LINK_SEE);
}
return "Unknown";
}
@ -565,9 +565,9 @@ public class PatientRenderer extends ResourceRenderer {
}
XhtmlNode tr = tbl.tr();
if (rels.size() == 1) {
nameCell(tr, (rels.get(0).getCodingFirstRep().hasDisplay() ? rels.get(0).getCodingFirstRep().getDisplay() : display(rels.get(0)))+":", context.formatMessage(RenderingContext.PAT_NOM_CONTACT)+" "+display(rels.get(0)));
nameCell(tr, (rels.get(0).getCodingFirstRep().hasDisplay() ? rels.get(0).getCodingFirstRep().getDisplay() : display(rels.get(0)))+":", context.formatPhrase(RenderingContext.PAT_NOM_CONTACT)+" "+display(rels.get(0)));
} else {
nameCell(tr, context.formatMessage(RenderingContext.PAT_NOK_CONTACT), context.formatMessage(RenderingContext.PAT_NOK_CONTACT_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.GENERAL_CONTACT), context.formatPhrase(RenderingContext.PAT_NOK_CONTACT_HINT));
}
XhtmlNode td = tr.td();
td.colspan("3");
@ -581,11 +581,11 @@ public class PatientRenderer extends ResourceRenderer {
}
} else if (gender != null) {
li = ul.li();
li.tx(context.formatMessage(RenderingContext.PAT_GENDER, gender));
li.tx(context.formatPhrase(RenderingContext.PAT_GENDER, gender));
}
if (rels.size() > 1) {
li = ul.li();
li.tx(context.formatMessage(RenderingContext.PAT_RELN));
li.tx(context.formatPhrase(RenderingContext.PAT_RELN));
boolean first = true;
for (CodeableConcept rel : rels) {
if (first) first = false; else li.tx(", ");
@ -600,12 +600,12 @@ public class PatientRenderer extends ResourceRenderer {
}
if (organization != null) {
li = ul.li();
li.tx(context.formatMessage(RenderingContext.PAT_ORG));
li.tx(context.formatPhrase(RenderingContext.PAT_ORG));
render(r, li, organization);
}
if (period != null) {
li = ul.li();
li.tx(context.formatMessage(RenderingContext.PAT_PERIOD));
li.tx(context.formatPhrase(RenderingContext.PAT_PERIOD));
render(r, li, period);
}
}
@ -625,7 +625,7 @@ public class PatientRenderer extends ResourceRenderer {
};
if (names.size() == 1) {
XhtmlNode tr = tbl.tr();
nameCell(tr, context.formatMessage(RenderingContext.PAT_ALT_NAME), context.formatMessage(RenderingContext.PAT_ALT_NAME_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_ALT_NAME), context.formatPhrase(RenderingContext.PAT_ALT_NAME_HINT));
XhtmlNode td = tr.td();
td.colspan("3");
if (names.size() == 1) {
@ -652,7 +652,7 @@ public class PatientRenderer extends ResourceRenderer {
}
if (tels.size() + adds.size() > 0) {
XhtmlNode tr = tbl.tr();
nameCell(tr, context.formatMessage(RenderingContext.PAT_CONTACT), context.formatMessage(RenderingContext.PAT_CONTACT_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_CONTACT), context.formatPhrase(RenderingContext.PAT_CONTACT_HINT));
XhtmlNode td = tr.td();
td.colspan("3");
if (tels.size() + adds.size() == 1) {
@ -695,7 +695,7 @@ public class PatientRenderer extends ResourceRenderer {
PropertyWrapper a = r.getChildByName("active");
if (a.hasValues()) {
pos++;
nameCell(tr, context.formatMessage(RenderingContext.PAT_ACTIVE), context.formatMessage(RenderingContext.PAT_ACTIVE_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_ACTIVE), context.formatPhrase(RenderingContext.PAT_ACTIVE_HINT));
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
@ -707,7 +707,7 @@ public class PatientRenderer extends ResourceRenderer {
PropertyWrapper a = r.getChildByName("deceased[x]");
if (a.hasValues()) {
pos++;
nameCell(tr, context.formatMessage(RenderingContext.PAT_DECEASED), context.formatMessage(RenderingContext.PAT_DECEASED_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_DECEASED), context.formatPhrase(RenderingContext.PAT_DECEASED_HINT));
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
@ -722,7 +722,7 @@ public class PatientRenderer extends ResourceRenderer {
if (pos == 3) {
tr = tbl.tr();
}
nameCell(tr, context.formatMessage(RenderingContext.PAT_MARITAL), context.formatMessage(RenderingContext.PAT_MARITAL_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_MARITAL), context.formatPhrase(RenderingContext.PAT_MARITAL_HINT));
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
@ -737,7 +737,7 @@ public class PatientRenderer extends ResourceRenderer {
if (pos == 3) {
tr = tbl.tr();
}
nameCell(tr, context.formatMessage(RenderingContext.PAT_MUL_BIRTH), context.formatMessage(RenderingContext.PAT_MUL_BIRTH_HINT));
nameCell(tr, context.formatPhrase(RenderingContext.PAT_MUL_BIRTH), context.formatPhrase(RenderingContext.PAT_MUL_BIRTH_HINT));
XhtmlNode td = tr.td();
if (pos == count) {
td.colspan("3");
@ -780,7 +780,7 @@ public class PatientRenderer extends ResourceRenderer {
String n = UUID.randomUUID().toString().toLowerCase()+ext;
TextFile.bytesToFile(att.getData(), ManagedFileAccess.file(Utilities.path(context.getDestDir(), n)));
context.registerFile(n);
td.img(n, context.formatMessage(RenderingContext.PAT_PHOTO));
td.img(n, context.formatPhrase(RenderingContext.PAT_PHOTO));
}
return;
}

View File

@ -107,7 +107,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
boolean idDone = false;
XhtmlNode p = x.para();
if (context.isAddGeneratedNarrativeHeader()) {
p.b().tx(/*!#*/"Generated Narrative: "+r.fhirType()+(context.isContained() ? " #"+r.getId() : ""));
p.b().tx(context.formatPhrase(RenderingContext.PROF_DRIV_GEN_NARR, r.fhirType(), (context.isContained() ? " #"+r.getId() : "")));
if (!Utilities.noString(r.getId())) {
p.an(r.getId());
p.an("hc"+r.getId());
@ -125,7 +125,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
try {
StructureDefinition sd = r.getDefinition();
if (sd == null) {
throw new FHIRException(/*!#*/"Cannot find definition for "+r.fhirType());
throw new FHIRException(context.formatPhrase(RenderingContext.PROF_DRIV_FEXCP, r.fhirType())+" ");
} else {
ElementDefinition ed = sd.getSnapshot().getElement().get(0);
containedIds.clear();
@ -133,9 +133,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), context.isTechnicalMode(), 0);
}
} catch (Exception e) {
System.out.println(/*!#*/"Error Generating Narrative for "+r.fhirType()+"/"+r.getId()+": "+e.getMessage());
System.out.println(context.formatPhrase(RenderingContext.PROF_DRIV_ERR_GEN_NARR) +r.fhirType()+"/"+r.getId()+": "+e.getMessage());
e.printStackTrace();
x.para().b().style("color: maroon").tx(/*!#*/"Exception generating Narrative: "+e.getMessage());
x.para().b().style("color: maroon").tx(context.formatPhrase(RenderingContext.PROF_DRIV_EXCP, e.getMessage())+" ");
}
return hasExtensions;
}

View File

@ -29,10 +29,10 @@ public class ProvenanceRenderer extends ResourceRenderer {
if (!prv.getTarget().isEmpty()) {
if (prv.getTarget().size() == 1) {
XhtmlNode p = x.para();
p.tx(/*!#*/"Provenance for ");
p.tx(context.formatPhrase(RenderingContext.PROV_PROV)+" ");
renderReference(prv, p, prv.getTargetFirstRep());
} else {
x.para().tx(/*!#*/"Provenance for:");
x.para().tx(context.formatPhrase(RenderingContext.PROV_PROVE)+" ");
XhtmlNode ul = x.ul();
for (Reference ref : prv.getTarget()) {
renderReference(prv, ul.li(), ref);
@ -40,12 +40,12 @@ public class ProvenanceRenderer extends ResourceRenderer {
}
}
// summary table
x.para().tx(/*!#*/"Summary");
x.para().tx(context.formatPhrase(RenderingContext.GENERAL_SUMM));
XhtmlNode t = x.table("grid");
XhtmlNode tr;
if (prv.hasOccurred()) {
tr = t.tr();
tr.td().tx(/*!#*/"Occurrence");
tr.td().tx(context.formatPhrase(RenderingContext.PROV_OCC));
if (prv.hasOccurredPeriod()) {
renderPeriod(tr.td(), prv.getOccurredPeriod());
} else {
@ -54,12 +54,12 @@ public class ProvenanceRenderer extends ResourceRenderer {
}
if (prv.hasRecorded()) {
tr = t.tr();
tr.td().tx(/*!#*/"Recorded");
tr.td().tx(context.formatPhrase(RenderingContext.PROV_REC));
tr.td().addText(displayDateTime(prv.getRecordedElement()));
}
if (prv.hasPolicy()) {
tr = t.tr();
tr.td().tx(/*!#*/"Policy");
tr.td().tx(context.formatPhrase(RenderingContext.PROV_POL));
if (prv.getPolicy().size() == 1) {
renderUri(tr.td(), prv.getPolicy().get(0));
} else {
@ -71,12 +71,12 @@ public class ProvenanceRenderer extends ResourceRenderer {
}
if (prv.hasLocation()) {
tr = t.tr();
tr.td().tx(/*!#*/"Location");
tr.td().tx(context.formatPhrase(RenderingContext.GENERAL_LOCATION));
renderReference(prv, tr.td(), prv.getLocation());
}
if (prv.hasActivity()) {
tr = t.tr();
tr.td().tx(/*!#*/"Activity");
tr.td().tx(context.formatPhrase(RenderingContext.PROV_ACT));
renderCodeableConcept(tr.td(), prv.getActivity(), false);
}
@ -88,18 +88,18 @@ public class ProvenanceRenderer extends ResourceRenderer {
hasRole = hasRole || a.hasRole();
hasOnBehalfOf = hasOnBehalfOf || a.hasOnBehalfOf();
}
x.para().b().tx(/*!#*/"Agents");
x.para().b().tx(context.formatPhrase(RenderingContext.PROV_AGE));
t = x.table("grid");
tr = t.tr();
if (hasType) {
tr.td().b().tx(/*!#*/"Type");
tr.td().b().tx(context.formatPhrase(RenderingContext.GENERAL_TYPE));
}
if (hasRole) {
tr.td().b().tx(/*!#*/"Role");
tr.td().b().tx(context.formatPhrase(RenderingContext.PROV_ROLE));
}
tr.td().b().tx(/*!#*/"who");
tr.td().b().tx(context.formatPhrase(RenderingContext.PROV_WHO));
if (hasOnBehalfOf) {
tr.td().b().tx(/*!#*/"On Behalf Of");
tr.td().b().tx(context.formatPhrase(RenderingContext.PROV_BEHALF));
}
for (ProvenanceAgentComponent a : prv.getAgent()) {
tr = t.tr();
@ -147,12 +147,12 @@ public class ProvenanceRenderer extends ResourceRenderer {
}
public String display(Provenance prv) throws UnsupportedEncodingException, IOException {
return /*!#*/"Provenance for "+displayReference(prv, prv.getTargetFirstRep());
return (context.formatPhrase(RenderingContext.PROV_FOR, displayReference(prv, prv.getTargetFirstRep()))+" ");
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return /*!#*/"Not done yet";
return (context.formatPhrase(RenderingContext.GENERAL_TODO));
}
}

View File

@ -45,7 +45,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// case DEFNS: return renderDefns(x, q);
case TREE: return renderTree(x, q);
default:
throw new Error(/*!#*/"Unknown QuestionnaireResponse Renderer Mode");
throw new Error(context.formatPhrase(RenderingContext.QUEST_UNKNOWN_MODE));
}
}
@ -57,7 +57,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// case DEFNS: return renderDefns(x, q);
case TREE: return renderTree(x, qr);
default:
throw new Error(/*!#*/"Unknown QuestionnaireResponse Renderer Mode");
throw new Error(context.formatPhrase(RenderingContext.QUEST_UNKNOWN_MODE));
}
}
@ -71,10 +71,10 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"LinkId", /*!#*/"The linkId for the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Text", /*!#*/"Text for the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Definition", /*!#*/"Minimum and Maximum # of times the the itemcan appear in the instance", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Answer", /*!#*/"The type of the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_LINKID), context.formatPhrase(RenderingContext.QUEST_LINK), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_TEXT), context.formatPhrase(RenderingContext.QUEST_TEXTFOR), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DEFINITION), context.formatPhrase(RenderingContext.QUEST_TIMES), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_ANSWER), context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM), null, 0));
boolean hasExt = false;
// first we add a root for the questionaire itself
@ -98,10 +98,10 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
model.setDocoImg(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "help16.png"));
}
model.setDocoRef(context.getLink(KnownLinkType.SPEC)+"formats.html#table");
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"LinkId", /*!#*/"The linkId for the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Text", /*!#*/"Text for the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Definition", /*!#*/"Minimum and Maximum # of times the the itemcan appear in the instance", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), /*!#*/"Answer", /*!#*/"The type of the item", null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_LINKID), context.formatPhrase(RenderingContext.QUEST_LINK), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_TEXT), context.formatPhrase(RenderingContext.QUEST_TEXTFOR), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.GENERAL_DEFINITION), context.formatPhrase(RenderingContext.QUEST_TIMES), null, 0));
model.getTitles().add(gen.new Title(null, model.getDocoRef(), context.formatPhrase(RenderingContext.QUEST_ANSWER), context.formatPhrase(RenderingContext.QUEST_TYPE_ITEM), null, 0));
boolean hasExt = false;
// first we add a root for the questionaire itself
@ -120,10 +120,10 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
Row r = gen.new Row();
rows.add(r);
r.setIcon("icon_q_root.gif", /*!#*/"QuestionnaireResponseRoot");
r.setIcon("icon_q_root.gif", context.formatPhrase(RenderingContext.QUEST_RESP_ROOT));
r.getCells().add(gen.new Cell(null, null, q.getId(), null, null));
r.getCells().add(gen.new Cell(null, null, "", null, null));
r.getCells().add(gen.new Cell(null, null, /*!#*/"QuestionnaireResponse", null, null));
r.getCells().add(gen.new Cell(null, null, context.formatPhrase(RenderingContext.QUEST_RESP), null, null));
r.getCells().add(gen.new Cell(null, null, "", null, null));
return r;
}
@ -136,18 +136,18 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
String ref = b == null ? null : b.primitiveValue();
Questionnaire q = context.getContext().fetchResource(Questionnaire.class, ref);
r.setIcon("icon_q_root.gif", /*!#*/"QuestionnaireResponseRoot");
r.setIcon("icon_q_root.gif", context.formatPhrase(RenderingContext.QUEST_RESP_ROOT));
r.getCells().add(gen.new Cell(null, null, qr.getId(), null, null));
r.getCells().add(gen.new Cell(null, null, "", null, null));
if (ref == null ) {
r.getCells().add(gen.new Cell(null, null, "", null, null));
r.getCells().add(gen.new Cell(/*!#*/"Questionnaire:", null, /*!#*/"None specified", null, null));
r.getCells().add(gen.new Cell(context.formatPhrase(RenderingContext.QUEST_QUESTION), null, context.formatPhrase(RenderingContext.QUEST_NONE_SPEC), null, null));
} else if (q == null || !q.hasWebPath()) {
r.getCells().add(gen.new Cell(null, null, "", null, null));
r.getCells().add(gen.new Cell(/*!#*/"Questionnaire:", null, ref, null, null));
r.getCells().add(gen.new Cell(context.formatPhrase(RenderingContext.QUEST_QUESTION), null, ref, null, null));
} else{
r.getCells().add(gen.new Cell(null, null, "", null, null));
r.getCells().add(gen.new Cell(/*!#*/"Questionnaire:", q.getWebPath(), q.present(), null, null));
r.getCells().add(gen.new Cell(context.formatPhrase(RenderingContext.QUEST_QUESTION), q.getWebPath(), q.present(), null, null));
}
return r;
}
@ -168,9 +168,9 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
}
}
if (hasItem) {
r.setIcon("icon-q-group.png", /*!#*/"Group");
r.setIcon("icon-q-group.png", context.formatPhrase(RenderingContext.QUEST_GROUP));
} else {
r.setIcon("icon-q-string.png", /*!#*/"Item");
r.setIcon("icon-q-string.png", context.formatPhrase(RenderingContext.QUEST_ITEM));
}
String linkId = i.has("linkId") ? i.get("linkId").primitiveValue() : "??";
String text = i.has("text") ? i.get("text").primitiveValue() : "";
@ -235,9 +235,9 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
hasItem = a.hasItem();
}
if (hasItem) {
r.setIcon("icon-q-group.png", /*!#*/"Group");
r.setIcon("icon-q-group.png", context.formatPhrase(RenderingContext.QUEST_GROUP));
} else {
r.setIcon("icon-q-string.png", /*!#*/"Item");
r.setIcon("icon-q-string.png", context.formatPhrase(RenderingContext.QUEST_ITEM));
}
r.getCells().add(gen.new Cell(null, context.getDefinitionsTarget() == null ? "" : context.getDefinitionsTarget()+"#item."+i.getLinkId(), i.getLinkId(), null, null));
r.getCells().add(gen.new Cell(null, null, i.getText(), null, null));
@ -327,7 +327,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
public boolean renderForm(XhtmlNode x, ResourceWrapper q) throws UnsupportedEncodingException, IOException {
boolean hasExt = false;
XhtmlNode d = x.div();
d.tx(/*!#*/"todo");
d.tx(context.formatPhrase(RenderingContext.GENERAL_TODO));
// boolean hasPrefix = false;
// for (QuestionnaireItemComponent c : q.getItem()) {
// hasPrefix = hasPrefix || doesItemHavePrefix(c);
@ -370,7 +370,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// }
// p.span(null, "linkId: "+i.getLinkId()).tx(i.getText());
// if (i.getRequired()) {
// p.span("color: red", /*!#*/"Mandatory").tx("*");
// p.span("color: red", context.formatPhrase(RenderingContext.QUEST_MAND)).tx("*");
// }
//
// XhtmlNode input = null;
@ -605,16 +605,16 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// }
//
private boolean renderLinks(XhtmlNode x, QuestionnaireResponse q) {
x.para().tx(/*!#*/"Try this QuestionnaireResponse out:");
x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY_QUEST));
XhtmlNode ul = x.ul();
ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(/*!#*/"NLM Forms Library");
ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM));
return false;
}
private boolean renderLinks(XhtmlNode x, ResourceWrapper q) {
x.para().tx(/*!#*/"Try this QuestionnaireResponse out:");
x.para().tx(context.formatPhrase(RenderingContext.QUEST_TRY_QUEST));
XhtmlNode ul = x.ul();
ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(/*!#*/"NLM Forms Library");
ul.li().ah("http://todo.nlm.gov/path?mode=ig&src="+Utilities.pathURL(context.getLink(KnownLinkType.SELF), "package.tgz")+"&q="+q.getId()+".json").tx(context.formatPhrase(RenderingContext.QUEST_NLM));
return false;
}
@ -711,13 +711,13 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// }
// if (qi.hasAnswerOption()) {
// XhtmlNode tr = tbl.tr();
// tr.td().tx(/*!#*/"Allowed Answers");
// tr.td().tx(context.formatPhrase(RenderingContext.QUEST_ALLOWED));
// XhtmlNode ul = tr.td().ul();
// for (QuestionnaireItemAnswerOptionComponent ans : qi.getAnswerOption()) {
// XhtmlNode li = ul.li();
// render(li, ans.getValue());
// if (ans.getInitialSelected()) {
// li.tx(/*!#*/" (initially selected)");
// li.tx(context.formatPhrase(RenderingContext.QUEST_INITIALLY));
// }
// }
// }
@ -738,7 +738,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// // appearance
// if (qi.hasExtension(" http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory")) {
// XhtmlNode tr = tbl.tr();
// tr.td().ah("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").tx(/*!#*/"Display Category");
// tr.td().ah("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").tx(context.formatPhrase(RenderingContext.QUEST_DISPLAY_CAT));
// render(tr.td(), qi.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-displayCategory").getValue());
// }
// if (ToolingExtensions.readBoolExtension(qi, "http://hl7.org/fhir/StructureDefinition/QuestionnaireResponse-hidden")) {
@ -763,14 +763,14 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
// }
// if (qi.hasExtension("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod")) {
// XhtmlNode tr = tbl.tr();
// tr.td().ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod").tx(/*!#*/"Observation Link Period");
// tr.td().ah(getSDCLink("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod").tx(context.formatPhrase(RenderingContext.QUEST_OBSERVATION));
// render(tr.td(), qi.getExtensionByUrl("http://hl7.org/fhir/uv/sdc/StructureDefinition/sdc-QuestionnaireResponse-observationLinkPeriod").getValue());
// }
//
// // dynamic management
// if (qi.hasEnableWhen()) {
// XhtmlNode tr = tbl.tr();
// tr.td().tx(/*!#*/"Enable When");
// tr.td().tx(context.formatPhrase(RenderingContext.QUEST_ENABLE));
// td = tr.td();
// if (qi.getEnableWhen().size() == 1) {
// renderEnableWhen(td, qi.getEnableWhen().get(0));
@ -876,12 +876,12 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
@Override
public String display(Resource r) throws UnsupportedEncodingException, IOException {
return /*!#*/"todo";
return context.formatPhrase(RenderingContext.GENERAL_TODO);
}
@Override
public String display(ResourceWrapper r) throws UnsupportedEncodingException, IOException {
return /*!#*/"Not done yet";
return context.formatPhrase(RenderingContext.GENERAL_TODO);
}
}

View File

@ -48,14 +48,14 @@ public class Renderer {
}
protected String formatMessage(String theMessage, Object... theMessageArguments) {
return context.formatMessage(theMessage, theMessageArguments);
protected String formatPhrase(String theMessage, Object... theMessageArguments) {
return context.formatPhrase(theMessage, theMessageArguments);
}
public void genStandardsStatus(XhtmlNode td, StandardsStatus ss) {
if (ss != null) {
td.tx(" ");
XhtmlNode a = td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "versions.html#std-process"), /*!#*/"Standards Status = "+ss.toDisplay());
XhtmlNode a = td.ah(Utilities.pathURL(context.getLink(KnownLinkType.SPEC), "versions.html#std-process"), (context.formatPhrase(RenderingContext.REND_STANDARDS, ss.toDisplay())));
a.style("padding-left: 3px; padding-right: 3px; border: 1px grey solid; font-weight: bold; color: black; background-color: "+ss.getColor());
a.tx(ss.getAbbrev());
}
@ -72,21 +72,21 @@ public class Renderer {
switch (vca.getType()) {
case Added:
XhtmlNode spanOuter = x.span("border: solid 1px #dddddd; margin: 2px; padding: 2px", null);
XhtmlNode spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been added since "+context.getChangeVersion());
XhtmlNode spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", (context.formatPhrase(RenderingContext.REND_SINCE_ADDED, context.getChangeVersion())));
spanInner.img("icon-change-add.png", "icon");
spanInner.tx(" "+/*!#*/"Added:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_ADDED));
return spanOuter;
case Changed:
spanOuter = x.span("border: solid 1px #dddddd; margin: 2px; padding: 2px", null);
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been changed since "+context.getChangeVersion()+(vca.getOriginal() != null ? " (was '"+vca.getOriginal()+"')" : ""));
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", vca.getOriginal() == null ? context.formatPhrase(RenderingContext.REND_SINCE_CHANGED, context.getChangeVersion()) : context.formatPhrase(RenderingContext.REND_SINCE_CHANGED_WAS, context.getChangeVersion(), vca.getOriginal()));
spanInner.img("icon-change-edit.png", "icon");
spanInner.tx(" "+/*!#*/"Changed:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_CHANGED));
return spanOuter;
case Deleted:
spanOuter = x.span("border: solid 1px #dddddd; margin: 2px; padding: 2px", null);
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been removed since "+context.getChangeVersion());
spanInner = spanOuter.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", (context.formatPhrase(RenderingContext.GENERAL_REMOVED_SINCE, context.getChangeVersion())));
spanInner.img("icon-change-remove.png", "icon");
spanInner.tx(" "+/*!#*/"Removed:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_REMOVED));
return spanOuter.strikethrough();
default:
return x;
@ -104,21 +104,21 @@ public class Renderer {
switch (vca.getType()) {
case Added:
XhtmlNode divOuter = x.div("border: solid 1px #dddddd; margin: 2px; padding: 2px");
XhtmlNode spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been added since "+context.getChangeVersion());
XhtmlNode spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", (context.formatPhrase(RenderingContext.REND_SINCE_ADDED, context.getChangeVersion())));
spanInner.img("icon-change-add.png", "icon");
spanInner.tx(" "+/*!#*/"Added:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_ADDED));
return divOuter;
case Changed:
divOuter = x.div("border: solid 1px #dddddd; margin: 2px; padding: 2px");
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been changed since "+context.getChangeVersion()+(vca.getOriginal() != null ? " (was '"+(vca.getOriginal())+"')" : ""));
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", vca.getOriginal() == null ? context.formatPhrase(RenderingContext.REND_SINCE_CHANGED, context.getChangeVersion()) : context.formatPhrase(RenderingContext.REND_SINCE_CHANGED_WAS, context.getChangeVersion(), vca.getOriginal()));
spanInner.img("icon-change-edit.png", "icon");
spanInner.tx(" "+/*!#*/"Changed:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_CHANGED));
return divOuter;
case Deleted:
divOuter = x.div("border: solid 1px #dddddd; margin: 2px; padding: 2px");
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been removed since "+context.getChangeVersion());
spanInner = divOuter.para().style("margin: 0").span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", (context.formatPhrase(RenderingContext.GENERAL_REMOVED_SINCE, context.getChangeVersion())));
spanInner.img("icon-change-remove.png", "icon");
spanInner.tx(" "+/*!#*/"Removed:");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_REMOVED));
return divOuter.strikethrough();
default:
return x;
@ -140,27 +140,27 @@ public class Renderer {
tr.style("border: solid 1px #dddddd; margin: 2px; padding: 2px");
}
XhtmlNode td = tr.td();
XhtmlNode span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px",/*!#*/"This row of content has been added since "+context.getChangeVersion());
XhtmlNode span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", (context.formatPhrase(RenderingContext.REND_ROW_SINCE, context.getChangeVersion())));
span.img("icon-change-add.png", "icon");
span.tx(" "+/*!#*/"Added:");
span.tx(" "+ context.formatPhrase(RenderingContext.REND_ADDED));
XhtmlNode x = new XhtmlNode(NodeType.Element, "holder");
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This row of content has been added since "+context.getChangeVersion()).tx(" ");
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", context.formatPhrase(RenderingContext.REND_ROW_SINCE, context.getChangeVersion())).tx(" ");
tr.styleCells(x);
return td;
case Changed:
td = tr.td();
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This row of content has been changed since"+context.getChangeVersion()+(vca.getOriginal() != null ? " (was '"+vca.getOriginal()+"')" : ""));
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", context.formatPhrase(RenderingContext.REND_ROW_CHANGED_SINCE_WAS, context.getChangeVersion(), vca.getOriginal()));
span.img("icon-change-edit.png", "icon");
span.tx(" "+/*!#*/"Changed:");
span.tx(" "+ context.formatPhrase(RenderingContext.REND_CHANGED));
return td;
case Deleted:
tr.style("text-decoration: line-through");
td = tr.td();
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been removed since "+context.getChangeVersion());
span = td.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", context.formatPhrase(RenderingContext.GENERAL_REMOVED_SINCE, context.getChangeVersion()));
span.img("icon-change-remove.png", "icon");
span.tx(" "+/*!#*/"Removed:");
span.tx(" "+ context.formatPhrase(RenderingContext.REND_REMOVED));
x = new XhtmlNode(NodeType.Element, "holder");
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px; text-decoration: none", /*!#*/"This row of content has been added since "+context.getChangeVersion()).tx(" ");
x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px; text-decoration: none", context.formatPhrase(RenderingContext.REND_ROW_SINCE, context.getChangeVersion())).tx(" ");
tr.styleCells(x);
return td;
default:
@ -168,29 +168,30 @@ public class Renderer {
}
}
public static void renderStatusSummary(Base base, XhtmlNode x, String version, String... metadataFields) {
public static void renderStatusSummary(RenderingContext context, Base base, XhtmlNode x, String version, String... metadataFields) {
if (base.hasUserData(VersionComparisonAnnotation.USER_DATA_NAME)) {
VersionComparisonAnnotation self = (VersionComparisonAnnotation) base.getUserData(VersionComparisonAnnotation.USER_DATA_NAME);
switch (self.getType()) {
case Added:
XhtmlNode spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been added since "+version);
XhtmlNode spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", context.formatPhrase(RenderingContext.REND_SINCE_ADDED, version));
spanInner.img("icon-change-add.png", "icon");
spanInner.tx(" "+/*!#*/"Added");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_ADDED));
return;
case Changed:
if (self.getComp().noChangeOtherThanMetadata(metadataFields)) {
x.span("color: #eeeeee").tx("n/c");
return;
} else {
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been changed since "+version+(self.getOriginal() != null ? " (was '"+(self.getOriginal())+"')" : ""));
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px",
self.getOriginal() != null ? context.formatPhrase(RenderingContext.REND_SINCE_CHANGED_WAS, version, self.getOriginal()) : context.formatPhrase(RenderingContext.REND_SINCE_CHANGED, version));
spanInner.img("icon-change-edit.png", "icon");
spanInner.tx(" "+/*!#*/"Changed");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_CHANGED));
}
return;
case Deleted:
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", /*!#*/"This content has been added since "+version);
spanInner = x.span("background-color: #fff2ff; border-left: solid 3px #ffa0ff; margin: 2px; padding: 2px", context.formatPhrase(RenderingContext.GENERAL_REMOVED_SINCE, version));
spanInner.img("icon-change-remove.png", "icon");
spanInner.tx(" "+/*!#*/"Removed");
spanInner.tx(" "+context.formatPhrase(RenderingContext.REND_REMOVED));
return;
default:
x.span("color: #eeeeee").tx("n/c");

Some files were not shown because too many files have changed in this diff Show More