rendering improvements for profile extensions
This commit is contained in:
parent
60fe0fd0f8
commit
2d0dcbb803
|
@ -204,9 +204,19 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
ALL_TYPES // allow any unknow profile
|
||||
}
|
||||
|
||||
private static final List<String> INHERITED_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-binding-style",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style");
|
||||
private static final List<String> NON_INHERITED_ED_URLS = Arrays.asList(
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-category",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-fmm",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-implements",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-explicit-type-name",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-security-category",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-wg",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-normative-version",
|
||||
"http://hl7.org/fhir/tools/StructureDefinition/obligation-profile",
|
||||
"http://hl7.org/fhir/StructureDefinition/structuredefinition-standards-status-reason",
|
||||
ToolingExtensions.EXT_OBLIGATION);
|
||||
|
||||
|
||||
public IWorkerContext getContext() {
|
||||
return this.context;
|
||||
|
@ -781,7 +791,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
slice.getFocus().setMin(count);
|
||||
} else {
|
||||
String msg = "The slice definition for "+slice.getFocus().getId()+" has a minimum of "+slice.getFocus().getMin()+" but the slices add up to a minimum of "+count;
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+slice.getFocus().getId(), msg, forPublication ? ValidationMessage.IssueSeverity.ERROR : ValidationMessage.IssueSeverity.INFORMATION));
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+slice.getFocus().getId(), msg, forPublication ? ValidationMessage.IssueSeverity.ERROR : ValidationMessage.IssueSeverity.INFORMATION).setIgnorableError(true));
|
||||
}
|
||||
}
|
||||
count = slice.checkMax();
|
||||
|
@ -801,12 +811,12 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
if (ed.hasSliceName() && !slices.containsKey(ed.getPath())) {
|
||||
String msg = "The element "+ed.getId()+" (["+i+"]) launches straight into slicing without the slicing being set up properly first";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+ed.getId(), msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+ed.getId(), msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true));
|
||||
}
|
||||
if (ed.hasSliceName() && slices.containsKey(ed.getPath())) {
|
||||
if (!slices.get(ed.getPath()).count(ed, ed.getSliceName())) {
|
||||
String msg = "Duplicate slice name "+ed.getSliceName()+" on "+ed.getId()+" (["+i+"])";
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+ed.getId(), msg, ValidationMessage.IssueSeverity.ERROR));
|
||||
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.VALUE, url+"#"+ed.getId(), msg, ValidationMessage.IssueSeverity.ERROR).setIgnorableError(true));
|
||||
}
|
||||
}
|
||||
i++;
|
||||
|
@ -886,7 +896,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
|
||||
private void copyInheritedExtensions(StructureDefinition base, StructureDefinition derived) {
|
||||
for (Extension ext : base.getExtension()) {
|
||||
if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !derived.hasExtension(ext.getUrl())) {
|
||||
if (!Utilities.existsInList(ext.getUrl(), NON_INHERITED_ED_URLS) && !derived.hasExtension(ext.getUrl())) {
|
||||
derived.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
|
@ -905,7 +915,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
} else {
|
||||
focus.getConstraint().addAll(ed.getConstraint());
|
||||
for (Extension ext : ed.getExtension()) {
|
||||
if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !focus.hasExtension(ext.getUrl())) {
|
||||
if (!Utilities.existsInList(ext.getUrl(), NON_INHERITED_ED_URLS) && !focus.hasExtension(ext.getUrl())) {
|
||||
focus.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
|
@ -2159,8 +2169,14 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
// hack workaround for problem in R5 snapshots
|
||||
List<Extension> elist = dest.getExtensionsByUrl(ToolingExtensions.EXT_TRANSLATABLE);
|
||||
if (elist.size() == 2) {
|
||||
dest.getExtension().remove(elist.get(1));
|
||||
}
|
||||
|
||||
for (Extension ext : source.getExtension()) {
|
||||
if (Utilities.existsInList(ext.getUrl(), INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) {
|
||||
if (!Utilities.existsInList(ext.getUrl(), NON_INHERITED_ED_URLS) && !dest.hasExtension(ext.getUrl())) {
|
||||
dest.getExtension().add(ext.copy());
|
||||
}
|
||||
}
|
||||
|
@ -2576,14 +2592,16 @@ public class ProfileUtilities extends TranslatingUtilities {
|
|||
dest.setBinding(null);
|
||||
}
|
||||
|
||||
// finally, we copy any extensions from source to dest
|
||||
for (Extension ex : derived.getExtension()) {
|
||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ex.getUrl(), derivedSrc);
|
||||
if (sd == null || sd.getSnapshot() == null || sd.getSnapshot().getElementFirstRep().getMax().equals("1")) {
|
||||
ToolingExtensions.removeExtension(dest, ex.getUrl());
|
||||
}
|
||||
dest.addExtension(ex.copy());
|
||||
}
|
||||
// // finally, we copy any extensions from source to dest
|
||||
//no, we already did.
|
||||
// for (Extension ex : derived.getExtension()) {
|
||||
// !
|
||||
// StructureDefinition sd = context.fetchResource(StructureDefinition.class, ex.getUrl(), derivedSrc);
|
||||
// if (sd == null || sd.getSnapshot() == null || sd.getSnapshot().getElementFirstRep().getMax().equals("1")) {
|
||||
// ToolingExtensions.removeExtension(dest, ex.getUrl());
|
||||
// }
|
||||
// dest.addExtension(ex.copy());
|
||||
// }
|
||||
}
|
||||
if (dest.hasFixed()) {
|
||||
checkTypeOk(dest, dest.getFixed().fhirType(), srcSD, "fixed");
|
||||
|
|
|
@ -227,7 +227,7 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
|
|||
// new XmlParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path("[tmp]", "snapshot", tail(sd.getUrl())+".xml")), sd);
|
||||
} catch (Exception e) {
|
||||
if (!isSuppressDebugMessages()) {
|
||||
System.out.println("Unable to generate snapshot for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage());
|
||||
System.out.println("Unable to generate snapshot @2 for "+tail(sd.getUrl()) +" from "+tail(sd.getBaseDefinition())+" because "+e.getMessage());
|
||||
if (context.getLogger().isDebugLogging()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -288,8 +288,13 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
|
|||
}
|
||||
pu.generateSnapshot(sd, p, p.getUrl(), sd.getUserString("webroot"), p.getName());
|
||||
for (ValidationMessage msg : msgs) {
|
||||
if ((!ignoreProfileErrors && msg.getLevel() == ValidationMessage.IssueSeverity.ERROR) || msg.getLevel() == ValidationMessage.IssueSeverity.FATAL)
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___ELEMENT__ERROR_GENERATING_SNAPSHOT_, p.getName(), p.getUrl(), msg.getLocation(), msg.getMessage()));
|
||||
if ((!ignoreProfileErrors && msg.getLevel() == ValidationMessage.IssueSeverity.ERROR) || msg.getLevel() == ValidationMessage.IssueSeverity.FATAL) {
|
||||
if (!msg.isIgnorableError()) {
|
||||
throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___ELEMENT__ERROR_GENERATING_SNAPSHOT_, p.getName(), p.getUrl(), msg.getLocation(), msg.getMessage()));
|
||||
} else {
|
||||
System.err.println(msg.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!p.hasSnapshot())
|
||||
throw new FHIRException(context.formatMessage(I18nConstants.PROFILE___ERROR_GENERATING_SNAPSHOT, p.getName(), p.getUrl()));
|
||||
|
|
|
@ -508,6 +508,7 @@ public interface IWorkerContext {
|
|||
* @throws Exception
|
||||
*/
|
||||
public <T extends Resource> T fetchResource(Class<T> class_, String uri);
|
||||
public <T extends Resource> T fetchResourceRaw(Class<T> class_, String uri);
|
||||
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
|
||||
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference) throws FHIRException;
|
||||
public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version);
|
||||
|
|
|
@ -548,7 +548,6 @@ public class Coding extends DataType implements IBaseCoding, ICompositeType, ICo
|
|||
return base;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(Coding other) {
|
||||
return other.hasCode() && this.hasCode() && other.hasSystem() && this.hasSystem() && this.getCode().equals(other.getCode()) && this.getSystem().equals(other.getSystem()) ;
|
||||
|
|
|
@ -660,6 +660,10 @@ public class Identifier extends DataType implements ICompositeType {
|
|||
, period, assigner);
|
||||
}
|
||||
|
||||
public boolean matches(Identifier other) {
|
||||
return hasSystem() && hasValue() && getSystem().matches(other.getSystem()) && getValue().matches(other.getValue());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -252,4 +252,9 @@ public abstract class PrimitiveType<T> extends DataType implements IPrimitiveTyp
|
|||
public String fpValue() {
|
||||
return primitiveValue();
|
||||
}
|
||||
|
||||
public boolean matches(String other) {
|
||||
return other != null && other.equals(asStringValue());
|
||||
}
|
||||
|
||||
}
|
|
@ -7080,7 +7080,9 @@ public QuestionnaireItemComponent getQuestion(String linkId) {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// end addition
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -489,6 +489,29 @@ The type is the Canonical URL of Resource Definition that is the type this refer
|
|||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean matches(Reference value) {
|
||||
if (value.hasReference() || hasReference()) {
|
||||
if (!(value.hasReference() && hasReference())) {
|
||||
return false;
|
||||
}
|
||||
if (!reference.matches(value.getReference())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (value.hasIdentifier() || hasIdentifier()) {
|
||||
if (!(value.hasIdentifier() && hasIdentifier())) {
|
||||
return false;
|
||||
}
|
||||
if (!identifier.matches(value.getIdentifier())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// end addition
|
||||
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package org.hl7.fhir.r5.conformance;
|
||||
package org.hl7.fhir.r5.renderers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -20,10 +20,7 @@ import org.hl7.fhir.r5.model.PrimitiveType;
|
|||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.UsageContext;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.CodeResolver;
|
||||
import org.hl7.fhir.r5.renderers.CodeResolver.CodeResolution;
|
||||
import org.hl7.fhir.r5.renderers.DataRenderer;
|
||||
import org.hl7.fhir.r5.renderers.IMarkdownProcessor;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.utils.PublicationHacker;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
@ -79,6 +76,7 @@ public class AdditionalBindingsRenderer {
|
|||
isUnchanged = isUnchanged && ((purpose==null && compare.purpose==null) || purpose.equals(compare.purpose));
|
||||
isUnchanged = isUnchanged && ((valueSet==null && compare.valueSet==null) || valueSet.equals(compare.valueSet));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((usage==null && compare.usage==null) || usage.equals(compare.usage));
|
||||
return isUnchanged;
|
||||
}
|
|
@ -13,10 +13,13 @@ import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
|
|||
import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.SystemRestfulInteraction;
|
||||
import org.hl7.fhir.r5.model.CapabilityStatement.TypeRestfulInteraction;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class CapabilityStatementRenderer extends ResourceRenderer {
|
||||
|
@ -99,20 +102,12 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
|
|||
if (hasSupProf) {
|
||||
profCell.br();
|
||||
profCell.addText("Additional supported profiles:");
|
||||
for (CanonicalType sp: r.getSupportedProfile()) {
|
||||
profCell.br();
|
||||
profCell.nbsp().nbsp();
|
||||
profCell.ah(sp.getValue()).addText(sp.getValue());
|
||||
}
|
||||
renderSupportedProfiles(profCell, r);
|
||||
}
|
||||
}
|
||||
else { //Case of only supported profiles
|
||||
profCell.addText("Supported profiles:");
|
||||
for (CanonicalType sp: r.getSupportedProfile()) {
|
||||
profCell.br();
|
||||
profCell.nbsp().nbsp();
|
||||
profCell.ah(sp.getValue()).addText(sp.getValue());
|
||||
}
|
||||
renderSupportedProfiles(profCell, r);
|
||||
}
|
||||
//Show capabilities
|
||||
tr.td().addText(showOp(r, TypeRestfulInteraction.READ));
|
||||
|
@ -135,6 +130,48 @@ public class CapabilityStatementRenderer extends ResourceRenderer {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void renderSupportedProfiles(XhtmlNode profCell, CapabilityStatementRestResourceComponent r) throws IOException {
|
||||
for (CanonicalType sp: r.getSupportedProfile()) {
|
||||
profCell.br();
|
||||
profCell.nbsp().nbsp();
|
||||
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, sp.getValue());
|
||||
if (sd != null) {
|
||||
profCell.ah(sd.getWebPath()).addText(sd.present());
|
||||
} else {
|
||||
profCell.ah(sp.getValue()).addText(sp.getValue());
|
||||
}
|
||||
}
|
||||
if (r.hasExtension(ToolingExtensions.EXT_PROFILE_MAPPING)) {
|
||||
profCell.br();
|
||||
profCell.b().tx("Profile Mapping");
|
||||
XhtmlNode tbl = profCell.table("grid");
|
||||
boolean doco = false;
|
||||
for (Extension ext : r.getExtensionsByUrl(ToolingExtensions.EXT_PROFILE_MAPPING)) {
|
||||
doco = doco || ext.hasExtension("documentation");
|
||||
}
|
||||
XhtmlNode tr = tbl.tr();
|
||||
tr.th().tx("Criteria");
|
||||
tr.th().tx("Profile");
|
||||
if (doco) {
|
||||
tr.th().tx("Criteria");
|
||||
}
|
||||
for (Extension ext : r.getExtensionsByUrl(ToolingExtensions.EXT_PROFILE_MAPPING)) {
|
||||
tr = tbl.tr();
|
||||
tr.td().code().tx(ToolingExtensions.readStringExtension(ext, "search"));
|
||||
String url = ToolingExtensions.readStringExtension(ext, "profile");
|
||||
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, url);
|
||||
if (sd != null) {
|
||||
tr.td().code().ah(sd.getWebPath()).tx(sd.present());
|
||||
} else {
|
||||
tr.td().code().tx(url);
|
||||
}
|
||||
if (doco) {
|
||||
tr.td().code().markdown(ToolingExtensions.readStringExtension(ext, "documentation"), "documentation");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void describe(XhtmlNode x, CapabilityStatement cs) {
|
||||
x.tx(display(cs));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.hl7.fhir.r5.terminologies.CodeSystemUtilities.CodeSystemNavigator;
|
|||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.LoincLinker;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.i18n.I18nConstants;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
|
||||
public class CodeSystemRenderer extends TerminologyRenderer {
|
||||
|
@ -141,10 +142,10 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
|
||||
private String sentenceForContent(CodeSystemContentMode mode, CodeSystem cs) {
|
||||
switch (mode) {
|
||||
case COMPLETE: return "This code system <param name='cs'/> defines the following code<if test='code-count != 1'>s</if>:";
|
||||
case EXAMPLE: return "This code system <param name='cs'/> provides some example code<if test='code-count != 1'>s</if>:";
|
||||
case FRAGMENT: return "This code system <param name='cs'/> provides a fragment that includes following code<if test='code-count != 1'>s</if>:";
|
||||
case NOTPRESENT: return "This code system <param name='cs'/> defines codes, but no codes are represented here";
|
||||
case COMPLETE: return context.getContext().formatMessage(I18nConstants.RND_CS_CONTENT_COMPLETE);
|
||||
case EXAMPLE: return context.getContext().formatMessage(I18nConstants.RND_CS_CONTENT_EXAMPLE);
|
||||
case FRAGMENT: return context.getContext().formatMessage(I18nConstants.RND_CS_CONTENT_FRAGMENT);
|
||||
case NOTPRESENT: return context.getContext().formatMessage(I18nConstants.RND_CS_CONTENT_NOTPRESENT);
|
||||
case SUPPLEMENT:
|
||||
boolean properties = CodeSystemUtilities.hasProperties(cs);
|
||||
boolean designations = CodeSystemUtilities.hasDesignations(cs);
|
||||
|
@ -158,7 +159,7 @@ public class CodeSystemRenderer extends TerminologyRenderer {
|
|||
} else {
|
||||
features = "features"; // ?
|
||||
}
|
||||
return "This code system <param name='cs'/> defines "+features+" on the following code<if test='code-count != 1'>s</if>:";
|
||||
return context.getContext().formatMessage(I18nConstants.RND_CS_CONTENT_SUPPLEMENT, features);
|
||||
}
|
||||
throw new FHIRException("Unknown CodeSystemContentMode mode");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,437 @@
|
|||
package org.hl7.fhir.r5.renderers;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.conformance.profile.BindingResolution;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileKnowledgeProvider;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
|
||||
import org.hl7.fhir.r5.model.ActorDefinition;
|
||||
import org.hl7.fhir.r5.model.CodeSystem;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition;
|
||||
import org.hl7.fhir.r5.model.Extension;
|
||||
import org.hl7.fhir.r5.model.PrimitiveType;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.r5.model.UsageContext;
|
||||
import org.hl7.fhir.r5.model.ValueSet;
|
||||
import org.hl7.fhir.r5.renderers.CodeResolver.CodeResolution;
|
||||
import org.hl7.fhir.r5.renderers.ObligationsRenderer.ObligationDetail;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.utils.PublicationHacker;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
import org.hl7.fhir.utilities.MarkDownProcessor;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Cell;
|
||||
import org.hl7.fhir.utilities.xhtml.HierarchicalTableGenerator.Piece;
|
||||
import org.hl7.fhir.utilities.xhtml.NodeType;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlComposer;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||
import org.hl7.fhir.utilities.xhtml.XhtmlNodeList;
|
||||
|
||||
public class ObligationsRenderer {
|
||||
public static class ObligationDetail {
|
||||
private String code;
|
||||
private List<String> elementIds = new ArrayList<>();
|
||||
private String actorId;
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private String filter;
|
||||
private String filterDesc;
|
||||
private List<UsageContext> usage = new ArrayList<>();
|
||||
private boolean isUnchanged = false;
|
||||
private boolean matched = false;
|
||||
private boolean removed = false;
|
||||
private ValueSet vs;
|
||||
|
||||
private ObligationDetail compare;
|
||||
private int count = 1;
|
||||
|
||||
public ObligationDetail(Extension ext) {
|
||||
this.code = ext.getExtensionString("code");
|
||||
this.actorId = ext.getExtensionString("actorId");
|
||||
this.doco = ext.getExtensionString("documentation");
|
||||
this.docoShort = ext.getExtensionString("shortDoco");
|
||||
this.filter = ext.getExtensionString("filter");
|
||||
this.filterDesc = ext.getExtensionString("filter-desc");
|
||||
for (Extension usage : ext.getExtensionsByUrl("usage")) {
|
||||
this.usage.add(usage.getValueUsageContext());
|
||||
}
|
||||
this.isUnchanged = ext.hasUserData(ProfileUtilities.UD_DERIVATION_EQUALS);
|
||||
}
|
||||
|
||||
private String getKey() {
|
||||
// Todo: Consider extending this with content from usageContext if purpose isn't sufficiently differentiating
|
||||
return code + Integer.toString(count);
|
||||
}
|
||||
|
||||
private void incrementCount() {
|
||||
count++;
|
||||
}
|
||||
private void setCompare(ObligationDetail match) {
|
||||
compare = match;
|
||||
match.matched = true;
|
||||
}
|
||||
private boolean alreadyMatched() {
|
||||
return matched;
|
||||
}
|
||||
public String getDoco(boolean full) {
|
||||
return full ? doco : docoShort;
|
||||
}
|
||||
public String getCode() {
|
||||
return code;
|
||||
}
|
||||
public boolean unchanged() {
|
||||
if (!isUnchanged)
|
||||
return false;
|
||||
if (compare==null)
|
||||
return true;
|
||||
isUnchanged = true;
|
||||
isUnchanged = isUnchanged && ((code==null && compare.code==null) || code.equals(compare.code));
|
||||
isUnchanged = elementIds.equals(compare.elementIds);
|
||||
isUnchanged = isUnchanged && ((actorId==null && compare.actorId==null) || actorId.equals(compare.actorId));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((filter==null && compare.filter==null) || filter.equals(compare.filter));
|
||||
isUnchanged = isUnchanged && ((filterDesc==null && compare.filterDesc==null) || filterDesc.equals(compare.filterDesc));
|
||||
isUnchanged = isUnchanged && ((usage==null && compare.usage==null) || usage.equals(compare.usage));
|
||||
return isUnchanged;
|
||||
}
|
||||
|
||||
public boolean hasFilter() {
|
||||
return filter != null;
|
||||
}
|
||||
|
||||
public boolean hasUsage() {
|
||||
return !usage.isEmpty();
|
||||
}
|
||||
|
||||
public String getFilterDesc() {
|
||||
return filterDesc;
|
||||
}
|
||||
|
||||
public String getFilter() {
|
||||
return filter;
|
||||
}
|
||||
|
||||
public List<UsageContext> getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public boolean hasActor() {
|
||||
return actorId != null;
|
||||
}
|
||||
|
||||
public boolean hasActor(String id) {
|
||||
return id.equals(actorId);
|
||||
}
|
||||
}
|
||||
|
||||
private static String STYLE_UNCHANGED = "opacity: 0.5;";
|
||||
private static String STYLE_REMOVED = STYLE_UNCHANGED + "text-decoration: line-through;";
|
||||
|
||||
private List<ObligationDetail> obligations = new ArrayList<>();
|
||||
private String corePath;
|
||||
private StructureDefinition profile;
|
||||
private String path;
|
||||
private RenderingContext context;
|
||||
private IMarkdownProcessor md;
|
||||
private CodeResolver cr;
|
||||
|
||||
public ObligationsRenderer(String corePath, StructureDefinition profile, String path, RenderingContext context, IMarkdownProcessor md, CodeResolver cr) {
|
||||
this.corePath = corePath;
|
||||
this.profile = profile;
|
||||
this.path = path;
|
||||
this.context = context;
|
||||
this.md = md;
|
||||
this.cr = cr;
|
||||
}
|
||||
|
||||
|
||||
public void seeObligations(ElementDefinition element, String id) {
|
||||
seeObligations(element.getExtension(), null, false, id);
|
||||
}
|
||||
|
||||
public void seeObligations(List<Extension> list) {
|
||||
seeObligations(list, null, false, "$all");
|
||||
}
|
||||
|
||||
public void seeObligations(List<Extension> list, List<Extension> compList, boolean compare, String id) {
|
||||
HashMap<String, ObligationDetail> compBindings = new HashMap<String, ObligationDetail>();
|
||||
if (compare && compList!=null) {
|
||||
for (Extension ext : compList) {
|
||||
ObligationDetail abr = obligationDetail(ext);
|
||||
if (compBindings.containsKey(abr.getKey())) {
|
||||
abr.incrementCount();
|
||||
}
|
||||
compBindings.put(abr.getKey(), abr);
|
||||
}
|
||||
}
|
||||
|
||||
for (Extension ext : list) {
|
||||
ObligationDetail obd = obligationDetail(ext);
|
||||
if (("$all".equals(id) && !obd.hasActor()) || (obd.hasActor(id))) {
|
||||
if (compare && compList!=null) {
|
||||
ObligationDetail match = null;
|
||||
do {
|
||||
match = compBindings.get(obd.getKey());
|
||||
if (obd.alreadyMatched())
|
||||
obd.incrementCount();
|
||||
} while (match!=null && obd.alreadyMatched());
|
||||
if (match!=null)
|
||||
obd.setCompare(match);
|
||||
obligations.add(obd);
|
||||
if (obd.compare!=null)
|
||||
compBindings.remove(obd.compare.getKey());
|
||||
} else
|
||||
obligations.add(obd);
|
||||
}
|
||||
}
|
||||
for (ObligationDetail b: compBindings.values()) {
|
||||
b.removed = true;
|
||||
obligations.add(b);
|
||||
}
|
||||
}
|
||||
|
||||
protected ObligationDetail obligationDetail(Extension ext) {
|
||||
ObligationDetail abr = new ObligationDetail(ext);
|
||||
return abr;
|
||||
}
|
||||
|
||||
public String render() throws IOException {
|
||||
if (obligations.isEmpty()) {
|
||||
return "";
|
||||
} else {
|
||||
XhtmlNode tbl = new XhtmlNode(NodeType.Element, "table");
|
||||
tbl.attribute("class", "grid");
|
||||
renderTable(tbl.getChildNodes(), true);
|
||||
return new XhtmlComposer(false).compose(tbl);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderTable(HierarchicalTableGenerator gen, Cell c) throws FHIRFormatError, DefinitionException, IOException {
|
||||
if (obligations.isEmpty()) {
|
||||
return;
|
||||
} else {
|
||||
Piece piece = gen.new Piece("table").attr("class", "grid");
|
||||
c.getPieces().add(piece);
|
||||
renderTable(piece.getChildren(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderList(HierarchicalTableGenerator gen, Cell c) throws FHIRFormatError, DefinitionException, IOException {
|
||||
if (obligations.size() > 0) {
|
||||
Piece p = gen.new Piece(null);
|
||||
c.addPiece(p);
|
||||
if (obligations.size() == 1) {
|
||||
renderObligationLI(p.getChildren(), obligations.get(0));
|
||||
} else {
|
||||
XhtmlNode ul = p.getChildren().ul();
|
||||
for (ObligationDetail ob : obligations) {
|
||||
renderObligationLI(ul.li().getChildNodes(), ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renderObligationLI(XhtmlNodeList children, ObligationDetail ob) throws IOException {
|
||||
renderCode(children, ob.getCode());
|
||||
if (ob.hasFilter() || ob.hasUsage()) {
|
||||
children.tx(" (");
|
||||
boolean ffirst = !ob.hasFilter();
|
||||
if (ob.hasFilter()) {
|
||||
children.span(null, ob.getFilterDesc()).code().tx(ob.getFilter());
|
||||
}
|
||||
for (UsageContext uc : ob.getUsage()) {
|
||||
if (ffirst) ffirst = false; else children.tx(",");
|
||||
if (!uc.getCode().is("http://terminology.hl7.org/CodeSystem/usage-context-type", "jurisdiction")) {
|
||||
children.tx(displayForUsage(uc.getCode()));
|
||||
children.tx("=");
|
||||
}
|
||||
CodeResolution ccr = this.cr.resolveCode(uc.getValueCodeableConcept());
|
||||
children.ah(ccr.getLink(), ccr.getHint()).tx(ccr.getDisplay());
|
||||
}
|
||||
children.tx(")");
|
||||
}
|
||||
// usage
|
||||
// filter
|
||||
// process
|
||||
}
|
||||
|
||||
|
||||
public void renderTable(List<XhtmlNode> children, boolean fullDoco) throws FHIRFormatError, DefinitionException, IOException {
|
||||
boolean doco = false;
|
||||
boolean usage = false;
|
||||
boolean actor = false;
|
||||
boolean filter = false;
|
||||
for (ObligationDetail binding : obligations) {
|
||||
actor = actor || binding.actorId!=null || (binding.compare!=null && binding.compare.actorId !=null);
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || !binding.usage.isEmpty() || (binding.compare!=null && !binding.compare.usage.isEmpty());
|
||||
filter = filter || binding.filter != null || (binding.compare!=null && binding.compare.filter!=null);
|
||||
}
|
||||
|
||||
XhtmlNode tr = new XhtmlNode(NodeType.Element, "tr");
|
||||
children.add(tr);
|
||||
tr.td().style("font-size: 11px").b().tx("Obligations");
|
||||
if (actor) {
|
||||
tr.td().style("font-size: 11px").tx("Actor");
|
||||
}
|
||||
if (usage) {
|
||||
tr.td().style("font-size: 11px").tx("Usage");
|
||||
}
|
||||
if (doco) {
|
||||
tr.td().style("font-size: 11px").tx("Documentation");
|
||||
}
|
||||
if (filter) {
|
||||
tr.td().style("font-size: 11px").tx("Filter");
|
||||
}
|
||||
for (ObligationDetail ob : obligations) {
|
||||
tr = new XhtmlNode(NodeType.Element, "tr");
|
||||
if (ob.unchanged()) {
|
||||
tr.style(STYLE_REMOVED);
|
||||
} else if (ob.removed) {
|
||||
tr.style(STYLE_REMOVED);
|
||||
}
|
||||
children.add(tr);
|
||||
|
||||
XhtmlNode code = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.code.equals(ob.compare.code))
|
||||
code.style("font-color: darkgray");
|
||||
renderCode(code.getChildNodes(), ob.code);
|
||||
if (ob.compare!=null && ob.compare.code != null && !ob.code.equals(ob.compare.code)) {
|
||||
code.br();
|
||||
code = code.span(STYLE_UNCHANGED, null);
|
||||
renderCode(code.getChildNodes(), ob.compare.code);
|
||||
}
|
||||
if (actor) {
|
||||
|
||||
ActorDefinition ad = context.getContext().fetchResource(ActorDefinition.class, ob.actorId);
|
||||
ActorDefinition compAd = null;
|
||||
if (ob.compare!=null && ob.compare.actorId!=null) {
|
||||
compAd = context.getContext().fetchResource(ActorDefinition.class, ob.compare.actorId);
|
||||
}
|
||||
|
||||
XhtmlNode actorId = tr.td().style("font-size: 11px");
|
||||
if (ob.compare!=null && ob.actorId.equals(ob.compare.actorId))
|
||||
actorId.style(STYLE_UNCHANGED);
|
||||
if (ad != null && ad.hasWebPath()) {
|
||||
actorId.ah(ad.getWebPath(), ob.actorId).tx(ad.present());
|
||||
} else if (ad != null) {
|
||||
actorId.span(null, ob.actorId).tx(ad.present());
|
||||
}
|
||||
|
||||
if (ob.compare!=null && ob.compare.actorId!=null && !ob.actorId.equals(ob.compare.actorId)) {
|
||||
actorId.br();
|
||||
actorId = actorId.span(STYLE_REMOVED, null);
|
||||
if (compAd != null) {
|
||||
if (compAd.hasWebPath()) {
|
||||
actorId.ah(compAd.getWebPath(), ob.compare.actorId).tx(compAd.present());
|
||||
} else {
|
||||
actorId.span(null, ob.compare.actorId).tx(compAd.present());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (usage) {
|
||||
if (ob.usage != null) {
|
||||
boolean first = true;
|
||||
XhtmlNode td = tr.td();
|
||||
for (UsageContext u : ob.usage) {
|
||||
if (first) first = false; else td.tx(", ");
|
||||
new DataRenderer(context).render(td, u);
|
||||
}
|
||||
} else {
|
||||
tr.td();
|
||||
}
|
||||
}
|
||||
if (doco) {
|
||||
if (ob.doco != null) {
|
||||
String d = fullDoco ? md.processMarkdown("Obligation.documentation", ob.doco) : ob.docoShort;
|
||||
String oldD = ob.compare==null ? null : fullDoco ? md.processMarkdown("Binding.description.compare", ob.compare.doco) : ob.compare.docoShort;
|
||||
tr.td().style("font-size: 11px").innerHTML(compareHtml(d, oldD));
|
||||
} else {
|
||||
tr.td().style("font-size: 11px");
|
||||
}
|
||||
}
|
||||
|
||||
if (filter) {
|
||||
if (ob.filter != null) {
|
||||
String d = "<code>"+ob.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.filterDesc) : "");
|
||||
String oldD = ob.compare==null ? null : "<code>"+ob.compare.filter+"</code>" + (fullDoco ? md.processMarkdown("Binding.description", ob.compare.filterDesc) : "");
|
||||
tr.td().style("font-size: 11px").innerHTML(compareHtml(d, oldD));
|
||||
} else {
|
||||
tr.td().style("font-size: 11px");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 void renderCode(XhtmlNodeList children, String codeExpr) {
|
||||
if (codeExpr != null) {
|
||||
boolean first = true;
|
||||
String[] codes = codeExpr.split("\\+");
|
||||
for (String code : codes) {
|
||||
if (first) first = false; else children.tx(" & ");
|
||||
int i = code.indexOf(":");
|
||||
if (i > -1) {
|
||||
String c = code.substring(0, i);
|
||||
code = code.substring(i+1);
|
||||
children.b().tx(c.toUpperCase());
|
||||
children.tx(":");
|
||||
}
|
||||
CodeResolution cr = this.cr.resolveCode("http://hl7.org/fhir/tools/CodeSystem/obligation", code);
|
||||
code = code.replace("will-", "").replace("can-", "");
|
||||
if (cr.getLink() != null) {
|
||||
children.ah(cr.getLink(), cr.getHint()).tx(code);
|
||||
} else {
|
||||
children.span(null, cr.getHint()).tx(code);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
children.span(null, "No Obligation Code?").tx("??");
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasObligations() {
|
||||
return !obligations.isEmpty();
|
||||
}
|
||||
|
||||
private String displayForUsage(Coding c) {
|
||||
if (c.hasDisplay()) {
|
||||
return c.getDisplay();
|
||||
}
|
||||
if ("http://terminology.hl7.org/CodeSystem/usage-context-type".equals(c.getSystem())) {
|
||||
return c.getCode();
|
||||
}
|
||||
return c.getCode();
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,6 @@ import org.apache.commons.lang3.StringUtils;
|
|||
import org.hl7.fhir.exceptions.DefinitionException;
|
||||
import org.hl7.fhir.exceptions.FHIRException;
|
||||
import org.hl7.fhir.exceptions.FHIRFormatError;
|
||||
import org.hl7.fhir.r5.conformance.AdditionalBindingsRenderer;
|
||||
import org.hl7.fhir.r5.conformance.profile.BindingResolution;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileKnowledgeProvider;
|
||||
import org.hl7.fhir.r5.conformance.profile.ProfileUtilities;
|
||||
|
@ -59,7 +58,7 @@ import org.hl7.fhir.r5.model.UriType;
|
|||
import org.hl7.fhir.r5.model.UsageContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.BaseWrappers.ResourceWrapper;
|
||||
import org.hl7.fhir.r5.renderers.CodeResolver.CodeResolution;
|
||||
import org.hl7.fhir.r5.renderers.StructureDefinitionRenderer.ObligationWrapper;
|
||||
import org.hl7.fhir.r5.renderers.ObligationsRenderer.ObligationDetail;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.GenerationRules;
|
||||
import org.hl7.fhir.r5.renderers.utils.RenderingContext.KnownLinkType;
|
||||
|
@ -86,68 +85,68 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNodeList;
|
|||
|
||||
public class StructureDefinitionRenderer extends ResourceRenderer {
|
||||
|
||||
public class ObligationWrapper {
|
||||
|
||||
private Extension ext;
|
||||
|
||||
public ObligationWrapper(Extension ext) {
|
||||
this.ext = ext;
|
||||
}
|
||||
|
||||
public boolean hasActor() {
|
||||
return ext.hasExtension("actor");
|
||||
}
|
||||
|
||||
public boolean hasActor(String id) {
|
||||
return ext.hasExtension("actor") && id.equals(ext.getExtensionByUrl("actor").getValue().primitiveValue());
|
||||
}
|
||||
|
||||
public Coding getCode() {
|
||||
Extension code = ext.getExtensionByUrl("code");
|
||||
if (code != null && code.hasValueCoding()) {
|
||||
return code.getValueCoding();
|
||||
}
|
||||
if (code != null && code.hasValueCodeType()) {
|
||||
return new Coding().setSystem("http://hl7.org/fhir/tools/CodeSystem/obligation").setCode(code.getValueCodeType().primitiveValue());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasFilter() {
|
||||
return ext.hasExtension("filter");
|
||||
}
|
||||
|
||||
public String getFilter() {
|
||||
Extension code = ext.getExtensionByUrl("filter");
|
||||
if (code != null && code.getValue() != null) {
|
||||
return code.getValue().primitiveValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasUsage() {
|
||||
return ext.hasExtension("usage");
|
||||
}
|
||||
|
||||
public String getFilterDocumentation() {
|
||||
Extension code = ext.getExtensionByUrl("filter-desc");
|
||||
if (code != null && code.getValue() != null) {
|
||||
return code.getValue().primitiveValue();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<UsageContext> getUsage() {
|
||||
List<UsageContext> usage = new ArrayList<>();
|
||||
for (Extension u : ext.getExtensionsByUrl("usage" )) {
|
||||
if (u.hasValueUsageContext()) {
|
||||
usage.add(u.getValueUsageContext());
|
||||
}
|
||||
}
|
||||
return usage;
|
||||
}
|
||||
|
||||
}
|
||||
// public class ObligationWrapper {
|
||||
//
|
||||
// private Extension ext;
|
||||
//
|
||||
// public ObligationWrapper(Extension ext) {
|
||||
// this.ext = ext;
|
||||
// }
|
||||
//
|
||||
// public boolean hasActor() {
|
||||
// return ext.hasExtension("actor");
|
||||
// }
|
||||
//
|
||||
// public boolean hasActor(String id) {
|
||||
// return ext.hasExtension("actor") && id.equals(ext.getExtensionByUrl("actor").getValue().primitiveValue());
|
||||
// }
|
||||
//
|
||||
// public Coding getCode() {
|
||||
// Extension code = ext.getExtensionByUrl("obligation");
|
||||
// if (code != null && code.hasValueCoding()) {
|
||||
// return code.getValueCoding();
|
||||
// }
|
||||
// if (code != null && code.hasValueCodeType()) {
|
||||
// return new Coding().setSystem("http://hl7.org/fhir/tools/CodeSystem/obligation").setCode(code.getValueCodeType().primitiveValue());
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public boolean hasFilter() {
|
||||
// return ext.hasExtension("filter");
|
||||
// }
|
||||
//
|
||||
// public String getFilter() {
|
||||
// Extension code = ext.getExtensionByUrl("filter");
|
||||
// if (code != null && code.getValue() != null) {
|
||||
// return code.getValue().primitiveValue();
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public boolean hasUsage() {
|
||||
// return ext.hasExtension("usage");
|
||||
// }
|
||||
//
|
||||
// public String getFilterDocumentation() {
|
||||
// Extension code = ext.getExtensionByUrl("filter-desc");
|
||||
// if (code != null && code.getValue() != null) {
|
||||
// return code.getValue().primitiveValue();
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// public List<UsageContext> getUsage() {
|
||||
// List<UsageContext> usage = new ArrayList<>();
|
||||
// for (Extension u : ext.getExtensionsByUrl("usage" )) {
|
||||
// if (u.hasValueUsageContext()) {
|
||||
// usage.add(u.getValueUsageContext());
|
||||
// }
|
||||
// }
|
||||
// return usage;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
@ -621,7 +620,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
genElementBindings(gen, element, columns, row, profile, corePath);
|
||||
break;
|
||||
case OBLIGATIONS:
|
||||
genElementObligations(gen, element, columns, row);
|
||||
genElementObligations(gen, element, columns, row, corePath, profile);
|
||||
break;
|
||||
case SUMMARY:
|
||||
genElementCells(gen, element, profileBaseFileName, snapshot, corePath, imagePath, root, logicalModel, allInvariants, profile, typesRow, row, hasDef, ext, used, ref, sName, nc, mustSupport, true, rc);
|
||||
|
@ -729,91 +728,16 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
return slicingRow;
|
||||
}
|
||||
|
||||
private void genElementObligations(HierarchicalTableGenerator gen, ElementDefinition element, List<Column> columns, Row row) throws IOException {
|
||||
private void genElementObligations(HierarchicalTableGenerator gen, ElementDefinition element, List<Column> columns, Row row, String corePath, StructureDefinition profile) throws IOException {
|
||||
for (Column col : columns) {
|
||||
Cell gc = gen.new Cell();
|
||||
row.getCells().add(gc);
|
||||
List<ObligationWrapper> obligations = collectObligations(element, col.id);
|
||||
if (obligations.size() > 0) {
|
||||
Piece p = gen.new Piece(null);
|
||||
gc.addPiece(p);
|
||||
if (obligations.size() == 1) {
|
||||
renderObligation(p.getChildren(), obligations.get(0));
|
||||
} else {
|
||||
XhtmlNode ul = p.getChildren().ul();
|
||||
for (ObligationWrapper ob : obligations) {
|
||||
renderObligation(ul.li().getChildNodes(), ob);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ObligationsRenderer obr = new ObligationsRenderer(corePath, profile, element.getPath(), context, null, this);
|
||||
obr.seeObligations(element, col.id);
|
||||
obr.renderList(gen, gc);
|
||||
}
|
||||
}
|
||||
|
||||
private List<ObligationWrapper> collectObligations(ElementDefinition element, String id) {
|
||||
List<ObligationWrapper> res = new ArrayList<>();
|
||||
for (Extension ext : element.getExtensionsByUrl("http://hl7.org/fhir/tools/StructureDefinition/obligation")) {
|
||||
ObligationWrapper ob = new ObligationWrapper(ext);
|
||||
if (("$all".equals(id) && !ob.hasActor()) || (ob.hasActor(id))) {
|
||||
res.add(ob);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void renderObligation(XhtmlNodeList children, ObligationWrapper ob) throws IOException {
|
||||
if ("http://hl7.org/fhir/tools/CodeSystem/obligation".equals(ob.getCode().getSystem())) {
|
||||
boolean first = true;
|
||||
String[] codes = ob.getCode().getCode().split("\\+");
|
||||
for (String code : codes) {
|
||||
if (first) first = false; else children.tx(" & ");
|
||||
int i = code.indexOf(":");
|
||||
if (i > -1) {
|
||||
String c = code.substring(0, i);
|
||||
code = code.substring(i+1);
|
||||
children.b().tx(c.toUpperCase());
|
||||
children.tx(":");
|
||||
}
|
||||
CodeResolution cr = resolveCode("http://hl7.org/fhir/tools/CodeSystem/obligation", code);
|
||||
code = code.replace("will-", "").replace("can-", "");
|
||||
if (cr.getLink() != null) {
|
||||
children.ah(cr.getLink(), cr.getHint()).tx(code);
|
||||
} else {
|
||||
children.span(null, cr.getHint()).tx(code);
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
CodeResolution cr = resolveCode(ob.getCode());
|
||||
if (cr.getLink() != null) {
|
||||
children.ah(cr.getLink(), cr.getHint()).tx(cr.getDisplay());
|
||||
} else {
|
||||
children.span(null, cr.getHint()).tx(cr.getDisplay());
|
||||
}
|
||||
}
|
||||
if (ob.hasFilter() || ob.hasUsage()) {
|
||||
children.tx(" (");
|
||||
boolean ffirst = !ob.hasFilter();
|
||||
if (ob.hasFilter()) {
|
||||
children.span(null, ob.getFilterDocumentation()).code().tx(ob.getFilter());
|
||||
}
|
||||
for (UsageContext uc : ob.getUsage()) {
|
||||
if (ffirst) ffirst = false; else children.tx(",");
|
||||
if (!uc.getCode().is("http://terminology.hl7.org/CodeSystem/usage-context-type", "jurisdiction")) {
|
||||
children.tx(displayForUsage(uc.getCode()));
|
||||
children.tx("=");
|
||||
}
|
||||
CodeResolution ccr = resolveCode(uc.getValueCodeableConcept());
|
||||
children.ah(ccr.getLink(), ccr.getHint()).tx(ccr.getDisplay());
|
||||
}
|
||||
children.tx(")");
|
||||
}
|
||||
// usage
|
||||
// filter
|
||||
// process
|
||||
}
|
||||
|
||||
|
||||
private String displayForUsage(Coding c) {
|
||||
if (c.hasDisplay()) {
|
||||
return c.getDisplay();
|
||||
|
@ -1229,7 +1153,6 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
c.getPieces().add(gen.new Piece(null, "This type can be bound to a value set using the ", null));
|
||||
c.getPieces().add(gen.new Piece(null, ToolingExtensions.readStringExtension(profile, ToolingExtensions.EXT_BINDING_STYLE), null));
|
||||
c.getPieces().add(gen.new Piece(null, " binding style", null));
|
||||
|
||||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_IMPLIED_PREFIX)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
|
@ -1251,6 +1174,13 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_DATE_FORMAT)) {
|
||||
String df = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_DATE_FORMAT);
|
||||
if (df != null) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.getPieces().add(gen.new Piece(null, "Date Format: "+df, null));
|
||||
}
|
||||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_ID_EXPECTATION)) {
|
||||
String ide = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_ID_EXPECTATION);
|
||||
if (ide.equals("optional")) {
|
||||
|
@ -1314,7 +1244,7 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_JSON_PROP_KEY)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_EMPTY);
|
||||
String code = ToolingExtensions.readStringExtension(definition, ToolingExtensions.EXT_JSON_PROP_KEY);
|
||||
c.getPieces().add(gen.new Piece(null, "JSON: Represented as a single JSON Object with named properties using the value of the "+code+" child as the key", null));
|
||||
}
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_TYPE_SPEC)) {
|
||||
|
@ -1337,6 +1267,34 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (root) {
|
||||
if (ToolingExtensions.readBoolExtension(profile, ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
c.addPiece(gen.new Piece(null, "This is an obligation profile that only contains obligations and additional bindings", null).addStyle("font-weight:bold"));
|
||||
}
|
||||
for (Extension ext : profile.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION_INHERITS)) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
String iu = ext.getValue().primitiveValue();
|
||||
c.addPiece(gen.new Piece(null, "This profile picks up obligations and additional bindings from ", null).addStyle("font-weight:bold"));
|
||||
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, iu);
|
||||
if (sd == null) {
|
||||
c.addPiece(gen.new Piece(null, iu, null).addStyle("font-weight:bold"));
|
||||
} else if (sd.hasWebPath()) {
|
||||
c.addPiece(gen.new Piece(sd.getWebPath(), sd.present(), null).addStyle("font-weight:bold"));
|
||||
} else {
|
||||
c.addPiece(gen.new Piece(iu, sd.present(), null).addStyle("font-weight:bold"));
|
||||
}
|
||||
}
|
||||
|
||||
if (profile.getKind() == StructureDefinitionKind.LOGICAL) {
|
||||
if (!c.getPieces().isEmpty()) { c.addPiece(gen.new Piece("br")); }
|
||||
if (ToolingExtensions.readBoolExtension(profile, ToolingExtensions.EXT_LOGICAL_TARGET)) {
|
||||
c.addPiece(gen.new Piece(null, "This logical model can be the target of a reference", null).addStyle("font-weight:bold"));
|
||||
} else {
|
||||
c.addPiece(gen.new Piece(null, "This logical model cannot be the target of a reference", null).addStyle("font-weight:bold"));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (definition != null) {
|
||||
ElementDefinitionBindingComponent binding = null;
|
||||
if (valueDefn != null && valueDefn.hasBinding() && !valueDefn.getBinding().isEmpty())
|
||||
|
@ -1422,6 +1380,13 @@ public class StructureDefinitionRenderer extends ResourceRenderer {
|
|||
c.getPieces().add(checkForNoChange(ex, gen.new Piece(null, buildJson(ex.getValue()), null).addStyle("color: darkgreen")));
|
||||
}
|
||||
}
|
||||
|
||||
ObligationsRenderer obr = new ObligationsRenderer(corePath, profile, definition.getPath(), rc, null, this);
|
||||
if (definition.hasExtension(ToolingExtensions.EXT_OBLIGATION)) {
|
||||
obr.seeObligations(definition.getExtensionsByUrl(ToolingExtensions.EXT_OBLIGATION));
|
||||
}
|
||||
obr.renderTable(gen, c);
|
||||
|
||||
if (definition.hasMaxLength() && definition.getMaxLength()!=0) {
|
||||
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")));
|
||||
|
|
|
@ -139,6 +139,8 @@ public class ToolingExtensions {
|
|||
public static final String EXT_JSON_NAME = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-json-name";
|
||||
public static final String EXT_BINDING_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-binding-style";
|
||||
public static final String EXT_EXTENSION_STYLE = "http://hl7.org/fhir/tools/StructureDefinition/elementdefinition-extension-style";
|
||||
public static final String EXT_LOGICAL_TARGET = "http://hl7.org/fhir/tools/StructureDefinition/logical-target";
|
||||
public static final String EXT_PROFILE_MAPPING = "http://hl7.org/fhir/tools/StructureDefinition/profile-mapping";
|
||||
|
||||
// validated
|
||||
// private static final String EXT_OID = "http://hl7.org/fhir/StructureDefinition/valueset-oid";
|
||||
|
@ -239,6 +241,7 @@ public class ToolingExtensions {
|
|||
public static final String EXT_MAPPING_TGTCARD = "http://hl7.org/fhir/tools/StructureDefinition/conceptmap-target-cardinality";
|
||||
|
||||
public static final String WEB_EXTENSION_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/format-extensions.html#extension-related-extensions";
|
||||
public static final String WEB_BINDING_STYLE = "http://build.fhir.org/ig/FHIR/fhir-tools-ig/StructureDefinition-binding-style.html";
|
||||
public static final String EXT_IGDEP_COMMENT = "http://hl7.org/fhir/tools/StructureDefinition/implementationguide-dependency-comment";
|
||||
public static final String EXT_XPATH_CONSTRAINT = "http://hl7.org/fhir/4.0/StructureDefinition/extension-ElementDefinition.constraint.xpath";
|
||||
public static final String EXT_OBLIGATION = "http://hl7.org/fhir/tools/StructureDefinition/obligation";
|
||||
|
|
Loading…
Reference in New Issue