fixes for 5.1.8 (#336)
* Fix up conversion for date problems * Mark packages as unsuitable for publication * rework rendering tests & fix bug in Parameters renderer * fix test case depedency * update VSACImporter to get value sets from VSAC directly * Fix up rendering of Extensions * Add support for choice groups, and markdownify some elements
This commit is contained in:
parent
6cf6367b30
commit
7ca698f36a
|
@ -65,6 +65,7 @@ import org.hl7.fhir.convertors.conv10_40.ValueSet10_40;
|
|||
import org.hl7.fhir.dstu2.model.CodeableConcept;
|
||||
import org.hl7.fhir.dstu2.model.Parameters;
|
||||
import org.hl7.fhir.dstu2.model.Parameters.ParametersParameterComponent;
|
||||
import org.hl7.fhir.dstu2.model.PositiveIntType;
|
||||
import org.hl7.fhir.dstu2.model.Reference;
|
||||
import org.hl7.fhir.dstu2.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
|
@ -3423,4 +3424,10 @@ public class VersionConvertor_10_40 {
|
|||
public static org.hl7.fhir.dstu2.model.Resource convertResource(org.hl7.fhir.r4.model.Resource src) throws FHIRException {
|
||||
return convertResource(src, null);
|
||||
}
|
||||
|
||||
public static UnsignedIntType convertUnsignedIntToPositive(PositiveIntType src) {
|
||||
org.hl7.fhir.r4.model.UnsignedIntType tgt = src.hasValue() ? new org.hl7.fhir.r4.model.UnsignedIntType(src.getValue()) : new org.hl7.fhir.r4.model.UnsignedIntType();
|
||||
copyElement(src, tgt);
|
||||
return tgt;
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ public class MedicationRequest10_40 {
|
|||
tgt.setIntent(org.hl7.fhir.r4.model.MedicationRequest.MedicationRequestIntent.ORDER);
|
||||
for (org.hl7.fhir.dstu2.model.Identifier identifier : src.getIdentifier()) tgt.addIdentifier(VersionConvertor_10_40.convertIdentifier(identifier));
|
||||
if (src.hasDateWritten())
|
||||
tgt.setAuthoredOn(src.getDateWritten());
|
||||
tgt.setAuthoredOnElement(VersionConvertor_10_40.convertDateTime(src.getDateWrittenElement()));
|
||||
if (src.hasStatus())
|
||||
tgt.setStatus(org.hl7.fhir.r4.model.MedicationRequest.MedicationRequestStatus.fromCode(src.getStatus().toCode()));
|
||||
if (src.hasPatient())
|
||||
|
@ -48,7 +48,7 @@ public class MedicationRequest10_40 {
|
|||
return null;
|
||||
org.hl7.fhir.r4.model.Dosage tgt = new org.hl7.fhir.r4.model.Dosage();
|
||||
if (src.hasText())
|
||||
tgt.setText(src.getText());
|
||||
tgt.setTextElement(VersionConvertor_10_40.convertString(src.getTextElement()));
|
||||
if (src.hasAdditionalInstructions())
|
||||
tgt.addAdditionalInstruction(VersionConvertor_10_40.convertCodeableConcept(src.getAdditionalInstructions()));
|
||||
if (src.hasTiming())
|
||||
|
@ -79,7 +79,7 @@ public class MedicationRequest10_40 {
|
|||
if (src.hasValidityPeriod())
|
||||
tgt.setValidityPeriod(VersionConvertor_10_40.convertPeriod(src.getValidityPeriod()));
|
||||
if (src.hasNumberOfRepeatsAllowed())
|
||||
tgt.setNumberOfRepeatsAllowed(src.getNumberOfRepeatsAllowed());
|
||||
tgt.setNumberOfRepeatsAllowedElement(VersionConvertor_10_40.convertUnsignedIntToPositive(src.getNumberOfRepeatsAllowedElement()));
|
||||
if (src.hasQuantity())
|
||||
tgt.setQuantity(VersionConvertor_10_40.convertSimpleQuantity(src.getQuantity()));
|
||||
if (src.hasExpectedSupplyDuration())
|
||||
|
|
|
@ -1,26 +1,29 @@
|
|||
package org.hl7.fhir.convertors.misc;
|
||||
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.r4.utils.client.FHIRToolingClient;
|
||||
import org.hl7.fhir.r4.formats.JsonParser;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r4.model.ValueSet;
|
||||
import org.hl7.fhir.r4.model.ValueSet.ConceptSetComponent;
|
||||
import org.hl7.fhir.utilities.CSVReader;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URISyntaxException;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class VSACImporter extends OIDBasedValueSetImporter {
|
||||
|
||||
public static void main(String[] args) throws FileNotFoundException, FHIRException, IOException, ParseException {
|
||||
public static void main(String[] args) throws FileNotFoundException, FHIRException, IOException, ParseException, URISyntaxException {
|
||||
// new PhinVadsImporter().importValueSet(TextFile.fileToBytes("C:\\work\\org.hl7.fhir\\packages\\us.cdc.phinvads-source\\source\\PHVS_BirthDefectsLateralityatDiagnosis_HL7_V1.txt"));
|
||||
VSACImporter self = new VSACImporter();
|
||||
self.process(args[0], args[1]);
|
||||
self.process(args[0], args[1], args[2], args[3]);
|
||||
}
|
||||
|
||||
public VSACImporter() throws FileNotFoundException, FHIRException, IOException {
|
||||
|
@ -28,69 +31,87 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
init();
|
||||
}
|
||||
|
||||
private void process(String source, String dest) {
|
||||
for (File f : new File(source).listFiles()) {
|
||||
private void process(String source, String dest, String username, String password) throws FHIRException, FileNotFoundException, IOException, URISyntaxException {
|
||||
CSVReader csv = new CSVReader(new FileInputStream(source));
|
||||
csv.readHeaders();
|
||||
FHIRToolingClient client = new FHIRToolingClient("https://cts.nlm.nih.gov/fhir", username, password);
|
||||
int i = 0;
|
||||
while (csv.line()) {
|
||||
String oid = csv.cell("OID");
|
||||
try {
|
||||
System.out.println("Process " + f.getName());
|
||||
List<ValueSet> vsl = importValueSet(TextFile.fileToBytes(f));
|
||||
for (ValueSet vs : vsl) {
|
||||
if (vs.getId() != null) {
|
||||
new JsonParser().compose(new FileOutputStream(Utilities.path(dest, "ValueSet-" + vs.getId() + ".json")), vs);
|
||||
}
|
||||
ValueSet vs = client.read(ValueSet.class, oid);
|
||||
new JsonParser().compose(new FileOutputStream(Utilities.path(dest, "ValueSet-"+oid+".json")), vs);
|
||||
i++;
|
||||
if (i % 100 == 0) {
|
||||
System.out.println(i);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Unable to fetch OID "+oid+": "+e.getMessage());
|
||||
}
|
||||
}
|
||||
System.out.println("Done. "+i+" ValueSets");
|
||||
// for (File f : new File(source).listFiles()) {
|
||||
// try {
|
||||
// System.out.println("Process " + f.getName());
|
||||
// List<ValueSet> vsl = importValueSet(TextFile.fileToBytes(f));
|
||||
// for (ValueSet vs : vsl) {
|
||||
// if (vs.getId() != null) {
|
||||
// new JsonParser().compose(new FileOutputStream(Utilities.path(dest, "ValueSet-" + vs.getId() + ".json")), vs);
|
||||
// }
|
||||
// }
|
||||
// } catch (Exception e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
private List<ValueSet> importValueSet(byte[] source) throws Exception {
|
||||
List<ValueSet> res = new ArrayList<ValueSet>();
|
||||
Element x = loadXml(new ByteArrayInputStream(source)).getDocumentElement();
|
||||
List<Element> vl = XMLUtil.getNamedChildren(x, "DescribedValueSet");
|
||||
for (Element v : vl) {
|
||||
ValueSet vs = new ValueSet();
|
||||
vs.setId(v.getAttribute("ID"));
|
||||
vs.setUrl("http://vsac.nlm.nih.gov/fhir/ValueSet/" + vs.getId());
|
||||
vs.getMeta().setSource("https://vsac.nlm.nih.gov/valueset/" + vs.getId() + "/expansion");
|
||||
vs.setVersion(v.getAttribute("version"));
|
||||
vs.setTitle(v.getAttribute("displayName"));
|
||||
vs.setName(Utilities.titleize(vs.getTitle()).replace(" ", ""));
|
||||
Element d = XMLUtil.getNamedChild(v, "Purpose");
|
||||
if (d != null) {
|
||||
vs.setDescription(d.getTextContent());
|
||||
}
|
||||
Element s = XMLUtil.getNamedChild(v, "Status");
|
||||
if (s != null && "Active".equals(s.getTextContent())) {
|
||||
vs.setStatus(PublicationStatus.ACTIVE);
|
||||
} else {
|
||||
vs.setStatus(PublicationStatus.DRAFT);
|
||||
}
|
||||
Element dt = XMLUtil.getNamedChild(v, "RevisionDate");
|
||||
if (dt != null) {
|
||||
vs.getDateElement().setValueAsString(dt.getTextContent());
|
||||
}
|
||||
|
||||
Element cl = XMLUtil.getNamedChild(v, "ConceptList");
|
||||
Element cc = XMLUtil.getFirstChild(cl);
|
||||
|
||||
while (cc != null) {
|
||||
String code = cc.getAttribute("code");
|
||||
String display = cc.getAttribute("displayName");
|
||||
String csoid = cc.getAttribute("codeSystem");
|
||||
String csver = cc.getAttribute("codeSystemVersion");
|
||||
String url = context.oid2Uri(csoid);
|
||||
if (url == null) {
|
||||
url = "urn:oid:" + csoid;
|
||||
}
|
||||
csver = fixVersionforSystem(url, csver);
|
||||
ConceptSetComponent inc = getInclude(vs, url, csver);
|
||||
inc.addConcept().setCode(code).setDisplay(display);
|
||||
cc = XMLUtil.getNextSibling(cc);
|
||||
}
|
||||
|
||||
res.add(vs);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// private List<ValueSet> importValueSet(byte[] source) throws Exception {
|
||||
// List<ValueSet> res = new ArrayList<ValueSet>();
|
||||
// Element x = loadXml(new ByteArrayInputStream(source)).getDocumentElement();
|
||||
// List<Element> vl = XMLUtil.getNamedChildren(x, "DescribedValueSet");
|
||||
// for (Element v : vl) {
|
||||
// ValueSet vs = new ValueSet();
|
||||
// vs.setId(v.getAttribute("ID"));
|
||||
// vs.setUrl("http://cts.nlm.nih.gov/fhir/ValueSet/" + vs.getId());
|
||||
// vs.getMeta().setSource("https://vsac.nlm.nih.gov/valueset/" + vs.getId() + "/expansion");
|
||||
// vs.setVersion(v.getAttribute("version"));
|
||||
// vs.setTitle(v.getAttribute("displayName"));
|
||||
// vs.setName(Utilities.titleize(vs.getTitle()).replace(" ", ""));
|
||||
// Element d = XMLUtil.getNamedChild(v, "Purpose");
|
||||
// if (d != null) {
|
||||
// vs.setDescription(d.getTextContent());
|
||||
// }
|
||||
// Element s = XMLUtil.getNamedChild(v, "Status");
|
||||
// if (s != null && "Active".equals(s.getTextContent())) {
|
||||
// vs.setStatus(PublicationStatus.ACTIVE);
|
||||
// } else {
|
||||
// vs.setStatus(PublicationStatus.DRAFT);
|
||||
// }
|
||||
// Element dt = XMLUtil.getNamedChild(v, "RevisionDate");
|
||||
// if (dt != null) {
|
||||
// vs.getDateElement().setValueAsString(dt.getTextContent());
|
||||
// }
|
||||
//
|
||||
// Element cl = XMLUtil.getNamedChild(v, "ConceptList");
|
||||
// Element cc = XMLUtil.getFirstChild(cl);
|
||||
//
|
||||
// while (cc != null) {
|
||||
// String code = cc.getAttribute("code");
|
||||
// String display = cc.getAttribute("displayName");
|
||||
// String csoid = cc.getAttribute("codeSystem");
|
||||
// String csver = cc.getAttribute("codeSystemVersion");
|
||||
// String url = context.oid2Uri(csoid);
|
||||
// if (url == null) {
|
||||
// url = "urn:oid:" + csoid;
|
||||
// }
|
||||
// csver = fixVersionforSystem(url, csver);
|
||||
// ConceptSetComponent inc = getInclude(vs, url, csver);
|
||||
// inc.addConcept().setCode(code).setDisplay(display);
|
||||
// cc = XMLUtil.getNextSibling(cc);
|
||||
// }
|
||||
//
|
||||
// res.add(vs);
|
||||
// }
|
||||
// return res;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -78,6 +78,9 @@ import org.hl7.fhir.r5.model.Enumeration;
|
|||
import org.hl7.fhir.r5.model.Enumerations.BindingStrength;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
|
||||
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode.Kind;
|
||||
import org.hl7.fhir.r5.model.ExpressionNode.Operation;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.IdType;
|
||||
import org.hl7.fhir.r5.model.IntegerType;
|
||||
|
@ -99,6 +102,8 @@ import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
|
|||
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
|
||||
import org.hl7.fhir.r5.renderers.TerminologyRenderer;
|
||||
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
|
||||
import org.hl7.fhir.r5.utils.FHIRLexer;
|
||||
import org.hl7.fhir.r5.utils.FHIRPathEngine;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.r5.utils.TranslatingUtilities;
|
||||
import org.hl7.fhir.r5.utils.XVerExtensionManager;
|
||||
|
@ -200,6 +205,30 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ElementChoiceGroup {
|
||||
private Row row;
|
||||
private String name;
|
||||
private boolean mandatory;
|
||||
private List<String> elements = new ArrayList<>();
|
||||
|
||||
public ElementChoiceGroup(String name, boolean mandatory) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.mandatory = mandatory;
|
||||
}
|
||||
public Row getRow() {
|
||||
return row;
|
||||
}
|
||||
public List<String> getElements() {
|
||||
return elements;
|
||||
}
|
||||
public void setRow(Row row) {
|
||||
this.row = row;
|
||||
}
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
private static final int MAX_RECURSION_LIMIT = 10;
|
||||
|
||||
|
@ -268,6 +297,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
// note that ProfileUtilities are used re-entrantly internally, so nothing with process state can be here
|
||||
private final IWorkerContext context;
|
||||
private FHIRPathEngine fpe;
|
||||
private List<ValidationMessage> messages;
|
||||
private List<String> snapshotStack = new ArrayList<String>();
|
||||
private ProfileKnowledgeProvider pkp;
|
||||
|
@ -284,6 +314,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
this.context = context;
|
||||
this.messages = messages;
|
||||
this.pkp = pkp;
|
||||
if (context != null) {
|
||||
this.fpe = new FHIRPathEngine(context, this);
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnusedTracker {
|
||||
|
@ -538,6 +571,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
processPaths("", derived.getSnapshot(), baseSnapshot, diff, baseCursor, diffCursor, baseSnapshot.getElement().size()-1,
|
||||
derived.getDifferential().hasElement() ? derived.getDifferential().getElement().size()-1 : -1, url, webUrl, derived.present(), null, null, false, base.getUrl(), null, false, null, new ArrayList<ElementRedirection>(), base);
|
||||
checkGroupConstraints(derived);
|
||||
if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
|
||||
for (ElementDefinition e : diff.getElement()) {
|
||||
if (!e.hasUserData(GENERATED_IN_SNAPSHOT)) {
|
||||
|
@ -666,6 +700,81 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
derived.clearUserData("profileutils.snapshot.generating");
|
||||
}
|
||||
|
||||
private void checkGroupConstraints(StructureDefinition derived) {
|
||||
List<ElementDefinition> toRemove = new ArrayList<>();
|
||||
// List<ElementDefinition> processed = new ArrayList<>();
|
||||
for (ElementDefinition element : derived.getSnapshot().getElement()) {
|
||||
if (!toRemove.contains(element) && !element.hasSlicing() && !"0".equals(element.getMax())) {
|
||||
checkForChildrenInGroup(derived, toRemove, element);
|
||||
}
|
||||
}
|
||||
derived.getSnapshot().getElement().removeAll(toRemove);
|
||||
}
|
||||
|
||||
public void checkForChildrenInGroup(StructureDefinition derived, List<ElementDefinition> toRemove, ElementDefinition element) throws Error {
|
||||
List<ElementDefinition> children = getChildren(derived, element);
|
||||
List<ElementChoiceGroup> groups = readChoices(element, children);
|
||||
for (ElementChoiceGroup group : groups) {
|
||||
System.out.println(children);
|
||||
String mandated = null;
|
||||
Set<String> names = new HashSet<>();
|
||||
for (ElementDefinition ed : children) {
|
||||
String name = tail(ed.getPath());
|
||||
if (names.contains(name)) {
|
||||
throw new Error("huh?");
|
||||
} else {
|
||||
names.add(name);
|
||||
}
|
||||
if (group.getElements().contains(name)) {
|
||||
if (ed.getMin() == 1) {
|
||||
if (mandated == null) {
|
||||
mandated = name;
|
||||
} else {
|
||||
throw new Error("Error: there are two mandatory elements in "+derived.getUrl()+" when there can only be one: "+mandated+" and "+name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mandated != null) {
|
||||
for (ElementDefinition ed : children) {
|
||||
String name = tail(ed.getPath());
|
||||
if (group.getElements().contains(name) && !mandated.equals(name)) {
|
||||
ed.setMax("0");
|
||||
addAllChildren(derived, ed, toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<ElementDefinition> getChildren(StructureDefinition derived, ElementDefinition element) {
|
||||
List<ElementDefinition> elements = derived.getSnapshot().getElement();
|
||||
int index = elements.indexOf(element) + 1;
|
||||
String path = element.getPath()+".";
|
||||
List<ElementDefinition> list = new ArrayList<>();
|
||||
while (index < elements.size()) {
|
||||
ElementDefinition e = elements.get(index);
|
||||
String p = e.getPath();
|
||||
if (p.startsWith(path) && !e.hasSliceName()) {
|
||||
if (!p.substring(path.length()).contains(".")) {
|
||||
list.add(e);
|
||||
}
|
||||
index++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private void addAllChildren(StructureDefinition derived, ElementDefinition element, List<ElementDefinition> toRemove) {
|
||||
List<ElementDefinition> children = getChildList(derived, element);
|
||||
for (ElementDefinition child : children) {
|
||||
toRemove.add(child);
|
||||
addAllChildren(derived, child, toRemove);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkDifferential(List<ElementDefinition> elements, String type, String url) {
|
||||
boolean first = true;
|
||||
for (ElementDefinition ed : elements) {
|
||||
|
@ -3620,12 +3729,17 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
Row currRow = row;
|
||||
List<ElementChoiceGroup> groups = readChoices(element, children);
|
||||
boolean isExtension = Utilities.existsInList(tail(element.getPath()), "extension", "modifierExtension");
|
||||
for (ElementDefinition child : children) {
|
||||
if (!child.hasSliceName())
|
||||
if (!child.hasSliceName()) {
|
||||
currRow = row;
|
||||
if (logicalModel || !child.getPath().endsWith(".id") || (child.getPath().endsWith(".id") && (profile != null) && (profile.getDerivation() == TypeDerivationRule.CONSTRAINT)))
|
||||
currRow = genElement(defPath, gen, currRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport);
|
||||
}
|
||||
Row childRow = chooseChildRowByGroup(gen, currRow, groups, child, element, isConstraintMode);
|
||||
|
||||
if (logicalModel || !child.getPath().endsWith(".id") || (child.getPath().endsWith(".id") && (profile != null) && (profile.getDerivation() == TypeDerivationRule.CONSTRAINT))) {
|
||||
currRow = genElement(defPath, gen, childRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport);
|
||||
}
|
||||
}
|
||||
// if (!snapshot && (extensions == null || !extensions))
|
||||
// for (ElementDefinition child : children)
|
||||
|
@ -3639,6 +3753,34 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
return slicingRow;
|
||||
}
|
||||
|
||||
private Row chooseChildRowByGroup(HierarchicalTableGenerator gen, Row row, List<ElementChoiceGroup> groups, ElementDefinition element, ElementDefinition parent, boolean isConstraintMode) {
|
||||
String name = tail(element.getPath());
|
||||
for (ElementChoiceGroup grp : groups) {
|
||||
if (grp.getElements().contains(name)) {
|
||||
if (grp.getRow() == null) {
|
||||
grp.setRow(makeChoiceElementRow(gen, row, grp, parent, isConstraintMode));
|
||||
}
|
||||
return grp.getRow();
|
||||
}
|
||||
}
|
||||
return row;
|
||||
}
|
||||
|
||||
private Row makeChoiceElementRow(HierarchicalTableGenerator gen, Row prow, ElementChoiceGroup grp, ElementDefinition parent, boolean isConstraintMode) {
|
||||
Row row = gen.new Row();
|
||||
row.setAnchor(parent.getPath()+"-"+grp.getName());
|
||||
row.setColor(getRowColor(parent, isConstraintMode));
|
||||
row.setLineColor(1);
|
||||
row.setIcon("icon_choice.gif", HierarchicalTableGenerator.TEXT_ICON_CHOICE);
|
||||
row.getCells().add(gen.new Cell(null, null, "(Choice of one)", "", null));
|
||||
row.getCells().add(gen.new Cell());
|
||||
row.getCells().add(gen.new Cell(null, null, (grp.mandatory ? "1" : "0")+"..1", "", null));
|
||||
row.getCells().add(gen.new Cell());
|
||||
row.getCells().add(gen.new Cell());
|
||||
prow.getSubRows().add(row);
|
||||
return row;
|
||||
}
|
||||
|
||||
public Cell genElementNameCell(HierarchicalTableGenerator gen, ElementDefinition element, String profileBaseFileName, boolean snapshot, String corePath,
|
||||
String imagePath, boolean root, boolean logicalModel, boolean allInvariants, StructureDefinition profile, Row typesRow, Row row, boolean hasDef,
|
||||
boolean ext, UnusedTracker used, String ref, String sName) throws IOException {
|
||||
|
@ -3985,7 +4127,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
if (root) {
|
||||
if (profile.getAbstract()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.addPiece(gen.new Piece(null, "This is an abstract profile", null));
|
||||
}
|
||||
}
|
||||
|
@ -3993,10 +4135,10 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "\""+buildJson(definition.getFixed())+"\"", null).addStyle("color: darkgreen")));
|
||||
} else {
|
||||
if (definition != null && definition.hasShort()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.addPiece(checkForNoChange(definition.getShortElement(), gen.new Piece(null, gt(definition.getShortElement()), null)));
|
||||
} else if (fallback != null && fallback.hasShort()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.addPiece(gen.new Piece(null, gt(fallback.getShortElement()), null).addStyle("opacity: 0.5"));
|
||||
}
|
||||
if (url != null) {
|
||||
|
@ -4041,7 +4183,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
if (definition.hasSlicing()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, translate("sd.table", "Slice")+": ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, describeSlice(definition.getSlicing()), null));
|
||||
}
|
||||
|
@ -4095,7 +4237,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
if (definition.hasFixed()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, translate("sd.table", "Fixed Value")+": ", null).addStyle("font-weight:bold")));
|
||||
if (!useTableForFixedValues || definition.getFixed().isPrimitive()) {
|
||||
String s = buildJson(definition.getFixed());
|
||||
|
@ -4113,7 +4255,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
c.getPieces().add(p);
|
||||
}
|
||||
} else if (definition.hasPattern()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, translate("sd.table", "Required Pattern")+": ", null).addStyle("font-weight:bold")));
|
||||
if (!useTableForFixedValues || definition.getPattern().isPrimitive())
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
|
||||
|
@ -4123,13 +4265,13 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
} else if (definition.hasExample()) {
|
||||
for (ElementDefinitionExampleComponent ex : definition.getExample()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, translate("sd.table", "Example")+("".equals("General")? "" : " "+ex.getLabel())+": ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, buildJson(ex.getValue()), null).addStyle("color: darkgreen")));
|
||||
}
|
||||
}
|
||||
if (definition.hasMaxLength() && definition.getMaxLength()!=0) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, "Max Length: ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, Integer.toString(definition.getMaxLength()), null).addStyle("color: darkgreen")));
|
||||
}
|
||||
|
@ -4367,7 +4509,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
if (definition.hasSlicing()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, "Slice: ", null).addStyle("font-weight:bold"));
|
||||
c.getPieces().add(gen.new Piece(null, describeSlice(definition.getSlicing()), null));
|
||||
}
|
||||
|
@ -4389,12 +4531,16 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
for (ElementDefinitionConstraintComponent inv : definition.getConstraint()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, inv.getKey()+": ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, inv.getHuman(), null)));
|
||||
if (inv.getHumanElement().hasExtension("http://hl7.org/fhir/StructureDefinition/rendering-markdown")) {
|
||||
c.addMarkdown(inv.getHumanElement().getExtensionString("http://hl7.org/fhir/StructureDefinition/rendering-markdown"));
|
||||
} else {
|
||||
c.getPieces().add(checkForNoChange(inv, gen.new Piece(null, inv.getHuman(), null)));
|
||||
}
|
||||
}
|
||||
if (definition.hasFixed()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(null, "Fixed Value: ", null).addStyle("font-weight:bold")));
|
||||
String s = buildJson(definition.getFixed());
|
||||
String link = null;
|
||||
|
@ -4402,18 +4548,18 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
link = pkp.getLinkForUrl(corePath, s);
|
||||
c.getPieces().add(checkForNoChange(definition.getFixed(), gen.new Piece(link, s, null).addStyle("color: darkgreen")));
|
||||
} else if (definition.hasPattern()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, "Required Pattern: ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(definition.getPattern(), gen.new Piece(null, buildJson(definition.getPattern()), null).addStyle("color: darkgreen")));
|
||||
} else if (definition.hasExample()) {
|
||||
for (ElementDefinitionExampleComponent ex : definition.getExample()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, "Example'"+("".equals("General")? "" : " "+ex.getLabel()+"'")+": ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, buildJson(ex.getValue()), null).addStyle("color: darkgreen")));
|
||||
}
|
||||
}
|
||||
if (definition.hasMaxLength() && definition.getMaxLength()!=0) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, "Max Length: ", null).addStyle("font-weight:bold")));
|
||||
c.getPieces().add(checkForNoChange(definition.getMaxLengthElement(), gen.new Piece(null, Integer.toString(definition.getMaxLength()), null).addStyle("color: darkgreen")));
|
||||
}
|
||||
|
@ -4434,14 +4580,14 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
if (definition.hasDefinition()) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, "Definition: ", null).addStyle("font-weight:bold"));
|
||||
c.addPiece(gen.new Piece("br"));
|
||||
c.addMarkdown(definition.getDefinition());
|
||||
// c.getPieces().add(checkForNoChange(definition.getCommentElement(), gen.new Piece(null, definition.getComment(), null)));
|
||||
}
|
||||
if (definition.getComment()!=null) {
|
||||
if (!c.getPieces().isEmpty()) c.addPiece(gen.new Piece("br"));
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, "Comments: ", null).addStyle("font-weight:bold"));
|
||||
c.addPiece(gen.new Piece("br"));
|
||||
c.addMarkdown(definition.getComment());
|
||||
|
@ -5935,6 +6081,64 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
|
||||
|
||||
public List<ElementChoiceGroup> readChoices(ElementDefinition ed, List<ElementDefinition> children) {
|
||||
List<ElementChoiceGroup> result = new ArrayList<>();
|
||||
for (ElementDefinitionConstraintComponent c : ed.getConstraint()) {
|
||||
ElementChoiceGroup grp = processConstraint(children, c);
|
||||
if (grp != null) {
|
||||
result.add(grp);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private ElementChoiceGroup processConstraint(List<ElementDefinition> children, ElementDefinitionConstraintComponent c) {
|
||||
if (!c.hasExpression()) {
|
||||
return null;
|
||||
}
|
||||
ExpressionNode expr = fpe.parse(c.getExpression());
|
||||
if (expr.getKind() != Kind.Group || expr.getOpNext() == null || !(expr.getOperation() == Operation.Equals || expr.getOperation() == Operation.LessOrEqual)) {
|
||||
return null;
|
||||
}
|
||||
ExpressionNode n1 = expr.getGroup();
|
||||
ExpressionNode n2 = expr.getOpNext();
|
||||
if (n2.getKind() != Kind.Constant || n2.getInner() != null || n2.getOpNext() != null || !"1".equals(n2.getConstant().primitiveValue())) {
|
||||
return null;
|
||||
}
|
||||
ElementChoiceGroup grp = new ElementChoiceGroup(c.getKey(), expr.getOperation() == Operation.Equals);
|
||||
while (n1 != null) {
|
||||
if (n1.getKind() != Kind.Name || n1.getInner() != null) {
|
||||
return null;
|
||||
}
|
||||
grp.elements.add(n1.getName());
|
||||
if (n1.getOperation() == null || n1.getOperation() == Operation.Union) {
|
||||
n1 = n1.getOpNext();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
int total = 0;
|
||||
for (String n : grp.elements) {
|
||||
boolean found = false;
|
||||
for (ElementDefinition child : children) {
|
||||
String name = tail(child.getPath());
|
||||
if (n.equals(name)) {
|
||||
found = true;
|
||||
if (!"0".equals(child.getMax())) {
|
||||
total++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (total <= 1) {
|
||||
return null;
|
||||
}
|
||||
return grp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -171,8 +171,9 @@ private Map<String, Object> userData;
|
|||
List<Property> children = new ArrayList<Property>();
|
||||
listChildren(children);
|
||||
for (Property c : children)
|
||||
if (c.getName().equals(name))
|
||||
if (c.getName().equals(name) || c.getName().equals(name+"[x]")) {
|
||||
return c;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,16 @@ import org.hl7.fhir.r5.model.Annotation;
|
|||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.BaseDateTimeType;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.CanonicalType;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ContactPoint;
|
||||
import org.hl7.fhir.r5.model.DataRequirement;
|
||||
import org.hl7.fhir.r5.model.DataRequirement.DataRequirementCodeFilterComponent;
|
||||
import org.hl7.fhir.r5.model.DataRequirement.DataRequirementDateFilterComponent;
|
||||
import org.hl7.fhir.r5.model.DataRequirement.DataRequirementSortComponent;
|
||||
import org.hl7.fhir.r5.model.DataRequirement.SortDirection;
|
||||
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
|
||||
import org.hl7.fhir.r5.model.DataType;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
|
@ -778,6 +784,102 @@ public class DataRenderer extends Renderer {
|
|||
x.addText(!p.hasEnd() ? "(ongoing)" : p.getEndElement().toHumanDisplay());
|
||||
}
|
||||
|
||||
public void renderDataRequirement(XhtmlNode x, DataRequirement dr) {
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
XhtmlNode td = tr.td().colspan("2");
|
||||
td.b().tx("Type");
|
||||
td.tx(": ");
|
||||
StructureDefinition sd = context.getWorker().fetchTypeDefinition(dr.getType().toCode());
|
||||
if (sd != null && sd.hasUserData("path")) {
|
||||
td.ah(sd.getUserString("path")).tx(dr.getType().toCode());
|
||||
} else {
|
||||
td.tx(dr.getType().toCode());
|
||||
}
|
||||
if (dr.hasProfile()) {
|
||||
td.tx(" (");
|
||||
boolean first = true;
|
||||
for (CanonicalType p : dr.getProfile()) {
|
||||
if (first) first = false; else td.tx(" | ");
|
||||
sd = context.getWorker().fetchResource(StructureDefinition.class, p.getValue());
|
||||
if (sd != null && sd.hasUserData("path")) {
|
||||
td.ah(sd.getUserString("path")).tx(sd.present());
|
||||
} else {
|
||||
td.tx(p.asStringValue());
|
||||
}
|
||||
}
|
||||
td.tx(")");
|
||||
}
|
||||
if (dr.hasSubject()) {
|
||||
tr = tbl.tr();
|
||||
td = tr.td().colspan("2");
|
||||
td.b().tx("Subject");
|
||||
if (dr.hasSubjectReference()) {
|
||||
renderReference(td, dr.getSubjectReference());
|
||||
} else {
|
||||
renderCodeableConcept(td, dr.getSubjectCodeableConcept());
|
||||
}
|
||||
}
|
||||
if (dr.hasCodeFilter() || dr.hasDateFilter()) {
|
||||
tr = tbl.tr().backgroundColor("#efefef");
|
||||
tr.td().tx("Filter");
|
||||
tr.td().tx("Value");
|
||||
}
|
||||
for (DataRequirementCodeFilterComponent cf : dr.getCodeFilter()) {
|
||||
tr = tbl.tr();
|
||||
if (cf.hasPath()) {
|
||||
tr.td().tx(cf.getPath());
|
||||
} else {
|
||||
tr.td().tx("Search on " +cf.getSearchParam());
|
||||
}
|
||||
if (cf.hasValueSet()) {
|
||||
td = tr.td();
|
||||
td.tx("In ValueSet ");
|
||||
render(td, cf.getValueSetElement());
|
||||
} else {
|
||||
boolean first = true;
|
||||
td = tr.td();
|
||||
td.tx("One of these codes: ");
|
||||
for (Coding c : cf.getCode()) {
|
||||
if (first) first = false; else td.tx(", ");
|
||||
render(td, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (DataRequirementDateFilterComponent cf : dr.getDateFilter()) {
|
||||
tr = tbl.tr();
|
||||
if (cf.hasPath()) {
|
||||
tr.td().tx(cf.getPath());
|
||||
} else {
|
||||
tr.td().tx("Search on " +cf.getSearchParam());
|
||||
}
|
||||
render(tr.td(), cf.getValue());
|
||||
}
|
||||
if (dr.hasSort() || dr.hasLimit()) {
|
||||
tr = tbl.tr();
|
||||
td = tr.td().colspan("2");
|
||||
if (dr.hasLimit()) {
|
||||
td.b().tx("Limit");
|
||||
td.tx(": ");
|
||||
td.tx(dr.getLimit());
|
||||
if (dr.hasSort()) {
|
||||
td.tx(", ");
|
||||
}
|
||||
}
|
||||
if (dr.hasSort()) {
|
||||
td.b().tx("Sort");
|
||||
td.tx(": ");
|
||||
boolean first = true;
|
||||
for (DataRequirementSortComponent p : dr.getSort()) {
|
||||
if (first) first = false; else td.tx(" | ");
|
||||
td.tx(p.getDirection() == SortDirection.ASCENDING ? "+" : "-");
|
||||
td.tx(p.getPath());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private String displayTiming(Timing s) throws FHIRException {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
if (s.hasCode())
|
||||
|
|
|
@ -31,13 +31,19 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
|||
|
||||
public class ParametersRenderer extends ResourceRenderer {
|
||||
|
||||
public ParametersRenderer(RenderingContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public ParametersRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||
super(context, rcontext);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean render(XhtmlNode x, Resource r) throws FHIRFormatError, DefinitionException, IOException, FHIRException, EOperationOutcome {
|
||||
x.h2().tx("Parameters");
|
||||
XhtmlNode tbl = x.table("grid");
|
||||
params(tbl, ((Parameters) r).getParameter(), 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -87,7 +93,7 @@ public class ParametersRenderer extends ResourceRenderer {
|
|||
}
|
||||
} else if (p.has("part")) {
|
||||
tr.td();
|
||||
PropertyWrapper pw = getProperty(p, "parameter");
|
||||
PropertyWrapper pw = getProperty(p, "part");
|
||||
paramsW(tbl, pw.getValues(), 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.hl7.fhir.r5.model.CodeableReference;
|
|||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ContactDetail;
|
||||
import org.hl7.fhir.r5.model.ContactPoint;
|
||||
import org.hl7.fhir.r5.model.DataRequirement;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Dosage;
|
||||
|
@ -82,6 +83,7 @@ import org.w3c.dom.Element;
|
|||
public class ProfileDrivenRenderer extends ResourceRenderer {
|
||||
|
||||
private Set<String> containedIds = new HashSet<>();
|
||||
private boolean hasExtensions;
|
||||
|
||||
public ProfileDrivenRenderer(RenderingContext context, ResourceContext rcontext) {
|
||||
super(context, rcontext);
|
||||
|
@ -108,12 +110,13 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
System.out.println("hah!");
|
||||
}
|
||||
containedIds.clear();
|
||||
hasExtensions = false;
|
||||
generateByProfile(r, sd, r.root(), sd.getSnapshot().getElement(), ed, context.getProfileUtilities().getChildList(sd, ed), x, r.fhirType(), false, 0);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
x.para().b().style("color: maroon").tx("Exception generating Narrative: "+e.getMessage());
|
||||
}
|
||||
return false;
|
||||
return hasExtensions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -378,6 +381,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
} else if (e instanceof Resource) {
|
||||
return;
|
||||
} else if (e instanceof DataRequirement) {
|
||||
DataRequirement p = (DataRequirement) e;
|
||||
renderDataRequirement(x, p);
|
||||
} else if (e instanceof ElementDefinition) {
|
||||
x.tx("todo-bundle");
|
||||
} else if (e != null && !(e instanceof Attachment) && !(e instanceof Narrative) && !(e instanceof Meta)) {
|
||||
|
@ -386,7 +392,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
throw new NotImplementedException("type "+e.getClass().getName()+" not handled yet, and no structure found");
|
||||
else
|
||||
generateByProfile(res, sd, ew, sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep(),
|
||||
getChildrenForPath(sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep().getPath()), x, path, showCodeDetails, indent + 1);
|
||||
getChildrenForPath(sd.getSnapshot().getElement(), sd.getSnapshot().getElementFirstRep().getPath()), x, e.fhirType(), showCodeDetails, indent + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -612,66 +618,99 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
for (PropertyWrapper p : splitExtensions(profile, e.children())) {
|
||||
if (p.hasValues()) {
|
||||
ElementDefinition child = getElementDefinition(children, path+"."+p.getName(), p);
|
||||
if (child == null) {
|
||||
child = p.getElementDefinition();
|
||||
}
|
||||
if (child != null) {
|
||||
Map<String, String> displayHints = readDisplayHints(child);
|
||||
if ("DomainResource.contained".equals(child.getBase().getPath())) {
|
||||
generateElementByProfile(res, profile, allElements, x, path, showCodeDetails, indent, p, child);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void generateElementByProfile(ResourceWrapper res, StructureDefinition profile, List<ElementDefinition> allElements, XhtmlNode x, String path,
|
||||
boolean showCodeDetails, int indent, PropertyWrapper p, ElementDefinition child) throws UnsupportedEncodingException, IOException, EOperationOutcome {
|
||||
Map<String, String> displayHints = readDisplayHints(child);
|
||||
if ("DomainResource.contained".equals(child.getBase().getPath())) {
|
||||
// if (p.getValues().size() > 0 && child != null) {
|
||||
// for (BaseWrapper v : p.getValues()) {
|
||||
// x.an(v.get("id").primitiveValue());
|
||||
// }
|
||||
// }
|
||||
} else if (!exemptFromRendering(child)) {
|
||||
List<ElementDefinition> grandChildren = getChildrenForPath(allElements, path+"."+p.getName());
|
||||
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
||||
if (p.getValues().size() > 0) {
|
||||
if (isPrimitive(child)) {
|
||||
XhtmlNode para = x.para();
|
||||
String name = p.getName();
|
||||
if (name.endsWith("[x]"))
|
||||
name = name.substring(0, name.length() - 3);
|
||||
if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) {
|
||||
para.b().addText(name);
|
||||
para.tx(": ");
|
||||
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||
XhtmlNode list = x.ul();
|
||||
for (BaseWrapper v : p.getValues())
|
||||
renderLeaf(res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent);
|
||||
} else {
|
||||
boolean first = true;
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
para.tx(", ");
|
||||
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (canDoTable(path, p, grandChildren)) {
|
||||
x.addTag(getHeader()).addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||
XhtmlNode tbl = x.table( "grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.td().tx("-"); // work around problem with empty table rows
|
||||
addColumnHeadings(tr, grandChildren);
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("*"); // work around problem with empty table rows
|
||||
addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
XhtmlNode bq = x.addTag("blockquote");
|
||||
bq.para().b().addText(p.getName());
|
||||
generateByProfile(res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1);
|
||||
}
|
||||
}
|
||||
} else if (!exemptFromRendering(child)) {
|
||||
if (isExtension(p)) {
|
||||
hasExtensions = true;
|
||||
}
|
||||
List<ElementDefinition> grandChildren = getChildrenForPath(allElements, path+"."+p.getName());
|
||||
filterGrandChildren(grandChildren, path+"."+p.getName(), p);
|
||||
if (p.getValues().size() > 0) {
|
||||
if (isPrimitive(child)) {
|
||||
XhtmlNode para = x.para();
|
||||
String name = p.getName();
|
||||
if (name.endsWith("[x]"))
|
||||
name = name.substring(0, name.length() - 3);
|
||||
if (showCodeDetails || !isDefaultValue(displayHints, p.getValues())) {
|
||||
para.b().addText(name);
|
||||
para.tx(": ");
|
||||
if (renderAsList(child) && p.getValues().size() > 1) {
|
||||
XhtmlNode list = x.ul();
|
||||
for (BaseWrapper v : p.getValues())
|
||||
renderLeaf(res, v, child, x, list.li(), false, showCodeDetails, displayHints, path, indent);
|
||||
} else {
|
||||
boolean first = true;
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (first)
|
||||
first = false;
|
||||
else
|
||||
para.tx(", ");
|
||||
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (canDoTable(path, p, grandChildren)) {
|
||||
x.addTag(getHeader()).addText(Utilities.capitalize(Utilities.camelCase(Utilities.pluralizeMe(p.getName()))));
|
||||
XhtmlNode tbl = x.table( "grid");
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.td().tx("-"); // work around problem with empty table rows
|
||||
addColumnHeadings(tr, grandChildren);
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
tr = tbl.tr();
|
||||
tr.td().tx("*"); // work around problem with empty table rows
|
||||
addColumnValues(res, tr, grandChildren, v, showCodeDetails, displayHints, path, indent);
|
||||
}
|
||||
}
|
||||
} else if (isExtension(p)) {
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
PropertyWrapper vp = v.getChildByName("value");
|
||||
PropertyWrapper ev = v.getChildByName("extension");
|
||||
if (vp.hasValues()) {
|
||||
BaseWrapper vv = vp.value();
|
||||
XhtmlNode para = x.para();
|
||||
para.b().addText(p.getStructure().present());
|
||||
para.tx(": ");
|
||||
renderLeaf(res, v, child, x, para, false, showCodeDetails, displayHints, path, indent);
|
||||
} else if (ev.hasValues()) {
|
||||
XhtmlNode bq = x.addTag("blockquote");
|
||||
bq.para().b().addText(isExtension(p) ? p.getStructure().present() : p.getName());
|
||||
for (BaseWrapper vv : ev.getValues()) {
|
||||
StructureDefinition ex = context.getWorker().fetchTypeDefinition("Extension");
|
||||
List<ElementDefinition> children = getChildrenForPath(ex.getSnapshot().getElement(), "Extension");
|
||||
generateByProfile(res, ex, vv, allElements, child, children, bq, "Extension", showCodeDetails, indent+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (BaseWrapper v : p.getValues()) {
|
||||
if (v != null) {
|
||||
XhtmlNode bq = x.addTag("blockquote");
|
||||
bq.para().b().addText(isExtension(p) ? p.getStructure().present() : p.getName());
|
||||
generateByProfile(res, profile, v, allElements, child, grandChildren, bq, path+"."+p.getName(), showCodeDetails, indent+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -699,6 +738,9 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
}
|
||||
|
||||
private boolean canDoTable(String path, PropertyWrapper p, List<ElementDefinition> grandChildren) {
|
||||
if (isExtension(p)) {
|
||||
return false;
|
||||
}
|
||||
for (ElementDefinition e : grandChildren) {
|
||||
List<PropertyWrapper> values = getValues(path, p, e);
|
||||
if (values.size() > 1 || !isPrimitive(e) || !canCollapse(e))
|
||||
|
@ -707,6 +749,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isExtension(PropertyWrapper p) {
|
||||
return p.getName().contains("extension[");
|
||||
}
|
||||
|
||||
|
||||
private boolean canCollapse(ElementDefinition e) {
|
||||
// we can collapse any data type
|
||||
|
@ -792,10 +838,10 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
|
|||
if (url.startsWith("http://hl7.org/fhir") && !url.startsWith("http://hl7.org/fhir/us"))
|
||||
throw new DefinitionException("unknown extension "+url);
|
||||
// System.out.println("unknown extension "+url);
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex));
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", p.getTypeCode(), p.getDefinition(), p.getMinCardinality(), p.getMaxCardinality(), ex), ed.getSnapshot().getElementFirstRep());
|
||||
} else {
|
||||
ElementDefinition def = ed.getSnapshot().getElement().get(0);
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", "Extension", def.getDefinition(), def.getMin(), def.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(def.getMax()), ex));
|
||||
pe = new PropertyWrapperDirect(this.context, new Property(p.getName()+"["+url+"]", "Extension", def.getDefinition(), def.getMin(), def.getMax().equals("*") ? Integer.MAX_VALUE : Integer.parseInt(def.getMax()), ex), ed.getSnapshot().getElementFirstRep());
|
||||
((PropertyWrapperDirect) pe).getWrapped().setStructure(ed);
|
||||
}
|
||||
results.add(pe);
|
||||
|
|
|
@ -72,6 +72,9 @@ public class RendererFactory {
|
|||
if ("OperationOutcome".equals(resourceName)) {
|
||||
return new OperationOutcomeRenderer(context);
|
||||
}
|
||||
if ("Parameters".equals(resourceName)) {
|
||||
return new ParametersRenderer(context);
|
||||
}
|
||||
return new ProfileDrivenRenderer(context);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||
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.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||
|
@ -28,6 +29,7 @@ public class BaseWrappers {
|
|||
public int getMinCardinality();
|
||||
public int getMaxCardinality();
|
||||
public StructureDefinition getStructure();
|
||||
public ElementDefinition getElementDefinition();
|
||||
public BaseWrapper value();
|
||||
public ResourceWrapper getAsResource();
|
||||
public String fhirType();
|
||||
|
@ -87,7 +89,7 @@ public class BaseWrappers {
|
|||
@Override
|
||||
public boolean has(String name) {
|
||||
for (PropertyWrapper p : children()) {
|
||||
if (p.getName().equals(name)) {
|
||||
if (p.getName().equals(name) || p.getName().equals(name+"[x]") ) {
|
||||
return p.hasValues();
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +99,7 @@ public class BaseWrappers {
|
|||
@Override
|
||||
public Base get(String name) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
for (PropertyWrapper p : children()) {
|
||||
if (p.getName().equals(name)) {
|
||||
if (p.getName().equals(name) || p.getName().equals(name+"[x]")) {
|
||||
if (p.hasValues()) {
|
||||
return p.getValues().get(0).getBase();
|
||||
} else {
|
||||
|
@ -111,7 +113,7 @@ public class BaseWrappers {
|
|||
@Override
|
||||
public List<BaseWrapper> children(String name) throws UnsupportedEncodingException, FHIRException, IOException {
|
||||
for (PropertyWrapper p : children()) {
|
||||
if (p.getName().equals(name)) {
|
||||
if (p.getName().equals(name) || p.getName().equals(name+"[x]")) {
|
||||
List<BaseWrapper> res = new ArrayList<>();
|
||||
for (BaseWrapper b : p.getValues()) {
|
||||
res.add(b);
|
||||
|
|
|
@ -206,6 +206,11 @@ public class DOMWrappers {
|
|||
return getTypeCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementDefinition getElementDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ResourceWrapperElement extends WrapperBaseImpl implements ResourceWrapper {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.util.List;
|
|||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Encounter;
|
||||
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
|
||||
import org.hl7.fhir.r5.model.Patient;
|
||||
|
@ -29,6 +30,7 @@ public class DirectWrappers {
|
|||
public static class PropertyWrapperDirect extends RendererWrapperImpl implements PropertyWrapper {
|
||||
private Property wrapped;
|
||||
private List<BaseWrapper> list;
|
||||
private ElementDefinition ed;
|
||||
|
||||
public PropertyWrapperDirect(RenderingContext context, Property wrapped) {
|
||||
super(context);
|
||||
|
@ -37,6 +39,14 @@ public class DirectWrappers {
|
|||
this.wrapped = wrapped;
|
||||
}
|
||||
|
||||
public PropertyWrapperDirect(RenderingContext context, Property wrapped, ElementDefinition ed) {
|
||||
super(context);
|
||||
if (wrapped == null)
|
||||
throw new Error("wrapped == null");
|
||||
this.wrapped = wrapped;
|
||||
this.ed = ed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return wrapped.getName();
|
||||
|
@ -106,6 +116,11 @@ public class DirectWrappers {
|
|||
public String fhirType() {
|
||||
return wrapped.getTypeCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementDefinition getElementDefinition() {
|
||||
return ed;
|
||||
}
|
||||
}
|
||||
|
||||
public static class BaseWrapperDirect extends WrapperBaseImpl implements BaseWrapper {
|
||||
|
|
|
@ -58,7 +58,7 @@ public class ElementWrappers {
|
|||
throw new FHIRException(e.getMessage(), e);
|
||||
}
|
||||
if (context.getParser() == null) {
|
||||
System.out.println("Noe version specific parser provided");
|
||||
System.out.println("No version specific parser provided");
|
||||
}
|
||||
if (context.getParser() == null) {
|
||||
throw new Error("No type parser provided to renderer context");
|
||||
|
@ -324,6 +324,11 @@ public class ElementWrappers {
|
|||
return getTypeCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ElementDefinition getElementDefinition() {
|
||||
return definition;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -319,6 +319,20 @@ public class FHIRPathEngine {
|
|||
}
|
||||
}
|
||||
|
||||
public FHIRPathEngine(IWorkerContext worker, ProfileUtilities utilities) {
|
||||
super();
|
||||
this.worker = worker;
|
||||
profileUtilities = utilities;
|
||||
for (StructureDefinition sd : worker.getStructures()) {
|
||||
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() != StructureDefinitionKind.LOGICAL) {
|
||||
allTypes.put(sd.getName(), sd);
|
||||
}
|
||||
if (sd.getDerivation() == TypeDerivationRule.SPECIALIZATION && sd.getKind() == StructureDefinitionKind.PRIMITIVETYPE) {
|
||||
primitiveTypes.add(sd.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- 3 methods to override in children -------------------------------------------------------
|
||||
// if you don't override, it falls through to the using the base reference implementation
|
||||
|
|
|
@ -104,17 +104,17 @@ public class NPMPackageGenerator {
|
|||
private NpmPackageIndexBuilder indexer;
|
||||
|
||||
|
||||
public NPMPackageGenerator(String destFile, String canonical, String url, PackageType kind, ImplementationGuide ig, Date date) throws FHIRException, IOException {
|
||||
public NPMPackageGenerator(String destFile, String canonical, String url, PackageType kind, ImplementationGuide ig, Date date, boolean notForPublication) throws FHIRException, IOException {
|
||||
super();
|
||||
this.destFile = destFile;
|
||||
start();
|
||||
List<String> fhirVersion = new ArrayList<>();
|
||||
for (Enumeration<FHIRVersion> v : ig.getFhirVersion())
|
||||
fhirVersion.add(v.asStringValue());
|
||||
buildPackageJson(canonical, kind, url, date, ig, fhirVersion);
|
||||
buildPackageJson(canonical, kind, url, date, ig, fhirVersion, notForPublication);
|
||||
}
|
||||
|
||||
public static NPMPackageGenerator subset(NPMPackageGenerator master, String destFile, String id, String name, Date date) throws FHIRException, IOException {
|
||||
public static NPMPackageGenerator subset(NPMPackageGenerator master, String destFile, String id, String name, Date date, boolean notForPublication) throws FHIRException, IOException {
|
||||
JsonObject p = master.packageJ.deepCopy();
|
||||
p.remove("name");
|
||||
p.addProperty("name", id);
|
||||
|
@ -122,24 +122,30 @@ public class NPMPackageGenerator {
|
|||
p.addProperty("type", PackageType.SUBSET.getCode());
|
||||
p.remove("title");
|
||||
p.addProperty("title", name);
|
||||
if (notForPublication) {
|
||||
p.addProperty("notForPublication", true);
|
||||
}
|
||||
|
||||
return new NPMPackageGenerator(destFile, p, date);
|
||||
return new NPMPackageGenerator(destFile, p, date, notForPublication);
|
||||
}
|
||||
|
||||
public NPMPackageGenerator(String destFile, String canonical, String url, PackageType kind, ImplementationGuide ig, Date date, List<String> fhirVersion) throws FHIRException, IOException {
|
||||
public NPMPackageGenerator(String destFile, String canonical, String url, PackageType kind, ImplementationGuide ig, Date date, List<String> fhirVersion, boolean notForPublication) throws FHIRException, IOException {
|
||||
super();
|
||||
this.destFile = destFile;
|
||||
start();
|
||||
buildPackageJson(canonical, kind, url, date, ig, fhirVersion);
|
||||
buildPackageJson(canonical, kind, url, date, ig, fhirVersion, notForPublication);
|
||||
}
|
||||
|
||||
public NPMPackageGenerator(String destFile, JsonObject npm, Date date) throws FHIRException, IOException {
|
||||
public NPMPackageGenerator(String destFile, JsonObject npm, Date date, boolean notForPublication) throws FHIRException, IOException {
|
||||
super();
|
||||
String dt = new SimpleDateFormat("yyyyMMddHHmmss").format(date);
|
||||
packageJ = npm;
|
||||
packageManifest = new JsonObject();
|
||||
packageManifest.addProperty("version", npm.get("version").getAsString());
|
||||
packageManifest.addProperty("date", dt);
|
||||
if (notForPublication) {
|
||||
packageManifest.addProperty("notForPublication", true);
|
||||
}
|
||||
npm.addProperty("date", dt);
|
||||
packageManifest.addProperty("name", npm.get("name").getAsString());
|
||||
this.destFile = destFile;
|
||||
|
@ -152,19 +158,23 @@ public class NPMPackageGenerator {
|
|||
}
|
||||
}
|
||||
|
||||
private void buildPackageJson(String canonical, PackageType kind, String web, Date date, ImplementationGuide ig, List<String> fhirVersion) throws FHIRException, IOException {
|
||||
private void buildPackageJson(String canonical, PackageType kind, String web, Date date, ImplementationGuide ig, List<String> fhirVersion, boolean notForPublication) throws FHIRException, IOException {
|
||||
String dtHuman = new SimpleDateFormat("EEE, MMM d, yyyy HH:mmZ", new Locale("en", "US")).format(date);
|
||||
String dt = new SimpleDateFormat("yyyyMMddHHmmss").format(date);
|
||||
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
if (!ig.hasPackageId())
|
||||
if (!ig.hasPackageId()) {
|
||||
b.append("packageId");
|
||||
if (!ig.hasVersion())
|
||||
}
|
||||
if (!ig.hasVersion()) {
|
||||
b.append("version");
|
||||
if (!ig.hasFhirVersion())
|
||||
}
|
||||
if (!ig.hasFhirVersion()) {
|
||||
b.append("fhirVersion");
|
||||
if (!ig.hasLicense())
|
||||
}
|
||||
if (!ig.hasLicense()) {
|
||||
b.append("license");
|
||||
}
|
||||
for (ImplementationGuideDependsOnComponent d : ig.getDependsOn()) {
|
||||
if (!d.hasVersion()) {
|
||||
b.append("dependsOn.version("+d.getUri()+")");
|
||||
|
@ -177,14 +187,20 @@ public class NPMPackageGenerator {
|
|||
npm.addProperty("tools-version", ToolsVersion.TOOLS_VERSION);
|
||||
npm.addProperty("type", kind.getCode());
|
||||
npm.addProperty("date", dt);
|
||||
if (ig.hasLicense())
|
||||
if (ig.hasLicense()) {
|
||||
npm.addProperty("license", ig.getLicense().toCode());
|
||||
}
|
||||
npm.addProperty("canonical", canonical);
|
||||
if (notForPublication) {
|
||||
npm.addProperty("notForPublication", true);
|
||||
}
|
||||
npm.addProperty("url", web);
|
||||
if (ig.hasTitle())
|
||||
if (ig.hasTitle()) {
|
||||
npm.addProperty("title", ig.getTitle());
|
||||
if (ig.hasDescription())
|
||||
}
|
||||
if (ig.hasDescription()) {
|
||||
npm.addProperty("description", ig.getDescription()+ " (built "+dtHuman+timezone()+")");
|
||||
}
|
||||
JsonArray vl = new JsonArray();
|
||||
|
||||
npm.add("fhirVersions", vl);
|
||||
|
@ -205,8 +221,9 @@ public class NPMPackageGenerator {
|
|||
dep.addProperty(d.getPackageId(), d.getVersion());
|
||||
}
|
||||
}
|
||||
if (ig.hasPublisher())
|
||||
if (ig.hasPublisher()) {
|
||||
npm.addProperty("author", ig.getPublisher());
|
||||
}
|
||||
JsonArray m = new JsonArray();
|
||||
for (ContactDetail t : ig.getContact()) {
|
||||
String email = email(t.getTelecom());
|
||||
|
|
|
@ -11,22 +11,32 @@ import javax.xml.parsers.ParserConfigurationException;
|
|||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager;
|
||||
import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
|
||||
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
||||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Base;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Questionnaire;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.RendererFactory;
|
||||
import org.hl7.fhir.r5.renderers.ResourceRenderer;
|
||||
import org.hl7.fhir.r5.renderers.utils.ElementWrappers;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ITypeParser;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.QuestionnaireRendererMode;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||
import org.hl7.fhir.r5.test.NarrativeGenerationTests.TestTypeParser;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.utilities.TerminologyServiceOptions;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
|
||||
import org.hl7.fhir.utilities.xml.XMLUtil;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
|
@ -40,6 +50,15 @@ import org.xml.sax.SAXException;
|
|||
|
||||
public class NarrativeGenerationTests {
|
||||
|
||||
public class TestTypeParser implements ITypeParser {
|
||||
|
||||
@Override
|
||||
public Base parseType(String xml, String type) throws FHIRFormatError, IOException, FHIRException {
|
||||
return new org.hl7.fhir.r5.formats.XmlParser().parseType(xml, type);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static final String WINDOWS = "WINDOWS";
|
||||
|
||||
private static final String HEADER = "<html><head>"+
|
||||
|
@ -57,11 +76,13 @@ public class NarrativeGenerationTests {
|
|||
public static class TestDetails {
|
||||
private String id;
|
||||
private boolean header;
|
||||
private boolean meta;
|
||||
|
||||
public TestDetails(Element test) {
|
||||
super();
|
||||
id = test.getAttribute("id");
|
||||
header = "true".equals(test.getAttribute("header"));
|
||||
meta = "true".equals(test.getAttribute("meta"));
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -72,6 +93,10 @@ public class NarrativeGenerationTests {
|
|||
return header;
|
||||
}
|
||||
|
||||
public boolean isMeta() {
|
||||
return meta;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static Stream<Arguments> data() throws ParserConfigurationException, IOException, FHIRFormatError, SAXException {
|
||||
|
@ -107,19 +132,30 @@ public class NarrativeGenerationTests {
|
|||
rc.setHeader(test.isHeader());
|
||||
rc.setDefinitionsTarget("test.html");
|
||||
rc.setTerminologyServiceOptions(TerminologyServiceOptions.defaults());
|
||||
IOUtils.copy(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-expected.xml"), new FileOutputStream(TestingUtilities.tempFile("narrative", test.getId() + "-expected.xml")));
|
||||
DomainResource source;
|
||||
if (TestingUtilities.findTestResource("r5", "narrative", test.getId() + "-input.json")) {
|
||||
source = (DomainResource) new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-input.json"));
|
||||
rc.setParser(new TestTypeParser());
|
||||
Resource source;
|
||||
if (TestingUtilities.findTestResource("r5", "narrative", test.getId() + ".json")) {
|
||||
source = (Resource) new JsonParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".json"));
|
||||
} else {
|
||||
source = (DomainResource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-input.xml"));
|
||||
source = (Resource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".xml"));
|
||||
}
|
||||
|
||||
XhtmlNode x = RendererFactory.factory(source, rc).build(source);
|
||||
String target = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".html"));
|
||||
String output = HEADER+new XhtmlComposer(true, true).compose(x)+FOOTER;
|
||||
TextFile.stringToFile(target, TestingUtilities.tempFile("narrative", test.getId() + ".target.html"));
|
||||
TextFile.stringToFile(output, TestingUtilities.tempFile("narrative", test.getId() + ".output.html"));
|
||||
Assertions.assertTrue(output.equals(target), "Output does not match expected");
|
||||
|
||||
if (test.isMeta()) {
|
||||
org.hl7.fhir.r5.elementmodel.Element e = Manager.parse(context, TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + ".xml"), FhirFormat.XML);
|
||||
x = RendererFactory.factory(source, rc).render(new ElementWrappers.ResourceWrapperMetaElement(rc, e));
|
||||
|
||||
target = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-meta.html"));
|
||||
output = HEADER+new XhtmlComposer(true).compose(x)+FOOTER;
|
||||
TextFile.stringToFile(output, TestingUtilities.tempFile("narrative", test.getId() + "-meta.output.html"));
|
||||
Assertions.assertTrue(output.equals(target), "Output does not match expected (meta)");
|
||||
}
|
||||
DomainResource target = (DomainResource) new XmlParser().parse(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-expected.xml"));
|
||||
RendererFactory.factory(source, rc).render(source);
|
||||
new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(TestingUtilities.tempFile("narrative", test.getId() + "-actual.xml")), source);
|
||||
source = (DomainResource) new XmlParser().parse(new FileInputStream(TestingUtilities.tempFile("narrative", test.getId() + "-actual.xml")));
|
||||
String html = HEADER+new XhtmlComposer(true).compose(source.getText().getDiv())+FOOTER;
|
||||
TextFile.stringToFile(html, TestingUtilities.tempFile("narrative", test.getId() + ".html"));
|
||||
Assertions.assertTrue(source.equalsDeep(target), "Output does not match expected");
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
|
|||
import org.hl7.fhir.r5.formats.JsonParser;
|
||||
import org.hl7.fhir.r5.formats.XmlParser;
|
||||
import org.hl7.fhir.r5.model.Bundle;
|
||||
import org.hl7.fhir.r5.model.DateTimeType;
|
||||
import org.hl7.fhir.r5.model.DomainResource;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.renderers.RendererFactory;
|
||||
|
@ -20,6 +21,7 @@ import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
|||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
|
||||
import org.hl7.fhir.r5.test.utils.TestingUtilities;
|
||||
import org.hl7.fhir.r5.utils.EOperationOutcome;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
public class ResourceRoundTripTests {
|
||||
|
@ -52,4 +54,5 @@ public class ResourceRoundTripTests {
|
|||
if (result == null)
|
||||
throw new FHIRException("Bundle was null");
|
||||
}
|
||||
|
||||
}
|
|
@ -1092,5 +1092,9 @@ public class NpmPackage {
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean isNotForPublication() {
|
||||
return JSONUtil.bool(npm, "notForPublication");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -741,6 +741,12 @@ public class XhtmlNode implements IBaseXhtml {
|
|||
}
|
||||
|
||||
|
||||
public XhtmlNode backgroundColor(String color) {
|
||||
style("background-color: "+color);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
2
pom.xml
2
pom.xml
|
@ -17,7 +17,7 @@
|
|||
|
||||
<properties>
|
||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||
<validator_test_case_version>1.1.35</validator_test_case_version>
|
||||
<validator_test_case_version>1.1.36-SNAPSHOT</validator_test_case_version>
|
||||
<junit_jupiter_version>5.6.2</junit_jupiter_version>
|
||||
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
||||
<jacoco_version>0.8.5</jacoco_version>
|
||||
|
|
Loading…
Reference in New Issue