Added support for rendering with differences between either base StructureDfeinition or parent StructureDefinition
This commit is contained in:
parent
b71d5ceac2
commit
a589f5fdf4
|
@ -2,6 +2,7 @@ package org.hl7.fhir.r5.conformance;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
|
@ -33,7 +34,27 @@ public class AdditionalBindingsRenderer {
|
||||||
private UsageContext usage;
|
private UsageContext usage;
|
||||||
private boolean any;
|
private boolean any;
|
||||||
private boolean unchanged;
|
private boolean unchanged;
|
||||||
|
private boolean matched;
|
||||||
|
private AdditionalBindingDetail compare;
|
||||||
|
private int count = 1;
|
||||||
|
private String getKey() {
|
||||||
|
// Todo: Consider extending this with content from usageContext if purpose isn't sufficiently differentiating
|
||||||
|
return purpose;
|
||||||
}
|
}
|
||||||
|
private void incrementCount() {
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
private void setCompare(AdditionalBindingDetail match) {
|
||||||
|
compare = match;
|
||||||
|
match.matched = true;
|
||||||
|
}
|
||||||
|
private boolean alreadyMatched() {
|
||||||
|
return matched;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String STYLE_UNCHANGED = "font-color: darkgray;";
|
||||||
|
private static String STYLE_REMOVED = STYLE_UNCHANGED + "text-decoration: line-through;";
|
||||||
|
|
||||||
private List<AdditionalBindingDetail> bindings = new ArrayList<>();
|
private List<AdditionalBindingDetail> bindings = new ArrayList<>();
|
||||||
private ProfileKnowledgeProvider pkp;
|
private ProfileKnowledgeProvider pkp;
|
||||||
|
@ -53,23 +74,68 @@ public class AdditionalBindingsRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void seeMaxBinding(Extension ext) {
|
public void seeMaxBinding(Extension ext) {
|
||||||
|
seeMaxBinding(ext, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seeMaxBinding(Extension ext, Extension compExt, boolean compare) {
|
||||||
|
seeBinding(ext, compExt, compare, "maximum");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void seeBinding(Extension ext, Extension compExt, boolean compare, String label) {
|
||||||
AdditionalBindingDetail abr = new AdditionalBindingDetail();
|
AdditionalBindingDetail abr = new AdditionalBindingDetail();
|
||||||
abr.purpose = "maximum";
|
abr.purpose = label;
|
||||||
abr.valueSet = ext.getValue().primitiveValue();
|
abr.valueSet = ext.getValue().primitiveValue();
|
||||||
|
if (compare) {
|
||||||
|
abr.unchanged = compExt!=null && ext.getValue().primitiveValue().equals(compExt.getValue().primitiveValue());
|
||||||
|
|
||||||
|
abr.compare = new AdditionalBindingDetail();
|
||||||
|
abr.compare.valueSet = compExt==null ? null : compExt.getValue().primitiveValue();
|
||||||
|
} else {
|
||||||
abr.unchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
abr.unchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
||||||
|
}
|
||||||
bindings.add(abr);
|
bindings.add(abr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void seeMinBinding(Extension ext) {
|
public void seeMinBinding(Extension ext) {
|
||||||
AdditionalBindingDetail abr = new AdditionalBindingDetail();
|
seeMinBinding(ext, null, false);
|
||||||
abr.purpose = "minimum";
|
}
|
||||||
abr.valueSet = ext.getValue().primitiveValue();
|
|
||||||
abr.unchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
public void seeMinBinding(Extension ext, Extension compExt, boolean compare) {
|
||||||
bindings.add(abr);
|
seeBinding(ext, compExt, compare, "minimum");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void seeAdditionalBindings(List<Extension> list) {
|
public void seeAdditionalBindings(List<Extension> list) {
|
||||||
|
seeAdditionalBindings(list, null, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void seeAdditionalBindings(List<Extension> list, List<Extension> compList, boolean compare) {
|
||||||
|
HashMap<String, AdditionalBindingDetail> compBindings = new HashMap<String, AdditionalBindingDetail>();
|
||||||
|
if (compare && compList!=null) {
|
||||||
|
for (Extension ext : compList) {
|
||||||
|
AdditionalBindingDetail abr = additionalBinding(ext);
|
||||||
|
while (compBindings.containsKey(abr.getKey()))
|
||||||
|
abr.incrementCount();
|
||||||
|
compBindings.put(abr.getKey(), abr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (Extension ext : list) {
|
for (Extension ext : list) {
|
||||||
|
AdditionalBindingDetail abr = additionalBinding(ext);
|
||||||
|
if (compare && compList!=null) {
|
||||||
|
AdditionalBindingDetail match = null;
|
||||||
|
do {
|
||||||
|
match = compBindings.get(abr.getKey());
|
||||||
|
if (abr.alreadyMatched())
|
||||||
|
abr.incrementCount();
|
||||||
|
} while (match!=null && !match.alreadyMatched());
|
||||||
|
if (match!=null)
|
||||||
|
abr.setCompare(match);
|
||||||
|
} else
|
||||||
|
bindings.add(abr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AdditionalBindingDetail additionalBinding(Extension ext) {
|
||||||
AdditionalBindingDetail abr = new AdditionalBindingDetail();
|
AdditionalBindingDetail abr = new AdditionalBindingDetail();
|
||||||
abr.purpose = ext.getExtensionString("purpose");
|
abr.purpose = ext.getExtensionString("purpose");
|
||||||
abr.valueSet = ext.getExtensionString("valueSet");
|
abr.valueSet = ext.getExtensionString("valueSet");
|
||||||
|
@ -77,8 +143,7 @@ public class AdditionalBindingsRenderer {
|
||||||
abr.usage = (ext.hasExtension("usage")) && ext.getExtensionByUrl("usage").hasValueUsageContext() ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
abr.usage = (ext.hasExtension("usage")) && ext.getExtensionByUrl("usage").hasValueUsageContext() ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
||||||
abr.any = "any".equals(ext.getExtensionString("scope"));
|
abr.any = "any".equals(ext.getExtensionString("scope"));
|
||||||
abr.unchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
abr.unchanged = ext.hasUserData(ProfileUtilities.DERIVATION_EQUALS);
|
||||||
bindings.add(abr);
|
return abr;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String render() throws IOException {
|
public String render() throws IOException {
|
||||||
|
@ -107,12 +172,11 @@ public class AdditionalBindingsRenderer {
|
||||||
boolean usage = false;
|
boolean usage = false;
|
||||||
boolean any = false;
|
boolean any = false;
|
||||||
for (AdditionalBindingDetail binding : bindings) {
|
for (AdditionalBindingDetail binding : bindings) {
|
||||||
doco = doco || (doDoco && binding.doco != null);
|
doco = doco || (doDoco && (binding.doco != null || (binding.compare!=null && binding.compare.doco!=null)));
|
||||||
usage = usage || binding.usage != null;
|
usage = usage || binding.usage != null || (binding.compare!=null && binding.compare.usage!=null);
|
||||||
any = any || binding.any;
|
any = any || binding.any || (binding.compare!=null && binding.compare.any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
|
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
|
||||||
children.add(tr);
|
children.add(tr);
|
||||||
tr.td().style("font-size: 11px").b().tx("Additional Bindings");
|
tr.td().style("font-size: 11px").b().tx("Additional Bindings");
|
||||||
|
@ -133,31 +197,55 @@ public class AdditionalBindingsRenderer {
|
||||||
}
|
}
|
||||||
children.add(tr);
|
children.add(tr);
|
||||||
BindingResolution br = pkp == null ? makeNullBr(binding) : pkp.resolveBinding(profile, binding.valueSet, path);
|
BindingResolution br = pkp == null ? makeNullBr(binding) : pkp.resolveBinding(profile, binding.valueSet, path);
|
||||||
|
BindingResolution compBr = null;
|
||||||
|
if (binding.compare!=null && binding.compare.valueSet!=null)
|
||||||
|
compBr = pkp == null ? makeNullBr(binding.compare) : pkp.resolveBinding(profile, binding.compare.valueSet, path);
|
||||||
|
|
||||||
|
XhtmlNode valueset = tr.td().style("font-size: 11px");
|
||||||
|
if (binding.compare!=null && binding.valueSet.equals(binding.compare.valueSet))
|
||||||
|
valueset.style(STYLE_UNCHANGED);
|
||||||
if (br.url != null) {
|
if (br.url != null) {
|
||||||
tr.td().style("font-size: 11px").ah(Utilities.isAbsoluteUrl(br.url) || !pkp.prependLinks() ? br.url : corePath+br.url, binding.valueSet).tx(br.display);
|
valueset.ah(determineUrl(br.url), binding.valueSet).tx(br.display);
|
||||||
} else {
|
} else {
|
||||||
tr.td().style("font-size: 11px").span(null, binding.valueSet).tx(br.display);
|
valueset.span(null, binding.valueSet).tx(br.display);
|
||||||
|
}
|
||||||
|
if (binding.compare!=null && binding.compare.valueSet!=null && !binding.valueSet.equals(binding.compare.valueSet)) {
|
||||||
|
valueset.br();
|
||||||
|
valueset = valueset.span(STYLE_REMOVED, null);
|
||||||
|
if (compBr.url != null) {
|
||||||
|
valueset.ah(determineUrl(compBr.url), binding.compare.valueSet).tx(compBr.display);
|
||||||
|
} else {
|
||||||
|
valueset.span(null, binding.compare.valueSet).tx(compBr.display);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
XhtmlNode purpose = tr.td().style("font-size: 11px");
|
||||||
|
if (binding.compare!=null && binding.purpose.equals(binding.compare.purpose))
|
||||||
|
purpose.style("font-color: darkgray");
|
||||||
|
renderPurpose(purpose, binding.purpose);
|
||||||
|
if (binding.compare!=null && binding.compare.purpose!=null && !binding.purpose.equals(binding.compare.purpose)) {
|
||||||
|
purpose.br();
|
||||||
|
purpose = purpose.span(STYLE_UNCHANGED, null);
|
||||||
|
renderPurpose(purpose, binding.compare.purpose);
|
||||||
}
|
}
|
||||||
renderPurpose(tr.td().style("font-size: 11px"), binding.purpose);
|
|
||||||
if (usage) {
|
if (usage) {
|
||||||
if (binding.usage != null) {
|
if (binding.usage != null) {
|
||||||
|
// TODO: This isn't rendered at all yet. Ideally, we want it to render with comparison...
|
||||||
new DataRenderer(context).render(tr.td(), binding.usage);
|
new DataRenderer(context).render(tr.td(), binding.usage);
|
||||||
} else {
|
} else {
|
||||||
tr.td();
|
tr.td();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (any) {
|
if (any) {
|
||||||
if (binding.any) {
|
String newRepeat = binding.any ? "Any repeats" : "All repeats";
|
||||||
tr.td().style("font-size: 11px").tx("Any repeat");
|
String oldRepeat = binding.compare!=null && binding.compare.any ? "Any repeats" : "All repeats";
|
||||||
} else {
|
compareString(tr.td().style("font-size: 11px"), newRepeat, oldRepeat);
|
||||||
tr.td().style("font-size: 11px").tx("All repeats");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (doco) {
|
if (doco) {
|
||||||
if (binding.doco != null) {
|
if (binding.doco != null) {
|
||||||
String d = md.processMarkdown("Binding.description", binding.doco);
|
String d = md.processMarkdown("Binding.description", binding.doco);
|
||||||
tr.td().style("font-size: 11px").innerHTML(d);
|
String oldD = binding.compare==null ? null : md.processMarkdown("Binding.description.compare", binding.compare.doco);
|
||||||
|
tr.td().style("font-size: 11px").innerHTML(compareHtml(d, oldD));
|
||||||
} else {
|
} else {
|
||||||
tr.td().style("font-size: 11px");
|
tr.td().style("font-size: 11px");
|
||||||
}
|
}
|
||||||
|
@ -165,6 +253,28 @@ public class AdditionalBindingsRenderer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private XhtmlNode compareString(XhtmlNode node, String newS, String oldS) {
|
||||||
|
if (oldS==null)
|
||||||
|
return node.tx(newS);
|
||||||
|
if (newS.equals(oldS))
|
||||||
|
return node.style(STYLE_UNCHANGED).tx(newS);
|
||||||
|
node.tx(newS);
|
||||||
|
node.br();
|
||||||
|
return node.span(STYLE_REMOVED,null).tx(oldS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String compareHtml(String newS, String oldS) {
|
||||||
|
if (oldS==null)
|
||||||
|
return newS;
|
||||||
|
if (newS.equals(oldS))
|
||||||
|
return "<span style=\"" + STYLE_UNCHANGED + "\">" + newS + "</span>";
|
||||||
|
return newS + "<br/><span style=\"" + STYLE_REMOVED + "\">" + oldS + "</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String determineUrl(String url) {
|
||||||
|
return Utilities.isAbsoluteUrl(url) || !pkp.prependLinks() ? url : corePath + url;
|
||||||
|
}
|
||||||
|
|
||||||
private void renderPurpose(XhtmlNode td, String purpose) {
|
private void renderPurpose(XhtmlNode td, String purpose) {
|
||||||
switch (purpose) {
|
switch (purpose) {
|
||||||
case "maximum":
|
case "maximum":
|
||||||
|
|
|
@ -325,7 +325,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
public static final int STATUS_ERROR = 3;
|
public static final int STATUS_ERROR = 3;
|
||||||
public static final int STATUS_FATAL = 4;
|
public static final int STATUS_FATAL = 4;
|
||||||
|
|
||||||
|
public static final String BASE_MODEL = "base.model";
|
||||||
|
public static final String BASE_PATH = "base.path";
|
||||||
public static final String DERIVATION_EQUALS = "derivation.equals";
|
public static final String DERIVATION_EQUALS = "derivation.equals";
|
||||||
public static final String DERIVATION_POINTER = "derived.pointer";
|
public static final String DERIVATION_POINTER = "derived.pointer";
|
||||||
public static final String IS_DERIVED = "derived.fact";
|
public static final String IS_DERIVED = "derived.fact";
|
||||||
|
@ -354,6 +355,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
private boolean wantFixDifferentialFirstElementType;
|
private boolean wantFixDifferentialFirstElementType;
|
||||||
private Set<String> masterSourceFileNames;
|
private Set<String> masterSourceFileNames;
|
||||||
private Map<ElementDefinition, List<ElementDefinition>> childMapCache = new HashMap<>();
|
private Map<ElementDefinition, List<ElementDefinition>> childMapCache = new HashMap<>();
|
||||||
|
private Map<String, Map<String, ElementDefinition>> sdMapCache = new HashMap<>();
|
||||||
|
|
||||||
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
|
public ProfileUtilities(IWorkerContext context, List<ValidationMessage> messages, ProfileKnowledgeProvider pkp, FHIRPathEngine fpe) {
|
||||||
super();
|
super();
|
||||||
|
@ -423,7 +425,21 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
String getLinkForUrl(String corePath, String s);
|
String getLinkForUrl(String corePath, String s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ElementDefinition getElementById(String structureCanonical, String id) {
|
||||||
|
Map<String, ElementDefinition> sdCache = sdMapCache.get(structureCanonical);
|
||||||
|
|
||||||
|
if (sdCache == null) {
|
||||||
|
StructureDefinition sd = (StructureDefinition) context.fetchResource(StructureDefinition.class, structureCanonical);
|
||||||
|
if (sd==null)
|
||||||
|
throw new FHIRException("Unable to retrieve StructureDefinition with URL " + structureCanonical);
|
||||||
|
sdCache = new HashMap<String, ElementDefinition>();
|
||||||
|
sdMapCache.put(structureCanonical, sdCache);
|
||||||
|
for (ElementDefinition e : sd.getSnapshot().getElement()) {
|
||||||
|
sdCache.put(e.getId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sdCache.get(id);
|
||||||
|
}
|
||||||
|
|
||||||
public List<ElementDefinition> getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
public List<ElementDefinition> getChildMap(StructureDefinition profile, ElementDefinition element) throws DefinitionException {
|
||||||
if (childMapCache .containsKey(element)) {
|
if (childMapCache .containsKey(element)) {
|
||||||
|
@ -497,7 +513,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
/**
|
/**
|
||||||
* Given a Structure, navigate to the element given by the path and return the direct children of that element
|
* Given a Structure, navigate to the element given by the path and return the direct children of that element
|
||||||
*
|
*
|
||||||
* @param structure The structure to navigate into
|
* @param profile The structure to navigate into
|
||||||
* @param path The path of the element within the structure to get the children for
|
* @param path The path of the element within the structure to get the children for
|
||||||
* @return A List containing the element children (all of them are Elements)
|
* @return A List containing the element children (all of them are Elements)
|
||||||
*/
|
*/
|
||||||
|
@ -608,10 +624,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
* Given a base (snapshot) profile structure, and a differential profile, generate a new snapshot profile
|
* Given a base (snapshot) profile structure, and a differential profile, generate a new snapshot profile
|
||||||
*
|
*
|
||||||
* @param base - the base structure on which the differential will be applied
|
* @param base - the base structure on which the differential will be applied
|
||||||
* @param differential - the differential to apply to the base
|
* @param derived - the differential to apply to the base
|
||||||
* @param url - where the base has relative urls for profile references, these need to be converted to absolutes by prepending this URL (e.g. the canonical URL)
|
* @param url - where the base has relative urls for profile references, these need to be converted to absolutes by prepending this URL (e.g. the canonical URL)
|
||||||
* @param webUrl - where the base has relative urls in markdown, these need to be converted to absolutes by prepending this URL (this is not the same as the canonical URL)
|
* @param webUrl - where the base has relative urls in markdown, these need to be converted to absolutes by prepending this URL (this is not the same as the canonical URL)
|
||||||
* @param trimDifferential - if this is true, then the snap short generator will remove any material in the element definitions that is not different to the base
|
|
||||||
* @return
|
* @return
|
||||||
* @throws FHIRException
|
* @throws FHIRException
|
||||||
* @throws DefinitionException
|
* @throws DefinitionException
|
||||||
|
@ -1133,7 +1148,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
// so we just copy it in
|
// so we just copy it in
|
||||||
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
updateConstraintSources(outcome, srcSD.getUrl());
|
updateConstraintSources(outcome, srcSD.getUrl());
|
||||||
markDerived(outcome);
|
markDerived(outcome);
|
||||||
if (resultPathBase == null)
|
if (resultPathBase == null)
|
||||||
|
@ -1280,7 +1295,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
if (res == null)
|
if (res == null)
|
||||||
res = outcome;
|
res = outcome;
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
if (diffMatches.get(0).hasSliceName()) {
|
if (diffMatches.get(0).hasSliceName()) {
|
||||||
outcome.setSliceName(diffMatches.get(0).getSliceName());
|
outcome.setSliceName(diffMatches.get(0).getSliceName());
|
||||||
if (!diffMatches.get(0).hasMin() && (diffMatches.size() > 1 || slicer == null || slicer.getSlicing().getRules() != SlicingRules.CLOSED) && !currentBase.hasSliceName()) {
|
if (!diffMatches.get(0).hasMin() && (diffMatches.size() > 1 || slicer == null || slicer.getSlicing().getRules() != SlicingRules.CLOSED) && !currentBase.hasSliceName()) {
|
||||||
|
@ -1543,7 +1558,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
// we're just going to accept the differential slicing at face value
|
// we're just going to accept the differential slicing at face value
|
||||||
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
|
|
||||||
if (!diffMatches.get(0).hasSlicing())
|
if (!diffMatches.get(0).hasSlicing())
|
||||||
outcome.setSlicing(makeExtensionSlicing());
|
outcome.setSlicing(makeExtensionSlicing());
|
||||||
|
@ -1618,7 +1633,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
// so we just copy it in
|
// so we just copy it in
|
||||||
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
markDerived(outcome);
|
markDerived(outcome);
|
||||||
if (resultPathBase == null)
|
if (resultPathBase == null)
|
||||||
resultPathBase = outcome.getPath();
|
resultPathBase = outcome.getPath();
|
||||||
|
@ -1655,6 +1670,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (!outcome.getPath().startsWith(resultPathBase))
|
if (!outcome.getPath().startsWith(resultPathBase))
|
||||||
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH_IN_PROFILE___VS_, profileName, outcome.getPath(), resultPathBase));
|
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH_IN_PROFILE___VS_, profileName, outcome.getPath(), resultPathBase));
|
||||||
result.getElement().add(outcome); // so we just copy it in
|
result.getElement().add(outcome); // so we just copy it in
|
||||||
|
outcome.setUserData(BASE_MODEL, srcSD.getUrl());
|
||||||
|
outcome.setUserData(BASE_PATH, resultPathBase);
|
||||||
baseCursor++;
|
baseCursor++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1815,7 +1832,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
ElementDefinition outcome = updateURLs(url, webUrl, currentBase.copy());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) {
|
if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) {
|
||||||
updateFromSlicing(outcome.getSlicing(), diffMatches.get(0).getSlicing());
|
updateFromSlicing(outcome.getSlicing(), diffMatches.get(0).getSlicing());
|
||||||
updateFromDefinition(outcome, diffMatches.get(0), profileName, closed, url, srcSD); // if there's no slice, we don't want to update the unsliced description
|
updateFromDefinition(outcome, diffMatches.get(0), profileName, closed, url, srcSD); // if there's no slice, we don't want to update the unsliced description
|
||||||
|
@ -1867,7 +1884,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
for (ElementDefinition baseItem : baseMatches) {
|
for (ElementDefinition baseItem : baseMatches) {
|
||||||
baseCursor = base.getElement().indexOf(baseItem);
|
baseCursor = base.getElement().indexOf(baseItem);
|
||||||
outcome = updateURLs(url, webUrl, baseItem.copy());
|
outcome = updateURLs(url, webUrl, baseItem.copy());
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
outcome.setSlicing(null);
|
outcome.setSlicing(null);
|
||||||
if (!outcome.getPath().startsWith(resultPathBase))
|
if (!outcome.getPath().startsWith(resultPathBase))
|
||||||
|
@ -1894,6 +1911,8 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
if (!outcome.getPath().startsWith(resultPathBase))
|
if (!outcome.getPath().startsWith(resultPathBase))
|
||||||
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH));
|
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH));
|
||||||
|
outcome.setUserData(BASE_PATH, outcome.getPath());
|
||||||
|
outcome.setUserData(BASE_MODEL, srcSD.getUrl());
|
||||||
result.getElement().add(outcome);
|
result.getElement().add(outcome);
|
||||||
baseCursor++;
|
baseCursor++;
|
||||||
}
|
}
|
||||||
|
@ -1923,7 +1942,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
outcome = updateURLs(url, webUrl, currentBase.copy());
|
outcome = updateURLs(url, webUrl, currentBase.copy());
|
||||||
// outcome = updateURLs(url, diffItem.copy());
|
// outcome = updateURLs(url, diffItem.copy());
|
||||||
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
outcome.setPath(fixedPathDest(contextPathDst, outcome.getPath(), redirector, contextPathSrc));
|
||||||
updateFromBase(outcome, currentBase);
|
updateFromBase(outcome, currentBase, srcSD.getUrl());
|
||||||
outcome.setSlicing(null);
|
outcome.setSlicing(null);
|
||||||
outcome.setMin(0); // we're in a slice, so it's only a mandatory if it's explicitly marked so
|
outcome.setMin(0); // we're in a slice, so it's only a mandatory if it's explicitly marked so
|
||||||
if (!outcome.getPath().startsWith(resultPathBase))
|
if (!outcome.getPath().startsWith(resultPathBase))
|
||||||
|
@ -2430,7 +2449,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void updateFromBase(ElementDefinition derived, ElementDefinition base) {
|
private void updateFromBase(ElementDefinition derived, ElementDefinition base, String baseProfileUrl) {
|
||||||
|
derived.setUserData(BASE_MODEL, baseProfileUrl);
|
||||||
|
derived.setUserData(BASE_PATH, base.getPath());
|
||||||
if (base.hasBase()) {
|
if (base.hasBase()) {
|
||||||
if (!derived.hasBase())
|
if (!derived.hasBase())
|
||||||
derived.setBase(new ElementDefinitionBaseComponent());
|
derived.setBase(new ElementDefinitionBaseComponent());
|
||||||
|
@ -3522,7 +3543,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (!child.getPath().endsWith(".id")) {
|
if (!child.getPath().endsWith(".id")) {
|
||||||
List<StructureDefinition> sdl = new ArrayList<>();
|
List<StructureDefinition> sdl = new ArrayList<>();
|
||||||
sdl.add(ed);
|
sdl.add(ed);
|
||||||
genElement(defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc);
|
genElement(defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc, "");
|
||||||
}
|
}
|
||||||
} else if (deep) {
|
} else if (deep) {
|
||||||
List<ElementDefinition> children = new ArrayList<ElementDefinition>();
|
List<ElementDefinition> children = new ArrayList<ElementDefinition>();
|
||||||
|
@ -4005,6 +4026,11 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
|
|
||||||
public XhtmlNode generateTable(String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath,
|
public XhtmlNode generateTable(String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath,
|
||||||
boolean logicalModel, boolean allInvariants, Set<String> outputTracker, boolean active, boolean mustSupport, RenderingContext rc) throws IOException, FHIRException {
|
boolean logicalModel, boolean allInvariants, Set<String> outputTracker, boolean active, boolean mustSupport, RenderingContext rc) throws IOException, FHIRException {
|
||||||
|
return generateTable(defFile, profile, diff, imageFolder, inlineGraphics, profileBaseFileName, snapshot, corePath, imagePath, logicalModel, allInvariants, outputTracker, active, mustSupport, rc, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public XhtmlNode generateTable(String defFile, StructureDefinition profile, boolean diff, String imageFolder, boolean inlineGraphics, String profileBaseFileName, boolean snapshot, String corePath, String imagePath,
|
||||||
|
boolean logicalModel, boolean allInvariants, Set<String> outputTracker, boolean active, boolean mustSupport, RenderingContext rc, String anchorPrefix) throws IOException, FHIRException {
|
||||||
assert(diff != snapshot);// check it's ok to get rid of one of these
|
assert(diff != snapshot);// check it's ok to get rid of one of these
|
||||||
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(imageFolder, inlineGraphics, true);
|
HierarchicalTableGenerator gen = new HierarchicalTableGenerator(imageFolder, inlineGraphics, true);
|
||||||
gen.setTranslator(getTranslator());
|
gen.setTranslator(getTranslator());
|
||||||
|
@ -4030,7 +4056,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (diff) {
|
if (diff) {
|
||||||
insertMissingSparseElements(list);
|
insertMissingSparseElements(list);
|
||||||
}
|
}
|
||||||
genElement(defFile == null ? null : defFile+"#", gen, model.getRows(), list.get(0), list, profiles, diff, profileBaseFileName, null, snapshot, corePath, imagePath, true, logicalModel, profile.getDerivation() == TypeDerivationRule.CONSTRAINT && usesMustSupport(list), allInvariants, null, mustSupport, rc);
|
genElement(defFile == null ? null : defFile+"#", gen, model.getRows(), list.get(0), list, profiles, diff, profileBaseFileName, null, snapshot, corePath, imagePath, true, logicalModel, profile.getDerivation() == TypeDerivationRule.CONSTRAINT && usesMustSupport(list), allInvariants, null, mustSupport, rc, anchorPrefix);
|
||||||
try {
|
try {
|
||||||
return gen.generate(model, imagePath, 0, outputTracker);
|
return gen.generate(model, imagePath, 0, outputTracker);
|
||||||
} catch (org.hl7.fhir.exceptions.FHIRException e) {
|
} catch (org.hl7.fhir.exceptions.FHIRException e) {
|
||||||
|
@ -4126,7 +4152,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
|
|
||||||
|
|
||||||
private Row genElement(String defPath, HierarchicalTableGenerator gen, List<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> profiles, boolean showMissing, String profileBaseFileName, Boolean extensions,
|
private Row genElement(String defPath, HierarchicalTableGenerator gen, List<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> profiles, boolean showMissing, String profileBaseFileName, Boolean extensions,
|
||||||
boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc) throws IOException, FHIRException {
|
boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc, String anchorPrefix) throws IOException, FHIRException {
|
||||||
Row originalRow = slicingRow;
|
Row originalRow = slicingRow;
|
||||||
StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1);
|
StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1);
|
||||||
Row typesRow = null;
|
Row typesRow = null;
|
||||||
|
@ -4188,7 +4214,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
row.setOpacity("0.5");
|
row.setOpacity("0.5");
|
||||||
}
|
}
|
||||||
UnusedTracker used = new UnusedTracker();
|
UnusedTracker used = new UnusedTracker();
|
||||||
String ref = defPath == null ? null : defPath + element.getId();
|
String ref = defPath == null ? null : defPath + anchorPrefix + element.getId();
|
||||||
String sName = tail(element.getPath());
|
String sName = tail(element.getPath());
|
||||||
if (element.hasSliceName())
|
if (element.hasSliceName())
|
||||||
sName = sName +":"+element.getSliceName();
|
sName = sName +":"+element.getSliceName();
|
||||||
|
@ -4263,7 +4289,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
Row childRow = chooseChildRowByGroup(gen, currRow, groups, child, element, isConstraintMode);
|
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))) {
|
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, rc);
|
currRow = genElement(defPath, gen, childRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport, rc, anchorPrefix);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean render(XhtmlNode x, StructureDefinition sd) throws FHIRFormatError, DefinitionException, IOException {
|
public boolean render(XhtmlNode x, StructureDefinition sd) throws FHIRFormatError, DefinitionException, IOException {
|
||||||
x.getChildNodes().add(context.getProfileUtilities().generateTable(context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, context.getSpecificationLink(), "", false, false, null, false, false, context));
|
x.getChildNodes().add(context.getProfileUtilities().generateTable(context.getDefinitionsTarget(), sd, true, context.getDestDir(), false, sd.getId(), false, context.getSpecificationLink(), "", false, false, null, false, false, context, ""));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue